[llvm] [GlobalIsel] Transform build_vector(binop(_, C), ...) -> binop(bv, constant bv) (PR #73577)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 27 14:28:17 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-aarch64

Author: Thorsten Schütt (tschuett)

<details>
<summary>Changes</summary>

test plan: ninja check-llvm-codegen

Port of https://github.com/llvm/llvm-project/pull/67358

The almost duplicated code is caused by the distinction of integers and floats.

Transforms a build vector of identically binops where the RHS is always a constant into a binop of two build vectors. The second is a constant build vector. Instead of O(n) binops, we take one vector binop and gain one constant build vector. The constant build vector might trigger other combines.

Differences: constants are not immediates but G_CONSTANT resp. G_FCONSTANT. Thus the hit rate may be higher, e.g., the constant might be hidden behind a COPY.

Credits: @<!-- -->preames

---

Patch is 279.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/73577.diff


18 Files Affected:

- (modified) llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (+3) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h (+54) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (+5) 
- (modified) llvm/include/llvm/Target/GlobalISel/Combine.td (+7-1) 
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+85) 
- (modified) llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (+11) 
- (added) llvm/test/CodeGen/AArch64/GlobalISel/combine-build-vector-to-binop.mir (+236) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/inline-memset.mir (+87-79) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i32.ll (+90-180) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll (+478-942) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i32.ll (+82-164) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll (+470-926) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/urem.i32.ll (+31-62) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/urem.i64.ll (+230-398) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.log.ll (+214-129) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.log10.ll (+214-129) 
- (modified) llvm/test/CodeGen/AMDGPU/v_pack.ll (+3-3) 
- (modified) llvm/test/CodeGen/AMDGPU/v_sat_pk_u8_i16.ll (+40-33) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index ba72a3b71ffd70b..1eb9f5816bdb036 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -812,6 +812,9 @@ class CombinerHelper {
   // Given a binop \p MI, commute operands 1 and 2.
   void applyCommuteBinOpOperands(MachineInstr &MI);
 
+  /// Transform build_vector (binop(_, C), ...) -> binop(bv, constant bv)
+  bool matchBuildVectorToBinOp(MachineInstr &MI, BuildFnTy &MatchInfo);
+
 private:
   /// Checks for legality of an indexed variant of \p LdSt.
   bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 6ab1d4550c51ca9..26742496327e912 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -558,6 +558,60 @@ class GVecReduce : public GenericMachineInstr {
   }
 };
 
+// Represents an integer binary operation.
+class GIBinOp : public GenericMachineInstr {
+public:
+  Register getLHSReg() const { return getReg(1); }
+  Register getRHSReg() const { return getReg(2); }
+
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    case TargetOpcode::G_ADD:
+    case TargetOpcode::G_SUB:
+    case TargetOpcode::G_MUL:
+    case TargetOpcode::G_SDIV:
+    case TargetOpcode::G_UDIV:
+    case TargetOpcode::G_SREM:
+    case TargetOpcode::G_UREM:
+    case TargetOpcode::G_AND:
+    case TargetOpcode::G_OR:
+    case TargetOpcode::G_XOR:
+    case TargetOpcode::G_SMIN:
+    case TargetOpcode::G_SMAX:
+    case TargetOpcode::G_UMIN:
+    case TargetOpcode::G_UMAX:
+      return true;
+    default:
+      return false;
+    }
+  };
+};
+
+// Represents a floating point binary operation.
+class GFBinOp : public GenericMachineInstr {
+public:
+  Register getLHSReg() const { return getReg(1); }
+  Register getRHSReg() const { return getReg(2); }
+
+  static bool classof(const MachineInstr *MI) {
+    switch (MI->getOpcode()) {
+    case TargetOpcode::G_FMINNUM:
+    case TargetOpcode::G_FMAXNUM:
+    case TargetOpcode::G_FMINNUM_IEEE:
+    case TargetOpcode::G_FMAXNUM_IEEE:
+    case TargetOpcode::G_FMINIMUM:
+    case TargetOpcode::G_FMAXIMUM:
+    case TargetOpcode::G_FADD:
+    case TargetOpcode::G_FSUB:
+    case TargetOpcode::G_FMUL:
+    case TargetOpcode::G_FDIV:
+    case TargetOpcode::G_FPOW:
+      return true;
+    default:
+      return false;
+    }
+  };
+};
 
 } // namespace llvm
 
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index e0101a5ac1ca804..94da5f5e0d14b21 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1061,6 +1061,11 @@ class MachineIRBuilder {
   MachineInstrBuilder buildBuildVectorConstant(const DstOp &Res,
                                                ArrayRef<APInt> Ops);
 
+  /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ... where each OpN is
+  /// built with G_FCONSTANT.
+  MachineInstrBuilder buildBuildVectorConstant(const DstOp &Res,
+                                               ArrayRef<APFloat> Ops);
+
   /// Build and insert \p Res = G_BUILD_VECTOR with \p Src replicated to fill
   /// the number of elements
   MachineInstrBuilder buildSplatVector(const DstOp &Res,
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 9a84ab80157f35f..a56327ff49696b5 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1236,6 +1236,12 @@ def select_to_minmax: GICombineRule<
          [{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]),
   (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
 
+def build_vector_to_binop : GICombineRule<
+  (defs root:$root, build_fn_matchinfo:$matchinfo),
+  (match (wip_match_opcode G_BUILD_VECTOR):$root,
+        [{ return Helper.matchBuildVectorToBinOp(*${root}, ${matchinfo}); }]),
+  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
 // FIXME: These should use the custom predicate feature once it lands.
 def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
                                      undef_to_negative_one,
@@ -1309,7 +1315,7 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
     intdiv_combines, mulh_combines, redundant_neg_operands,
     and_or_disjoint_mask, fma_combines, fold_binop_into_select,
     sub_add_reg, select_to_minmax, redundant_binop_in_equality,
-    fsub_to_fneg, commute_constant_to_rhs]>;
+    fsub_to_fneg, commute_constant_to_rhs, build_vector_to_binop]>;
 
 // A combine group used to for prelegalizer combiners at -O0. The combines in
 // this group have been selected based on experiments to balance code size and
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index c2a7c2d01188129..a0b2e86c6148cff 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -6224,3 +6224,88 @@ void CombinerHelper::applyCommuteBinOpOperands(MachineInstr &MI) {
   MI.getOperand(2).setReg(LHSReg);
   Observer.changedInstr(MI);
 }
+
+// Transform build_vector of binop(_,C) -> binop(BV, constant BV).
+bool CombinerHelper::matchBuildVectorToBinOp(MachineInstr &MI,
+                                             BuildFnTy &MatchInfo) {
+  GBuildVector *BuildVector = cast<GBuildVector>(&MI);
+  Register Dst = BuildVector->getReg(0);
+
+  unsigned NumOfSources = BuildVector->getNumSources();
+  if (NumOfSources == 1)
+    return false;
+
+  LLT ElementTy = MRI.getType(BuildVector->getSourceReg(0));
+  LLT BVTy = MRI.getType(BuildVector->getReg(0));
+
+  MachineInstr *FirstDef = MRI.getVRegDef(BuildVector->getSourceReg(0));
+  const unsigned Opcode = FirstDef->getOpcode();
+  SmallVector<Register> LHS;
+
+  if (isa<GIBinOp>(FirstDef)) {
+    SmallVector<APInt> RHS;
+
+    // Collect registers and constants and check for non-conformance.
+    for (unsigned I = 0; I < NumOfSources; ++I) {
+      // Check for integer binop of the same kind.
+      GIBinOp *BinOp = getOpcodeDef<GIBinOp>(BuildVector->getSourceReg(I), MRI);
+      if (!BinOp || BinOp->getOpcode() != Opcode)
+        return false;
+      // Check for constant on rhs.
+      auto IConstant =
+          getIConstantVRegValWithLookThrough(BinOp->getRHSReg(), MRI);
+      if (!IConstant)
+        return false;
+      LHS.push_back(BinOp->getLHSReg());
+      RHS.push_back(IConstant->Value);
+    }
+
+    if (!isLegalOrBeforeLegalizer({Opcode, {BVTy, ElementTy}}))
+      return false;
+
+    // Binop of build_vector, integer constant build_vector.
+    MatchInfo = [=](MachineIRBuilder &B) {
+      B.setInstrAndDebugLoc(*BuildVector);
+      Register First = MRI.createGenericVirtualRegister(BVTy);
+      Register Second = MRI.createGenericVirtualRegister(BVTy);
+      B.buildBuildVector(First, LHS);
+      B.buildBuildVectorConstant(Second, RHS);
+      B.buildInstr(Opcode, {Dst}, {First, Second}); // DEBUG: did not happen
+    };
+    return true;
+  } else if (isa<GFBinOp>(FirstDef)) {
+    SmallVector<APFloat> RHS;
+
+    // Collect registers and constants and check for non-conformance.
+    for (unsigned I = 0; I < NumOfSources; ++I) {
+      // Check for float binop of the same kind.
+      GFBinOp *BinOp = getOpcodeDef<GFBinOp>(BuildVector->getSourceReg(I), MRI);
+      if (!BinOp || BinOp->getOpcode() != Opcode)
+        return false;
+      // Check for float constant on rhs.
+      auto FConstant =
+          getFConstantVRegValWithLookThrough(BinOp->getRHSReg(), MRI);
+      if (!FConstant)
+        return false;
+      LHS.push_back(BinOp->getLHSReg());
+      RHS.push_back(FConstant->Value);
+    }
+
+    if (!isLegalOrBeforeLegalizer({Opcode, {BVTy, ElementTy}}))
+      return false;
+
+    // Binop of build_vector, floating point constant build_vector.
+    MatchInfo = [=](MachineIRBuilder &B) {
+      B.setInstrAndDebugLoc(*BuildVector);
+      Register First = MRI.createGenericVirtualRegister(BVTy);
+      Register Second = MRI.createGenericVirtualRegister(BVTy);
+      B.buildBuildVector(First, LHS);
+      B.buildBuildVectorConstant(Second, RHS);
+      B.buildInstr(Opcode, {Dst}, {First, Second});
+    };
+    return true;
+  } else {
+    // Not a binop.
+    return false;
+  }
+}
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 80e9c08e850b683..89d5d73a2394a39 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -700,6 +700,17 @@ MachineIRBuilder::buildBuildVectorConstant(const DstOp &Res,
   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
 }
 
+MachineInstrBuilder
+MachineIRBuilder::buildBuildVectorConstant(const DstOp &Res,
+                                           ArrayRef<APFloat> Ops) {
+  SmallVector<SrcOp> TmpVec;
+  TmpVec.reserve(Ops.size());
+  LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
+  for (const auto &Op : Ops)
+    TmpVec.push_back(buildFConstant(EltTy, Op));
+  return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
+}
+
 MachineInstrBuilder MachineIRBuilder::buildSplatVector(const DstOp &Res,
                                                        const SrcOp &Src) {
   SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-build-vector-to-binop.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-build-vector-to-binop.mir
new file mode 100644
index 000000000000000..ea69bd4a9be2d5f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-build-vector-to-binop.mir
@@ -0,0 +1,236 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -o - -mtriple=aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s | FileCheck %s
+
+---
+name:            build_vector_success_add
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK-LABEL: name: build_vector_success_add
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 10
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32)
+    ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C1]](s32)
+    ; CHECK-NEXT: %bv:_(<2 x s32>) = G_ADD [[BUILD_VECTOR]], [[BUILD_VECTOR1]]
+    ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), [[COPY]](s32)
+    ; CHECK-NEXT: %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), [[COPY1]](s32)
+    ; CHECK-NEXT: $w0 = COPY %extract(s32)
+    ; CHECK-NEXT: $w1 = COPY %extract2(s32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = COPY $w1
+    %2:_(s32) = G_CONSTANT i32 10
+    %3:_(s32) = G_CONSTANT i32 1
+    %4:_(s32) = G_ADD %0, %2
+    %5:_(s32) = G_ADD %1, %3
+    %bv:_(<2 x s32>) = G_BUILD_VECTOR %4(s32), %5(s32)
+    %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %0(s32)
+    %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %1(s32)
+    $w0 = COPY %extract(s32)
+    $w1 = COPY %extract2(s32)
+    RET_ReallyLR implicit $w0
+
+...
+---
+name:            build_vector_failure_mixed
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK-LABEL: name: build_vector_failure_mixed
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
+    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C]]
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY1]], [[C1]]
+    ; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR [[ADD]](s32), [[SUB]](s32)
+    ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), [[COPY]](s32)
+    ; CHECK-NEXT: %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), [[COPY1]](s32)
+    ; CHECK-NEXT: $w0 = COPY %extract(s32)
+    ; CHECK-NEXT: $w1 = COPY %extract2(s32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = COPY $w1
+    %2:_(s32) = G_CONSTANT i32 5
+    %3:_(s32) = G_CONSTANT i32 11
+    %4:_(s32) = G_ADD %0, %2
+    %5:_(s32) = G_SUB %1, %3
+    %bv:_(<2 x s32>) = G_BUILD_VECTOR %4(s32), %5(s32)
+    %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %0(s32)
+    %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %1(s32)
+    $w0 = COPY %extract(s32)
+    $w1 = COPY %extract2(s32)
+    RET_ReallyLR implicit $w0
+
+...
+---
+name:            build_vector_success_sub
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK-LABEL: name: build_vector_success_sub
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 10
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
+    ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C1]](s32), [[C2]](s32), [[C3]](s32)
+    ; CHECK-NEXT: %bv:_(<4 x s32>) = G_SUB [[BUILD_VECTOR]], [[BUILD_VECTOR1]]
+    ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY3]](s32)
+    ; CHECK-NEXT: %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY]](s32)
+    ; CHECK-NEXT: $w0 = COPY %extract(s32)
+    ; CHECK-NEXT: $w1 = COPY %extract2(s32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = COPY $w1
+    %2:_(s32) = COPY $w2
+    %3:_(s32) = COPY $w3
+    %4:_(s32) = G_CONSTANT i32 10
+    %5:_(s32) = G_CONSTANT i32 1
+    %6:_(s32) = G_CONSTANT i32 2
+    %7:_(s32) = G_CONSTANT i32 3
+    %8:_(s32) = G_SUB %0, %4
+    %9:_(s32) = G_SUB %1, %5
+    %10:_(s32) = G_SUB %2, %6
+    %11:_(s32) = G_SUB %3, %7
+    %bv:_(<4 x s32>) = G_BUILD_VECTOR %8(s32), %9(s32), %10(s32), %11(s32)
+    %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %3(s32)
+    %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %0(s32)
+    $w0 = COPY %extract(s32)
+    $w1 = COPY %extract2(s32)
+    RET_ReallyLR implicit $w0
+
+
+...
+---
+name:            build_vector_success_fadd
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK-LABEL: name: build_vector_success_fadd
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+01
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.100000e+01
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.200000e+01
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.400000e+01
+    ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
+    ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C1]](s32), [[C2]](s32), [[C3]](s32)
+    ; CHECK-NEXT: %bv:_(<4 x s32>) = G_FADD [[BUILD_VECTOR]], [[BUILD_VECTOR1]]
+    ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY3]](s32)
+    ; CHECK-NEXT: %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY]](s32)
+    ; CHECK-NEXT: $w0 = COPY %extract(s32)
+    ; CHECK-NEXT: $w1 = COPY %extract2(s32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = COPY $w1
+    %2:_(s32) = COPY $w2
+    %3:_(s32) = COPY $w3
+    %4:_(s32) = G_FCONSTANT float 10.000000e+00
+    %5:_(s32) = G_FCONSTANT float 11.000000e+00
+    %6:_(s32) = G_FCONSTANT float 12.000000e+00
+    %7:_(s32) = G_FCONSTANT float 14.000000e+00
+    %8:_(s32) = G_FADD %0, %4
+    %9:_(s32) = G_FADD %1, %5
+    %10:_(s32) = G_FADD %2, %6
+    %11:_(s32) = G_FADD %3, %7
+    %bv:_(<4 x s32>) = G_BUILD_VECTOR %8(s32), %9(s32), %10(s32), %11(s32)
+    %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %3(s32)
+    %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %0(s32)
+    $w0 = COPY %extract(s32)
+    $w1 = COPY %extract2(s32)
+    RET_ReallyLR implicit $w0
+
+...
+---
+name:            build_vector_failed_no_constant_for_you
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK-LABEL: name: build_vector_failed_no_constant_for_you
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+01
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.100000e+01
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.200000e+01
+    ; CHECK-NEXT: [[FADD:%[0-9]+]]:_(s32) = G_FADD [[COPY]], [[C]]
+    ; CHECK-NEXT: [[FADD1:%[0-9]+]]:_(s32) = G_FADD [[COPY1]], [[C1]]
+    ; CHECK-NEXT: [[FADD2:%[0-9]+]]:_(s32) = G_FADD [[COPY2]], [[C2]]
+    ; CHECK-NEXT: [[FADD3:%[0-9]+]]:_(s32) = G_FADD [[COPY3]], [[COPY]]
+    ; CHECK-NEXT: %bv:_(<4 x s32>) = G_BUILD_VECTOR [[FADD]](s32), [[FADD1]](s32), [[FADD2]](s32), [[FADD3]](s32)
+    ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY3]](s32)
+    ; CHECK-NEXT: %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY]](s32)
+    ; CHECK-NEXT: $w0 = COPY %extract(s32)
+    ; CHECK-NEXT: $w1 = COPY %extract2(s32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = COPY $w1
+    %2:_(s32) = COPY $w2
+    %3:_(s32) = COPY $w3
+    %4:_(s32) = G_FCONSTANT float 10.000000e+00
+    %5:_(s32) = G_FCONSTANT float 11.000000e+00
+    %6:_(s32) = G_FCONSTANT float 12.000000e+00
+    %8:_(s32) = G_FADD %0, %4
+    %9:_(s32) = G_FADD %1, %5
+    %10:_(s32) = G_FADD %2, %6
+    %11:_(s32) = G_FADD %3, %0
+    %bv:_(<4 x s32>) = G_BUILD_VECTOR %8(s32), %9(s32), %10(s32), %11(s32)
+    %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %3(s32)
+    %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %0(s32)
+    $w0 = COPY %extract(s32)
+    $w1 = COPY %extract2(s32)
+    RET_ReallyLR implicit $w0
+
+...
+---
+name:            build_vector_failed_no_binop
+liveins:
+body:             |
+  bb.0:
+
+    ; CHECK-LABEL: name: build_vector_failed_no_binop
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+    ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s32) = G_FNEG [[COPY]]
+    ; CHECK-NEXT: [[FNEG1:%[0-9]+]]:_(s32) = G_FNEG [[COPY1]]
+    ; CHECK-NEXT: [[FNEG2:%[0-9]+]]:_(s32) = G_FNEG [[COPY2]]
+    ; CHECK-NEXT: [[FNEG3:%[0-9]+]]:_(s32) = G_FNEG [[COPY3]]
+    ; CHECK-NEXT: %bv:_(<4 x s32>) = G_BUILD_VECTOR [[FNEG]](s32), [[FNEG1]](s32), [[FNEG2]](s32), [[FNEG3]](s32)
+    ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY3]](s32)
+    ; CHECK-NEXT: %extract2:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), [[COPY]](s32)
+    ; CHECK-NEXT: $w0 = COPY %extract(s32)
+    ; CHECK-NEXT: $w1 = COPY %extract2(s32)
+    ; CHECK-NEXT: RET_ReallyLR implicit $w0
+    %0:_(s32) = COPY $w0
+    %1:_(s32) = COPY $w1
+    %2:_(s32) = COPY $w2
+    %3:_(s32) = COPY $w3
+    %8:_(s32) = G_FNEG %0
+    %9:_(s32) = G_FNEG %1
+    %10:_(s32) = G_FNEG %2
+    %11:_(s32) = G_FNEG %3
+    %bv:_(<4 x s32>) = G_BUILD_VECTOR %8(s32), %9(s32), %10(s32), %11(s32)
+    %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %3(s32)
+   ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/73577


More information about the llvm-commits mailing list