[llvm] X86: Emit adox instead of adc for overflow add (PR #216609)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 26 21:20:22 PDT 2026
================
@@ -59769,6 +59785,57 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+// Optimize RES, EFLAGS = X86ISD::ADOX LHS, RHS, EFLAGS
+static SDValue combineADOX(SDNode *N, SelectionDAG &DAG) {
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+ SDValue CarryIn = N->getOperand(2);
+ auto *LHSC = dyn_cast<ConstantSDNode>(LHS);
+ auto *RHSC = dyn_cast<ConstantSDNode>(RHS);
+
+ // Canonicalize constant to RHS.
+ if (LHSC && !RHSC)
+ return DAG.getNode(X86ISD::ADOX, SDLoc(N), N->getVTList(), RHS, LHS,
+ CarryIn);
+
+ // Fold ADOX(ADD(X,Y),0,Carry) -> ADOX(X,Y,Carry)
+ // ISD::ADD produces no EFLAGS, so we only need to ensure the ADOX's own
+ // flag output is not needed before replacing it with a 2-operand ADOX.
+ SDValue AddOp = LHS;
+
+ // Unwrap extensions. This changes what the wide intermediate represents,
+ // but we will verify later that all uses of the wide result are
+ // truncations to the original width.
+ if (AddOp.getOpcode() == ISD::ANY_EXTEND ||
+ AddOp.getOpcode() == ISD::ZERO_EXTEND)
+ AddOp = AddOp.getOperand(0);
+
+ if (AddOp.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() &&
+ !needCarryOrOverflowFlag(SDValue(N, 1))) {
+ if (AddOp != LHS) {
+ unsigned OrigBits = AddOp.getValueType().getScalarSizeInBits();
+ for (SDUse &Use : N->uses()) {
+ if (Use.getResNo() == 0) {
+ SDNode *User = Use.getUser();
+ if (User->getOpcode() != ISD::TRUNCATE ||
+ User->getValueType(0).getScalarSizeInBits() > OrigBits)
----------------
topperc wrote:
getValueSizeInBits(0)
https://github.com/llvm/llvm-project/pull/216609
More information about the llvm-commits
mailing list