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

Amara Emerson via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 27 14:51:11 PST 2023


================
@@ -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;
----------------
aemerson wrote:

No need for else.

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


More information about the llvm-commits mailing list