[llvm] [SDag] Fold saddo[_carry] with bitwise-not argument to ssubo[_carry] (PR #66571)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 15 23:22:25 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
<details>
<summary>Changes</summary>
Fold `(saddo (not a), 1)` to `(ssubo 0, a)` and
`(saddo_carry (not a), b, c)` to `(ssubo_carry b, a, !c)`.
This is the same as https://reviews.llvm.org/D46505 and
https://reviews.llvm.org/D59208, but for signed opcodes.
---
Full diff: https://github.com/llvm/llvm-project/pull/66571.diff
3 Files Affected:
- (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+26-1)
- (modified) llvm/test/CodeGen/AArch64/i128-math.ll (+25)
- (modified) llvm/test/CodeGen/X86/addcarry.ll (+29)
``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index be654b1d6591b20..484a6231b7f65fe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -430,6 +430,8 @@ namespace {
SDValue visitSADDO_CARRY(SDNode *N);
SDValue visitUADDO_CARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
SDNode *N);
+ SDValue visitSADDO_CARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
+ SDNode *N);
SDValue visitSUBE(SDNode *N);
SDValue visitUSUBO_CARRY(SDNode *N);
SDValue visitSSUBO_CARRY(SDNode *N);
@@ -3305,7 +3307,12 @@ SDValue DAGCombiner::visitADDO(SDNode *N) {
return CombineTo(N, DAG.getNode(ISD::ADD, DL, VT, N0, N1),
DAG.getConstant(0, DL, CarryVT));
- if (!IsSigned) {
+ if (IsSigned) {
+ // fold (saddo (xor a, -1), 1) -> (ssub 0, a).
+ if (isBitwiseNot(N0) && isOneOrOneSplat(N1))
+ return DAG.getNode(ISD::SSUBO, DL, N->getVTList(),
+ DAG.getConstant(0, DL, VT), N0.getOperand(0));
+ } else {
// fold (uaddo (xor a, -1), 1) -> (usub 0, a) and flip carry.
if (isBitwiseNot(N0) && isOneOrOneSplat(N1)) {
SDValue Sub = DAG.getNode(ISD::USUBO, DL, N->getVTList(),
@@ -3637,6 +3644,18 @@ SDValue DAGCombiner::visitUADDO_CARRYLike(SDValue N0, SDValue N1,
return SDValue();
}
+SDValue DAGCombiner::visitSADDO_CARRYLike(SDValue N0, SDValue N1,
+ SDValue CarryIn, SDNode *N) {
+ // fold (saddo_carry (xor a, -1), b, c) -> (ssubo_carry b, a, !c)
+ if (isBitwiseNot(N0)) {
+ if (SDValue NotC = extractBooleanFlip(CarryIn, DAG, TLI, true))
+ return DAG.getNode(ISD::SSUBO_CARRY, SDLoc(N), N->getVTList(), N1,
+ N0.getOperand(0), NotC);
+ }
+
+ return SDValue();
+}
+
SDValue DAGCombiner::visitSADDO_CARRY(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
@@ -3656,6 +3675,12 @@ SDValue DAGCombiner::visitSADDO_CARRY(SDNode *N) {
return DAG.getNode(ISD::SADDO, DL, N->getVTList(), N0, N1);
}
+ if (SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn, N))
+ return Combined;
+
+ if (SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn, N))
+ return Combined;
+
return SDValue();
}
diff --git a/llvm/test/CodeGen/AArch64/i128-math.ll b/llvm/test/CodeGen/AArch64/i128-math.ll
index 2f7848de82274e8..2e81c7381966aa0 100644
--- a/llvm/test/CodeGen/AArch64/i128-math.ll
+++ b/llvm/test/CodeGen/AArch64/i128-math.ll
@@ -430,3 +430,28 @@ define i128 @i128_saturating_mul(i128 %x, i128 %y) {
%7 = select i1 %3, i128 %6, i128 %2
ret i128 %7
}
+
+define { i128, i1 } @saddo_not_1(i128 %x) nounwind {
+; CHECK-LABEL: saddo_not_1:
+; CHECK: // %bb.0:
+; CHECK-NEXT: negs x0, x0
+; CHECK-NEXT: ngcs x1, x1
+; CHECK-NEXT: cset w2, vs
+; CHECK-NEXT: ret
+ %not = xor i128 %x, -1
+ %r = call { i128, i1} @llvm.sadd.with.overflow.i128(i128 %not, i128 1)
+ ret { i128, i1 } %r
+}
+
+define { i128, i1 } @saddo_carry_not_1(i128 %x) nounwind {
+; CHECK-LABEL: saddo_carry_not_1:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, #1 // =0x1
+; CHECK-NEXT: negs x0, x0
+; CHECK-NEXT: sbcs x1, x8, x1
+; CHECK-NEXT: cset w2, vs
+; CHECK-NEXT: ret
+ %not = xor i128 %x, -1
+ %r = call { i128, i1} @llvm.sadd.with.overflow.i128(i128 %not, i128 u0x10000000000000001)
+ ret { i128, i1 } %r
+}
diff --git a/llvm/test/CodeGen/X86/addcarry.ll b/llvm/test/CodeGen/X86/addcarry.ll
index 231645f6415919c..64152154ac34c0e 100644
--- a/llvm/test/CodeGen/X86/addcarry.ll
+++ b/llvm/test/CodeGen/X86/addcarry.ll
@@ -4,6 +4,7 @@
declare { i8, i64 } @llvm.x86.addcarry.64(i8, i64, i64)
declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64) #1
declare { i64, i1 } @llvm.usub.with.overflow.i64(i64, i64) #1
+declare { i128, i1 } @llvm.sadd.with.overflow.i128(i128, i128)
define i128 @add128(i128 %a, i128 %b) nounwind {
; CHECK-LABEL: add128:
@@ -388,6 +389,34 @@ define i128 @addcarry1_not(i128 %n) nounwind {
ret i128 %2
}
+define { i128, i1 } @saddo_not_1(i128 %x) nounwind {
+; CHECK-LABEL: saddo_not_1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movq %rdi, %rax
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: negq %rax
+; CHECK-NEXT: sbbq %rsi, %rdx
+; CHECK-NEXT: seto %cl
+; CHECK-NEXT: retq
+ %not = xor i128 %x, -1
+ %r = call { i128, i1} @llvm.sadd.with.overflow.i128(i128 %not, i128 1)
+ ret { i128, i1 } %r
+}
+
+define { i128, i1 } @saddo_carry_not_1(i128 %x) nounwind {
+; CHECK-LABEL: saddo_carry_not_1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movq %rdi, %rax
+; CHECK-NEXT: negq %rax
+; CHECK-NEXT: movl $1, %edx
+; CHECK-NEXT: sbbq %rsi, %rdx
+; CHECK-NEXT: seto %cl
+; CHECK-NEXT: retq
+ %not = xor i128 %x, -1
+ %r = call { i128, i1} @llvm.sadd.with.overflow.i128(i128 %not, i128 u0x10000000000000001)
+ ret { i128, i1 } %r
+}
+
define i128 @addcarry_to_subcarry(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: addcarry_to_subcarry:
; CHECK: # %bb.0:
``````````
</details>
https://github.com/llvm/llvm-project/pull/66571
More information about the llvm-commits
mailing list