[llvm] [GlobalISel] Combine [S,U]SUBO (PR #116489)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 16 09:54:40 PST 2024


================
@@ -84,3 +84,75 @@ bool CombinerHelper::matchMergeXAndZero(const MachineInstr &MI,
   };
   return true;
 }
+
+bool CombinerHelper::matchSuboCarryOut(const MachineInstr &MI,
+                                       BuildFnTy &MatchInfo) {
+  const GSubCarryOut *Subo = cast<GSubCarryOut>(&MI);
+
+  Register Dst = Subo->getReg(0);
+  Register LHS = Subo->getLHSReg();
+  Register RHS = Subo->getRHSReg();
+  Register Carry = Subo->getCarryOutReg();
+  LLT DstTy = MRI.getType(Dst);
+  LLT CarryTy = MRI.getType(Carry);
+
+  // Check legality before known bits.
+  if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy}}) ||
+      !isConstantLegalOrBeforeLegalizer(CarryTy))
+    return false;
+
+  if (Subo->isSigned()) {
+    // G_SSUBO
+    ConstantRange KBLHS = ConstantRange::fromKnownBits(KB->getKnownBits(LHS),
+                                                       /* IsSigned= */ true);
+    ConstantRange KBRHS = ConstantRange::fromKnownBits(KB->getKnownBits(RHS),
+                                                       /* IsSigned= */ true);
+    switch (KBLHS.signedSubMayOverflow(KBRHS)) {
+    case ConstantRange::OverflowResult::MayOverflow:
+      return false;
+    case ConstantRange::OverflowResult::NeverOverflows: {
+      MatchInfo = [=](MachineIRBuilder &B) {
+        B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
+        B.buildConstant(Carry, 0);
+      };
+      return true;
+    }
+    case ConstantRange::OverflowResult::AlwaysOverflowsLow:
+    case ConstantRange::OverflowResult::AlwaysOverflowsHigh: {
+      MatchInfo = [=](MachineIRBuilder &B) {
+        B.buildSub(Dst, LHS, RHS);
+        B.buildConstant(Carry, 1);
+      };
+      return true;
+    }
+    }
+    return false;
+  }
+
+  // G_USUBO
+  ConstantRange KBLHS = ConstantRange::fromKnownBits(KB->getKnownBits(LHS),
+                                                     /* IsSigned= */ false);
+  ConstantRange KBRHS = ConstantRange::fromKnownBits(KB->getKnownBits(RHS),
+                                                     /* IsSigned= */ false);
----------------
arsenm wrote:

Can avoid duplicating these in the signed / unsigned cases 

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


More information about the llvm-commits mailing list