From 6b8e95423cd718b1131684eb55b64b81851df851 Mon Sep 17 00:00:00 2001 From: Sai Abhinay Anubola Date: Wed, 12 Mar 2025 12:15:50 +0530 Subject: [PATCH 1/2] [NFC] Refactor G_BUILD_VECTOR combines --- llvm/lib/Target/AIE/AIECombine.td | 30 ++-- llvm/lib/Target/AIE/AIECombinerHelper.cpp | 200 +++++++++++----------- llvm/lib/Target/AIE/AIECombinerHelper.h | 28 +-- 3 files changed, 111 insertions(+), 147 deletions(-) diff --git a/llvm/lib/Target/AIE/AIECombine.td b/llvm/lib/Target/AIE/AIECombine.td index c6b4cb22333f..f250a67690e6 100644 --- a/llvm/lib/Target/AIE/AIECombine.td +++ b/llvm/lib/Target/AIE/AIECombine.td @@ -34,20 +34,11 @@ def combine_extract_vector_elt_and_zsa_ext : GICombineRule< (apply [{ applyExtractVecEltAndExt(*${root}, MRI, B, ${matchinfo}); }]) >; -def combine_splat_vector_matchdata: GIDefMatchData<"std::pair">; -def combine_splat_vector : GICombineRule< - (defs root:$root, combine_splat_vector_matchdata:$matchinfo), - (match (wip_match_opcode G_BUILD_VECTOR): $root, - [{ return matchSplatVector(*${root}, MRI, ${matchinfo}); }]), - (apply [{ applySplatVector(*${root}, MRI, B, ${matchinfo}); }]) ->; - -def combine_single_diff_build_vector_matchdata: GIDefMatchData<"AIESingleDiffLaneBuildVectorMatchData">; -def combine_single_diff_build_vector : GICombineRule< - (defs root:$root, combine_single_diff_build_vector_matchdata:$matchinfo), +def combine_build_vector : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), (match (wip_match_opcode G_BUILD_VECTOR): $root, - [{ return matchSingleDiffLaneBuildVector(*${root}, MRI, ${matchinfo}); }]), - (apply [{ applySingleDiffLaneBuildVector(*${root}, MRI, B, ${matchinfo}); }]) + [{ return matchBuildVectorPatterns(*${root}, MRI, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }]) >; def combine_pad_vector_matchdata: GIDefMatchData<"Register">; @@ -72,11 +63,12 @@ def combine_unpad_vector : GICombineRule< (apply [{ applyUnpadVector(*${root}, MRI, B); }]) >; +def combine_vector_broadcast_matchdata: GIDefMatchData<"std::pair">; def combine_vector_broadcast : GICombineRule< - (defs root:$root, combine_splat_vector_matchdata:$matchinfo), + (defs root:$root, combine_vector_broadcast_matchdata:$matchinfo), (match (wip_match_opcode G_SHUFFLE_VECTOR): $root, [{ return matchBroadcastElement(*${root}, MRI, ${matchinfo}); }]), - (apply [{ applySplatVector(*${root}, MRI, B, ${matchinfo}); }])>; + (apply [{ applyBroadcastElement(*${root}, MRI, B, ${matchinfo}); }])>; def combine_vector_shuffle_broadcast : GICombineRule< (defs root:$root, build_fn_matchinfo:$matchinfo), @@ -107,8 +99,7 @@ def AIE2PreLegalizerCombiner all_combines, combine_S20NarrowingOpt, combine_globalval_offset, combine_extract_vector_elt_and_zsa_ext, - combine_splat_vector, combine_concat_to_pad_vector, - combine_single_diff_build_vector]> { + combine_build_vector, combine_concat_to_pad_vector]> { let CombineAllMethodName = "tryCombineAllImpl"; } @@ -119,11 +110,10 @@ def AIE2PPreLegalizerCombiner all_combines, combine_S20NarrowingOpt, combine_globalval_offset, combine_extract_vector_elt_and_zsa_ext, - combine_splat_vector, combine_vector_broadcast, + combine_build_vector, combine_vector_broadcast, combine_concat_to_pad_vector, combine_vector_shuffle_vsel, - combine_vector_shuffle_broadcast, - combine_single_diff_build_vector]> { + combine_vector_shuffle_broadcast]> { let CombineAllMethodName = "tryCombineAllImpl"; } diff --git a/llvm/lib/Target/AIE/AIECombinerHelper.cpp b/llvm/lib/Target/AIE/AIECombinerHelper.cpp index e7e03d0faa84..1a6cbac76524 100644 --- a/llvm/lib/Target/AIE/AIECombinerHelper.cpp +++ b/llvm/lib/Target/AIE/AIECombinerHelper.cpp @@ -1133,44 +1133,6 @@ void llvm::applyExtractVecEltAndExt( MI.eraseFromParent(); MatchMI->eraseFromParent(); } - -// Match something like: -// %0:_(<32 x s16>) = G_BUILD_VECTOR %1:_(s16), ... x32 -// -// To turn it into -// %0:_(<32 x s16>) = G_AIE_BROADCAST_VECTOR %1:_(s16) -bool llvm::matchSplatVector(MachineInstr &MI, MachineRegisterInfo &MRI, - std::pair &MatchInfo) { - - assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR && - "Expected a G_BUILD_VECTOR"); - - const Register DstVecReg = MI.getOperand(0).getReg(); - const LLT DstVecTy = MRI.getType(DstVecReg); - const unsigned DstVecSize = DstVecTy.getSizeInBits(); - - switch (DstVecSize) { - case 256: - case 512: - case 1024: - case 2048: - break; - default: - // unimplemented - return false; - } - - const unsigned NumOps = MI.getNumOperands(); - const MachineOperand FirstOp = MI.getOperand(1); - for (unsigned i = 2; i < NumOps; i++) { - if (!MI.getOperand(i).isIdenticalTo(FirstOp)) { - return false; - } - } - MatchInfo = std::make_pair(DstVecReg, FirstOp.getReg()); - return true; -} - static void buildBroadcastVector(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register SrcReg, Register DstVecReg) { const AIEBaseInstrInfo &AIETII = (const AIEBaseInstrInfo &)B.getTII(); @@ -1230,101 +1192,121 @@ static void buildBroadcastVector(MachineIRBuilder &B, MachineRegisterInfo &MRI, } } -bool llvm::applySplatVector(MachineInstr &MI, MachineRegisterInfo &MRI, - MachineIRBuilder &B, - std::pair &MatchInfo) { - B.setInstrAndDebugLoc(MI); - auto [DstVecReg, SrcReg] = MatchInfo; - buildBroadcastVector(B, MRI, SrcReg, DstVecReg); - MI.eraseFromParent(); +// This helper attempts to match a single-different-lane splat vector pattern. +// That pattern is a nearly-splat vector (one repeated register) but with one +// lane "differing" from the rest. +static bool matchSingleDiffSplatVector( + DenseMap> UniqueRegs, + Register DstVecReg, MachineRegisterInfo &MRI, BuildFnTy &MatchInfo) { + Register SplatReg, DifferingReg; + unsigned DifferingIndex; + + // Identify splat (multiple uses) and differing (single use) registers + for (const auto &[Reg, RegInfo] : UniqueRegs) { + if (RegInfo.first == 1) { + DifferingReg = Reg; + DifferingIndex = RegInfo.second; + } else { + SplatReg = Reg; + } + } + // Validate that one register was used exactly once + if (!DifferingReg.isValid() || !SplatReg.isValid()) + return false; + + // Ignore G_IMPLICIT_DEF to avoid conflicts with \fn matchBroadcastElement + const MachineInstr *SplatRegDef = getDefIgnoringCopies(SplatReg, MRI); + if (!SplatRegDef || SplatRegDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) + return false; + + // If we match, build a function-lambda that does the transformation: + // 1) Create a broadcast of the SplatReg into the destination vector. + // 2) Insert the differing lane at DifferingIndex. + MatchInfo = [=, &MRI](MachineIRBuilder &B) { + const LLT DstVecRegTy = MRI.getType(DstVecReg); + const Register BcstDstReg = MRI.createGenericVirtualRegister(DstVecRegTy); + const LLT S32 = LLT::scalar(32); + + buildBroadcastVector(B, MRI, SplatReg, BcstDstReg); + const Register IdxReg = B.buildConstant(S32, DifferingIndex).getReg(0); + B.buildInsertVectorElement(DstVecReg, BcstDstReg, DifferingReg, IdxReg); + }; return true; } // Match something like: +// %0:_(<32 x s16>) = G_BUILD_VECTOR %1:_(s16), ... x32 +// +// To turn it into +// %0:_(<32 x s16>) = G_AIE_BROADCAST_VECTOR %1:_(s16) +// +// And this: // %0:_(<32 x s16>) = G_BUILD_VECTOR %2:(s16), %2:(s16), %1:(s16) ... x32 // // To turn it into // %3:_(<32 x s16>) = G_AIE_BROADCAST_VECTOR %2:_(s16) // %0:(<32 x s16>) = G_AIE_INSERT_VECTOR_ELT %3:(<32 x s16>), %1:_(s16), 2 -bool llvm::matchSingleDiffLaneBuildVector( - MachineInstr &MI, MachineRegisterInfo &MRI, - AIESingleDiffLaneBuildVectorMatchData &MatchInfo) { - assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR && - "Expected a G_BUILD_VECTOR"); +static bool matchSplatVector(MachineInstr &MI, MachineRegisterInfo &MRI, + BuildFnTy &MatchInfo) { - const Register DstVecReg = MI.getOperand(0).getReg(); - const LLT DstVecTy = MRI.getType(DstVecReg); - const unsigned DstVecSize = DstVecTy.getSizeInBits(); - - switch (DstVecSize) { - case 256: - case 512: - case 1024: - case 2048: - break; - default: - // unimplemented - return false; - } // DenseMap to hold unique registers and their (count, last index) DenseMap> UniqueRegs; + const Register DstVecReg = MI.getOperand(0).getReg(); const unsigned NumOps = MI.getNumOperands(); + for (unsigned i = 1; i < NumOps; i++) { const Register OpReg = MI.getOperand(i).getReg(); auto &RegInfo = UniqueRegs[OpReg]; RegInfo.first += 1; RegInfo.second = i - 1; - if (UniqueRegs.size() > 2) return false; } - // Ensure exactly 2 unique registers to match the single differing lane build - // vector pattern. More than 2 registers won't match; 1 unique register would - // be a splat vector combine - if (UniqueRegs.size() != 2) - return false; - Register SplatReg, DifferingReg; - unsigned DifferingIndex; + switch (UniqueRegs.size()) { + case 1: { + // Pure splat as there is only one unique register. - // Identify splat (multiple uses) and differing (single use) registers - for (const auto &[Reg, RegInfo] : UniqueRegs) { - if (RegInfo.first == 1) { - DifferingReg = Reg; - DifferingIndex = RegInfo.second; - } else { - SplatReg = Reg; - } + auto It = UniqueRegs.begin(); + Register SplatReg = It->first; + // Build a lambda that creates a broadcast of SplatReg into DstVecReg. + MatchInfo = [=, &MRI](MachineIRBuilder &B) { + buildBroadcastVector(B, MRI, SplatReg, DstVecReg); + }; + return true; } - // Validate that one register was used exactly once - if (!DifferingReg.isValid() || !SplatReg.isValid()) + case 2: + // Check for single differing lane splat, as there are 2 unique registers. + return matchSingleDiffSplatVector(UniqueRegs, DstVecReg, MRI, MatchInfo); + default: return false; + } +} - // Ignore G_IMPLICIT_DEF to avoid conflicts with \fn matchBroadcastElement - const MachineInstr *SplatRegDef = getDefIgnoringCopies(SplatReg, MRI); - if (!SplatRegDef || SplatRegDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) - return false; +bool llvm::matchBuildVectorPatterns(MachineInstr &MI, MachineRegisterInfo &MRI, + BuildFnTy &MatchInfo) { - MatchInfo = {DstVecReg, SplatReg, DifferingReg, DifferingIndex}; - return true; -} + assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR && + "Expected a G_BUILD_VECTOR"); -bool llvm::applySingleDiffLaneBuildVector( - MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, - AIESingleDiffLaneBuildVectorMatchData &MatchInfo) { - B.setInstrAndDebugLoc(MI); - const Register DstVecReg = MatchInfo.DstVecReg; - const LLT DstVecRegTy = MRI.getType(DstVecReg); - const Register BcstDstReg = MRI.createGenericVirtualRegister(DstVecRegTy); - const LLT S32 = LLT::scalar(32); + const Register DstVecReg = MI.getOperand(0).getReg(); + const LLT DstVecTy = MRI.getType(DstVecReg); + const unsigned DstVecSize = DstVecTy.getSizeInBits(); - buildBroadcastVector(B, MRI, MatchInfo.SplatReg, BcstDstReg); - const Register IdxReg = - B.buildConstant(S32, MatchInfo.DifferingIndex).getReg(0); - B.buildInsertVectorElement(DstVecReg, BcstDstReg, MatchInfo.DifferingReg, - IdxReg); - MI.eraseFromParent(); - return true; + switch (DstVecSize) { + case 256: + case 512: + case 1024: + case 2048: + break; + default: + // unimplemented + return false; + } + if (matchSplatVector(MI, MRI, MatchInfo)) { + return true; + } + return false; } // Match something like: @@ -1903,6 +1885,16 @@ bool llvm::matchBroadcastElement(MachineInstr &MI, MachineRegisterInfo &MRI, return true; } +bool llvm::applyBroadcastElement(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &B, + std::pair &MatchInfo) { + B.setInstrAndDebugLoc(MI); + auto [DstVecReg, SrcReg] = MatchInfo; + buildBroadcastVector(B, MRI, SrcReg, DstVecReg); + MI.eraseFromParent(); + return true; +} + static void buildUnmergeVector(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register DstReg, Register SrcReg, unsigned NumSubVectors, unsigned SubIdx) { diff --git a/llvm/lib/Target/AIE/AIECombinerHelper.h b/llvm/lib/Target/AIE/AIECombinerHelper.h index abb0398fbf41..5c83a79bee8b 100644 --- a/llvm/lib/Target/AIE/AIECombinerHelper.h +++ b/llvm/lib/Target/AIE/AIECombinerHelper.h @@ -62,17 +62,6 @@ class MaskMatch { int Amplitude = 1; }; -struct AIESingleDiffLaneBuildVectorMatchData { - /// Destination register of G_BUILD_VECTOR - Register DstVecReg; - /// The repeated register - Register SplatReg; - /// Register for the differing element - Register DifferingReg; - /// Lane index of the single differing element - unsigned DifferingIndex; -}; - /// Look for any PtrAdd instruction that use the same base as \a MI that can be /// combined with it and stores it in \a MatchData /// \return true if an instruction is found @@ -101,6 +90,9 @@ bool matchGlobalValOffset(MachineInstr &MI, MachineRegisterInfo &MRI, /// idiom into G_AIE_BROADCAST bool matchBroadcastElement(MachineInstr &MI, MachineRegisterInfo &MRI, std::pair &MatchInfo); +bool applyBroadcastElement(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &B, + std::pair &MatchInfo); bool matchShuffleToBroadcast(MachineInstr &MI, MachineRegisterInfo &MRI, const AIEBaseInstrInfo &TII, BuildFnTy &MatchInfo); /// Combine G_SHUFFLE_VECTOR(G_BUILD_VECTOR (VAL, UNDEF, ...), mask<0,0,...>) @@ -186,18 +178,8 @@ void applyExtractVecEltAndExt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, std::pair &MatchInfo); -bool matchSplatVector(MachineInstr &MI, MachineRegisterInfo &MRI, - std::pair &MatchInfo); -bool applySplatVector(MachineInstr &MI, MachineRegisterInfo &MRI, - MachineIRBuilder &B, - std::pair &MatchInfo); - -bool matchSingleDiffLaneBuildVector( - MachineInstr &MI, MachineRegisterInfo &MRI, - AIESingleDiffLaneBuildVectorMatchData &MatchInfo); -bool applySingleDiffLaneBuildVector( - MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, - AIESingleDiffLaneBuildVectorMatchData &MatchInfo); +bool matchBuildVectorPatterns(MachineInstr &MI, MachineRegisterInfo &MRI, + BuildFnTy &MatchInfo); bool matchUnpadVector(MachineInstr &MI, MachineRegisterInfo &MRI, const AIEBaseInstrInfo &TII); From 0ca40b9b5d0a7f281b0528015a7773a9a82a1c02 Mon Sep 17 00:00:00 2001 From: Sai Abhinay Anubola Date: Wed, 12 Mar 2025 14:48:11 +0530 Subject: [PATCH 2/2] [AIE2][AIE2P] Support 128-bit G_BUILD_VECTOR combines --- llvm/lib/Target/AIE/AIECombinerHelper.cpp | 9 ++- ...egalizercombiner-single-diff-build-vec.mir | 60 ++++++++++++++ .../prelegalizercombiner-splat-vector.mir | 79 +++++++++++++++++++ 3 files changed, 144 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/AIE/AIECombinerHelper.cpp b/llvm/lib/Target/AIE/AIECombinerHelper.cpp index 1a6cbac76524..b0b1505161c5 100644 --- a/llvm/lib/Target/AIE/AIECombinerHelper.cpp +++ b/llvm/lib/Target/AIE/AIECombinerHelper.cpp @@ -1177,10 +1177,10 @@ static void buildBroadcastVector(MachineIRBuilder &B, MachineRegisterInfo &MRI, // Build the G_AIE_BROADCAST_VECTOR instruction for the 512-bit vector. B.buildInstr(AIETII.getGenericBroadcastVectorOpcode(), {DstVec512BitReg}, {SrcReg}); - if (DstVecSize == 256) { - const Register UnusedSubReg = MRI.createGenericVirtualRegister(DstVecTy); - // Unmerge the 512-bit vector into the 256-bit destination vector. - B.buildUnmerge({DstVecReg, UnusedSubReg}, DstVec512BitReg); + if (DstVecSize == 128 || DstVecSize == 256) { + // Unpad the 512-bit vector to form a 128/256-bit destination vector. + B.buildInstr(AIETII.getGenericUnpadVectorOpcode(), {DstVecReg}, + {DstVec512BitReg}); } else if (DstVecSize == 1024) { // Concatenate two 512-bit vectors to form a 1024-bit destination vector. B.buildConcatVectors({DstVecReg}, {DstVec512BitReg, DstVec512BitReg}); @@ -1294,6 +1294,7 @@ bool llvm::matchBuildVectorPatterns(MachineInstr &MI, MachineRegisterInfo &MRI, const unsigned DstVecSize = DstVecTy.getSizeInBits(); switch (DstVecSize) { + case 128: case 256: case 512: case 1024: diff --git a/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-single-diff-build-vec.mir b/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-single-diff-build-vec.mir index 1f6a20fd944b..9162687f0b2c 100644 --- a/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-single-diff-build-vec.mir +++ b/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-single-diff-build-vec.mir @@ -8,6 +8,66 @@ # RUN: llc -mtriple aie2 -run-pass=aie2-prelegalizer-combiner %s -verify-machineinstrs -o - | FileCheck %s # RUN: llc -mtriple aie2p -run-pass=aie2p-prelegalizer-combiner %s -verify-machineinstrs -o - | FileCheck %s +--- +name: test_build_vector_128_8bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_8bit_scl + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $r1 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<64 x s8>) = G_AIE_BROADCAST_VECTOR [[COPY]](s32) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<16 x s8>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<64 x s8>) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<16 x s8>) = G_INSERT_VECTOR_ELT [[AIE_UNPAD_VECTOR]], [[TRUNC]](s8), [[C]](s32) + ; CHECK-NEXT: $q0 = COPY [[IVEC]](<16 x s8>) + %0:_(s32) = COPY $r0 + %1:_(s8) = G_TRUNC %0:_(s32) + %2:_(s32) = COPY $r1 + %3:_(s8) = G_TRUNC %2:_(s32) + %4:_(<16 x s8>) = G_BUILD_VECTOR %1:_(s8), %1:_(s8), %3:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8) + $q0 = COPY %4:_(<16 x s8>) +... + +--- +name: test_build_vector_128_16bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_16bit_scl + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $r1 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<32 x s16>) = G_AIE_BROADCAST_VECTOR [[COPY]](s32) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<32 x s16>) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<8 x s16>) = G_INSERT_VECTOR_ELT [[AIE_UNPAD_VECTOR]], [[TRUNC]](s16), [[C]](s32) + ; CHECK-NEXT: $q0 = COPY [[IVEC]](<8 x s16>) + %0:_(s32) = COPY $r0 + %1:_(s16) = G_TRUNC %0:_(s32) + %2:_(s32) = COPY $r1 + %3:_(s16) = G_TRUNC %2:_(s32) + %4:_(<8 x s16>) = G_BUILD_VECTOR %3:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16) + $q0 = COPY %4:_(<8 x s16>) +... + +--- +name: test_build_vector_128_32bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_32bit_scl + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $r1 + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<16 x s32>) = G_AIE_BROADCAST_VECTOR [[COPY]](s32) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<16 x s32>) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<4 x s32>) = G_INSERT_VECTOR_ELT [[AIE_UNPAD_VECTOR]], [[COPY1]](s32), [[C]](s32) + ; CHECK-NEXT: $q0 = COPY [[IVEC]](<4 x s32>) + %1:_(s32) = COPY $r0 + %2:_(s32) = COPY $r1 + %3:_(<4 x s32>) = G_BUILD_VECTOR %1:_(s32), %2:_(s32), %1:_(s32), %1:_(s32) + $q0 = COPY %3:_(<4 x s32>) +... + --- name: test_build_vector_256_8bit_scl body: | diff --git a/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-splat-vector.mir b/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-splat-vector.mir index 2e29b9611627..2bb3aa9db394 100644 --- a/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-splat-vector.mir +++ b/llvm/test/CodeGen/AIE/GlobalISel/prelegalizercombiner-splat-vector.mir @@ -8,6 +8,85 @@ # RUN: llc -mtriple aie2 -run-pass=aie2-prelegalizer-combiner %s -verify-machineinstrs -o - | FileCheck %s # RUN: llc -mtriple aie2p -run-pass=aie2p-prelegalizer-combiner %s -verify-machineinstrs -o - | FileCheck %s +--- +name: test_build_vector_128_8bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_8bit_scl + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<64 x s8>) = G_AIE_BROADCAST_VECTOR [[COPY]](s32) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<16 x s8>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<64 x s8>) + ; CHECK-NEXT: $q0 = COPY [[AIE_UNPAD_VECTOR]](<16 x s8>) + %0:_(s32) = COPY $r0 + %1:_(s8) = G_TRUNC %0:_(s32) + %2:_(<16 x s8>) = G_BUILD_VECTOR %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8), %1:_(s8) + $q0 = COPY %2:_(<16 x s8>) +... + +--- +name: test_build_vector_128_16bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_16bit_scl + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<32 x s16>) = G_AIE_BROADCAST_VECTOR [[COPY]](s32) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<32 x s16>) + ; CHECK-NEXT: $q0 = COPY [[AIE_UNPAD_VECTOR]](<8 x s16>) + %0:_(s32) = COPY $r0 + %1:_(s16) = G_TRUNC %0:_(s32) + %2:_(<8 x s16>) = G_BUILD_VECTOR %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16), %1:_(s16) + $q0 = COPY %2:_(<8 x s16>) +... + +--- +name: test_build_vector_128_32bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_32bit_scl + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<16 x s32>) = G_AIE_BROADCAST_VECTOR [[COPY]](s32) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<16 x s32>) + ; CHECK-NEXT: $q0 = COPY [[AIE_UNPAD_VECTOR]](<4 x s32>) + %1:_(s32) = COPY $r0 + %2:_(<4 x s32>) = G_BUILD_VECTOR %1:_(s32), %1:_(s32), %1:_(s32), %1:_(s32) + $q0 = COPY %2:_(<4 x s32>) +... + +--- +name: test_build_vector_128_64bit_scl +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_64bit_scl + ; CHECK: [[DEF:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $l0 + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]](s64) + ; CHECK-NEXT: [[AIE_BROADCAST_VECTOR:%[0-9]+]]:_(<8 x s64>) = G_AIE_BROADCAST_VECTOR [[BITCAST]](<2 x s32>) + ; CHECK-NEXT: [[AIE_UNPAD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_AIE_UNPAD_VECTOR [[AIE_BROADCAST_VECTOR]](<8 x s64>) + ; CHECK-NEXT: G_STORE [[AIE_UNPAD_VECTOR]](<2 x s64>), [[DEF]](p0) :: (store (<2 x s64>)) + %0:_(p0) = G_IMPLICIT_DEF + %1:_(s64) = COPY $l0 + %2:_(<2 x s64>) = G_BUILD_VECTOR %1:_(s64), %1:_(s64) + G_STORE %2(<2 x s64>), %0(p0) :: (store (<2 x s64>)) +... + +# Invalid Vector for broadcast. +# As two of the elements in G_BUILD_VECTOR are different from others, +# ideally this should not be converted into G_AIE_BROADCAST_VECTOR +--- +name: test_build_vector_128_32bit_scl_invalid +body: | + bb.1.entry: + ; CHECK-LABEL: name: test_build_vector_128_32bit_scl_invalid + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $r0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $r1 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY1]](s32), [[COPY]](s32), [[COPY]](s32), [[COPY1]](s32) + ; CHECK-NEXT: $q0 = COPY [[BUILD_VECTOR]](<4 x s32>) + %1:_(s32) = COPY $r0 + %2:_(s32) = COPY $r1 + %3:_(<4 x s32>) = G_BUILD_VECTOR %2:_(s32), %1:_(s32), %1:_(s32), %2:_(s32) + $q0 = COPY %3:_(<4 x s32>) +... + --- name: test_build_vector_256_8bit_scl body: |