[llvm] [CGP] Reconstruct borrow chain from icmp pattern for subtract-with-carry (PR #189018)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 4 14:36:21 PDT 2026
=?utf-8?q?Paweł?= Bylica <pawel at hepcolgum.band>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/189018 at github.com>
================
@@ -1762,6 +1763,68 @@ bool CodeGenPrepare::combineToUSubWithOverflow(CmpInst *Cmp,
return true;
}
+/// FIXME: The name is similar to combineToUSubWithOverflow. Consider renaming
+/// one or both to better distinguish them.
+///
+/// Reconstruct a subtract-with-borrow chain from its canonicalized icmp form.
+///
+/// InstCombine simplifies chained usub.with.overflow intrinsics (used for
+/// multi-precision subtraction) into icmp patterns:
+/// carry_out = or(icmp ult A, B, and(icmp eq A, B, carry_in))
+///
+/// This is algebraically correct but prevents the backend from generating
+/// efficient subtract-with-borrow instructions (e.g. x86 sbb, aarch64 sbcs).
+///
+/// This function matches the pattern and reconstructs the chained
+/// usub.with.overflow form that the DAG combiner can lower to USUBO_CARRY.
+bool CodeGenPrepare::combineToUSubWithCarry(BinaryOperator *OrI) {
+ if (!OrI->getType()->isIntOrIntVectorTy(1))
+ return false;
+
+ assert(OrI->getOpcode() == Instruction::Or && "Expected or instruction");
+
+ // Match: or(icmp ult A, B, and(icmp eq A, B, carry_in))
+ // with all commuted variants of and and icmp eq operand order.
+ Value *A, *B, *CarryIn;
+ if (!match(
+ OrI,
+ m_c_BinOp(
+ m_SpecificICmp(ICmpInst::ICMP_ULT, m_Value(A), m_Value(B)),
+ m_c_And(m_CombineOr(m_SpecificICmp(ICmpInst::ICMP_EQ,
+ m_Deferred(A), m_Deferred(B)),
+ m_SpecificICmp(ICmpInst::ICMP_EQ,
+ m_Deferred(B), m_Deferred(A))),
+ m_Value(CarryIn)))))
+ return false;
+
+ // Check that the target supports subtract-with-borrow for this type.
+ Type *OpTy = A->getType();
+ EVT VT = TLI->getValueType(*DL, OpTy);
+ if (!TLI->isOperationLegalOrCustom(ISD::USUBO_CARRY, VT))
----------------
RKSimon wrote:
Do you think this should go in DAG instead? I've no objections, I just figured it'd end up in CGP like some of the other addsub-overfow patterns
https://github.com/llvm/llvm-project/pull/189018
More information about the llvm-commits
mailing list