[llvm] [X86] Fold X - (!OF) into ADOX (PR #220455)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 1 19:00:44 PDT 2026
https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/220455
Add support for inversion of OF
>From d16e063b52aeae92fb22adc56669644c973068ce Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Tue, 1 Sep 2026 20:08:16 -0400
Subject: [PATCH 1/2] [X86][test] Pre-commit test for adox with -= !OF
---
llvm/test/CodeGen/X86/adox.ll | 77 +++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/llvm/test/CodeGen/X86/adox.ll b/llvm/test/CodeGen/X86/adox.ll
index d8b833ced37fb..b2ac76d18598b 100644
--- a/llvm/test/CodeGen/X86/adox.ll
+++ b/llvm/test/CodeGen/X86/adox.ll
@@ -330,5 +330,82 @@ nonzero:
ret i32 222
}
+
+define i32 @adox_test_sub_not_ov_i32(i32 %a, i32 %b, i8 %c, i8 %d) {
+; NDD-LABEL: adox_test_sub_not_ov_i32:
+; NDD: # %bb.0:
+; NDD-NEXT: xorl %eax, %eax
+; NDD-NEXT: cmpb %cl, %dl
+; NDD-NEXT: setno %al
+; NDD-NEXT: subl %esi, %edi
+; NDD-NEXT: subl %eax, %edi, %eax
+; NDD-NEXT: retq
+;
+; ADX-LABEL: adox_test_sub_not_ov_i32:
+; ADX: # %bb.0:
+; ADX-NEXT: movl %edi, %eax
+; ADX-NEXT: xorl %edi, %edi
+; ADX-NEXT: cmpb %cl, %dl
+; ADX-NEXT: setno %dil
+; ADX-NEXT: subl %esi, %eax
+; ADX-NEXT: subl %edi, %eax
+; ADX-NEXT: retq
+;
+; NOADX-LABEL: adox_test_sub_not_ov_i32:
+; NOADX: # %bb.0:
+; NOADX-NEXT: movl %edi, %eax
+; NOADX-NEXT: xorl %edi, %edi
+; NOADX-NEXT: cmpb %cl, %dl
+; NOADX-NEXT: setno %dil
+; NOADX-NEXT: subl %esi, %eax
+; NOADX-NEXT: subl %edi, %eax
+; NOADX-NEXT: retq
+ %ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
+ %ov = extractvalue { i8, i1 } %ssub, 1
+ %not.ov = xor i1 %ov, true
+ %not.ov.ext = zext i1 %not.ov to i32
+ %sum = sub i32 %a, %b
+ %res = sub i32 %sum, %not.ov.ext
+ ret i32 %res
+}
+
+define i64 @adox_test_sub_not_ov_i64(i64 %a, i64 %b, i8 %c, i8 %d) {
+; NDD-LABEL: adox_test_sub_not_ov_i64:
+; NDD: # %bb.0:
+; NDD-NEXT: xorl %eax, %eax
+; NDD-NEXT: cmpb %cl, %dl
+; NDD-NEXT: setno %al
+; NDD-NEXT: subq %rsi, %rdi
+; NDD-NEXT: subq %rax, %rdi, %rax
+; NDD-NEXT: retq
+;
+; ADX-LABEL: adox_test_sub_not_ov_i64:
+; ADX: # %bb.0:
+; ADX-NEXT: movq %rdi, %rax
+; ADX-NEXT: xorl %edi, %edi
+; ADX-NEXT: cmpb %cl, %dl
+; ADX-NEXT: setno %dil
+; ADX-NEXT: subq %rsi, %rax
+; ADX-NEXT: subq %rdi, %rax
+; ADX-NEXT: retq
+;
+; NOADX-LABEL: adox_test_sub_not_ov_i64:
+; NOADX: # %bb.0:
+; NOADX-NEXT: movq %rdi, %rax
+; NOADX-NEXT: xorl %edi, %edi
+; NOADX-NEXT: cmpb %cl, %dl
+; NOADX-NEXT: setno %dil
+; NOADX-NEXT: subq %rsi, %rax
+; NOADX-NEXT: subq %rdi, %rax
+; NOADX-NEXT: retq
+ %ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
+ %ov = extractvalue { i8, i1 } %ssub, 1
+ %not.ov = xor i1 %ov, true
+ %not.ov.ext = zext i1 %not.ov to i64
+ %sum = sub i64 %a, %b
+ %res = sub i64 %sum, %not.ov.ext
+ ret i64 %res
+}
+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
>From ee5bbc506323a755ac0cbb4bae699f48b41b42cd Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Tue, 1 Sep 2026 21:59:11 -0400
Subject: [PATCH 2/2] [X86] Fold X - (!OF) into ADOX
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 21 +++++++++++++++----
llvm/test/CodeGen/X86/adox.ll | 28 +++++++++++--------------
2 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 71cba0b21af82..622376a8fa0e8 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53525,11 +53525,20 @@ static SDValue combineAddOrSubToADCOrSBB(bool IsSub, const SDLoc &DL, EVT VT,
X86::CondCode CC;
SDValue EFLAGS;
+ bool InvertCC = false;
+ if (Y.getOpcode() == ISD::XOR && isOneConstant(Y.getOperand(1)) &&
+ Y.hasOneUse()) {
+ InvertCC = true;
+ Y = Y.getOperand(0);
+ }
+
if (Y.getOpcode() == X86ISD::SETCC && Y.hasOneUse()) {
CC = (X86::CondCode)Y.getConstantOperandVal(0);
+ if (InvertCC)
+ CC = X86::GetOppositeBranchCondition(CC);
EFLAGS = Y.getOperand(1);
- } else if (Y.getOpcode() == ISD::AND && isOneConstant(Y.getOperand(1)) &&
- Y.hasOneUse()) {
+ } else if (!InvertCC && Y.getOpcode() == ISD::AND &&
+ isOneConstant(Y.getOperand(1)) && Y.hasOneUse()) {
EFLAGS = LowerAndToBT(Y, ISD::SETNE, DL, DAG, CC);
}
@@ -53576,10 +53585,12 @@ static SDValue combineAddOrSubToADCOrSBB(bool IsSub, const SDLoc &DL, EVT VT,
DAG.getVTList(VT, MVT::i32), X,
DAG.getConstant(0, DL, VT), EFLAGS);
}
- if (!IsSub && CC == X86::COND_O && !FlagsUsed &&
+ if (((!IsSub && CC == X86::COND_O) || (IsSub && CC == X86::COND_NO)) &&
+ !FlagsUsed &&
(VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32 || VT == MVT::i64) &&
DAG.getSubtarget<X86Subtarget>().hasADX()) {
// X + (overflow_from_OF ? 1 : 0) --> adox X, 0
+ // X - (!overflow_from_OF ? 1 : 0) --> adox X, -1
// NOTE: For i8/i16, ADOX32's OF output does not match the original iN
// overflow. This is safe because this ADOX replaces an ISD::ADD, so its OF
// output is natively dead. Its ANY_EXTEND operands ensure future transforms
@@ -53588,7 +53599,9 @@ static SDValue combineAddOrSubToADCOrSBB(bool IsSub, const SDLoc &DL, EVT VT,
SDValue AdoxX = DAG.getAnyExtOrTrunc(X, DL, AdoxVT);
SDValue Adox =
DAG.getNode(X86ISD::ADOX, DL, DAG.getVTList(AdoxVT, MVT::i32), AdoxX,
- DAG.getConstant(0, DL, AdoxVT), EFLAGS);
+ IsSub ? DAG.getAllOnesConstant(DL, AdoxVT)
+ : DAG.getConstant(0, DL, AdoxVT),
+ EFLAGS);
return DAG.getAnyExtOrTrunc(Adox, DL, VT);
}
diff --git a/llvm/test/CodeGen/X86/adox.ll b/llvm/test/CodeGen/X86/adox.ll
index b2ac76d18598b..9d2b92761d7f0 100644
--- a/llvm/test/CodeGen/X86/adox.ll
+++ b/llvm/test/CodeGen/X86/adox.ll
@@ -334,21 +334,19 @@ nonzero:
define i32 @adox_test_sub_not_ov_i32(i32 %a, i32 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_sub_not_ov_i32:
; NDD: # %bb.0:
-; NDD-NEXT: xorl %eax, %eax
+; NDD-NEXT: subl %esi, %edi, %eax
; NDD-NEXT: cmpb %cl, %dl
-; NDD-NEXT: setno %al
-; NDD-NEXT: subl %esi, %edi
-; NDD-NEXT: subl %eax, %edi, %eax
+; NDD-NEXT: movl $-1, %ecx
+; NDD-NEXT: adoxl %ecx, %eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_sub_not_ov_i32:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
-; ADX-NEXT: xorl %edi, %edi
-; ADX-NEXT: cmpb %cl, %dl
-; ADX-NEXT: setno %dil
; ADX-NEXT: subl %esi, %eax
-; ADX-NEXT: subl %edi, %eax
+; ADX-NEXT: cmpb %cl, %dl
+; ADX-NEXT: movl $-1, %ecx
+; ADX-NEXT: adoxl %ecx, %eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_sub_not_ov_i32:
@@ -372,21 +370,19 @@ define i32 @adox_test_sub_not_ov_i32(i32 %a, i32 %b, i8 %c, i8 %d) {
define i64 @adox_test_sub_not_ov_i64(i64 %a, i64 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_sub_not_ov_i64:
; NDD: # %bb.0:
-; NDD-NEXT: xorl %eax, %eax
+; NDD-NEXT: subq %rsi, %rdi, %rax
; NDD-NEXT: cmpb %cl, %dl
-; NDD-NEXT: setno %al
-; NDD-NEXT: subq %rsi, %rdi
-; NDD-NEXT: subq %rax, %rdi, %rax
+; NDD-NEXT: movq $-1, %rcx
+; NDD-NEXT: adoxq %rcx, %rax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_sub_not_ov_i64:
; ADX: # %bb.0:
; ADX-NEXT: movq %rdi, %rax
-; ADX-NEXT: xorl %edi, %edi
-; ADX-NEXT: cmpb %cl, %dl
-; ADX-NEXT: setno %dil
; ADX-NEXT: subq %rsi, %rax
-; ADX-NEXT: subq %rdi, %rax
+; ADX-NEXT: cmpb %cl, %dl
+; ADX-NEXT: movq $-1, %rcx
+; ADX-NEXT: adoxq %rcx, %rax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_sub_not_ov_i64:
More information about the llvm-commits
mailing list