[X86] Optimized ADC + ADD to ADC - #176713
Conversation
|
@llvm/pr-subscribers-backend-x86 Author: None (JaydeepChauhan14) ChangesFull diff: https://github.com/llvm/llvm-project/pull/176713.diff 2 Files Affected:
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 640d9c5f5bc07..d0f59fb95eec0 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58197,7 +58197,11 @@ static SDValue combineFunnelShift(SDNode *N, SelectionDAG &DAG,
static bool needCarryOrOverflowFlag(SDValue Flags) {
assert(Flags.getValueType() == MVT::i32 && "Unexpected VT!");
- for (const SDNode *User : Flags->users()) {
+ for (const SDUse &Use : Flags->uses()) {
+ // Only check things that use the flags.
+ if (Use.getResNo() != Flags.getResNo())
+ continue;
+ const SDNode *User = Use.getUser();
X86::CondCode CC;
switch (User->getOpcode()) {
default:
@@ -58541,7 +58545,7 @@ static SDValue combineADC(SDNode *N, SelectionDAG &DAG,
// Fold ADC(ADD(X,Y),0,Carry) -> ADC(X,Y,Carry)
// iff the flag result is dead.
if (LHS.getOpcode() == ISD::ADD && RHSC && RHSC->isZero() &&
- !N->hasAnyUseOfValue(1))
+ !needCarryOrOverflowFlag(SDValue(N, 1)))
return DAG.getNode(X86ISD::ADC, SDLoc(N), N->getVTList(), LHS.getOperand(0),
LHS.getOperand(1), CarryIn);
diff --git a/llvm/test/CodeGen/X86/combine-add.ll b/llvm/test/CodeGen/X86/combine-add.ll
index 51a8bf5b48415..7bacb3c495b50 100644
--- a/llvm/test/CodeGen/X86/combine-add.ll
+++ b/llvm/test/CodeGen/X86/combine-add.ll
@@ -561,3 +561,99 @@ define i64 @add_notx_x(i64 %v0) nounwind {
%y = add i64 %x, %v0
ret i64 %y
}
+
+; Basic positive test
+define i32 @add_adc(i32 %0, i32 %1, i32 %2) {
+; CHECK-LABEL: add_adc:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl %edi, %eax
+; CHECK-NEXT: cmpl %esi, %edi
+; CHECK-NEXT: adcl %edi, %edx
+; CHECK-NEXT: cmovsl %esi, %eax
+; CHECK-NEXT: retq
+ %4 = icmp ult i32 %0, %1
+ %5 = zext i1 %4 to i32
+ %6 = add i32 %2, %0
+ %7 = add i32 %6, %5
+ %8 = icmp slt i32 %7, 0
+ %9 = select i1 %8, i32 %1, i32 %0
+ ret i32 %9
+}
+
+; Negative test: Carry or overflow flag is used
+define i32 @add_adc_wrong_flags(i32 %0, i32 %1, i32 %2, i32 %3) {
+; CHECK-LABEL: add_adc_wrong_flags:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl %esi, %eax
+; CHECK-NEXT: cmpl %esi, %edi
+; CHECK-NEXT: adcl $0, %edx
+; CHECK-NEXT: addl %ecx, %edx
+; CHECK-NEXT: cmovbl %edi, %eax
+; CHECK-NEXT: retq
+ %5 = icmp ult i32 %0, %1
+ %6 = zext i1 %5 to i32
+ %7 = add i32 %2, %6
+ %8 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %7, i32 %3)
+ %9 = extractvalue { i32, i1 } %8, 1
+ %10 = select i1 %9, i32 %0, i32 %1
+ ret i32 %10
+}
+
+; Negative test: Multi-use
+define i32 @add_adc_multi_use(i32 %0, i32 %1, i32 %2, i32 %3, ptr %4) {
+; CHECK-LABEL: add_adc_multi_use:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl %esi, %eax
+; CHECK-NEXT: cmpl %esi, %edi
+; CHECK-NEXT: adcl $0, %edx
+; CHECK-NEXT: movl %edx, (%r8)
+; CHECK-NEXT: addl %ecx, %edx
+; CHECK-NEXT: cmovsl %edi, %eax
+; CHECK-NEXT: retq
+ %6 = icmp ult i32 %0, %1
+ %7 = zext i1 %6 to i32
+ %8 = add i32 %2, %7
+ store i32 %8, ptr %4, align 4
+ %9 = add i32 %8, %3
+ %10 = icmp slt i32 %9, 0
+ %11 = select i1 %10, i32 %0, i32 %1
+ ret i32 %11
+}
+
+; Positive test: Both adc operands are constants
+define i32 @add_adc_constants(i32 %0, i32 %1, i32 %2) {
+; CHECK-LABEL: add_adc_constants:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl %esi, %edi
+; CHECK-NEXT: adcl $42, %eax
+; CHECK-NEXT: addl %edx, %eax
+; CHECK-NEXT: retq
+ %4 = icmp ult i32 %0, %1
+ %5 = zext i1 %4 to i8
+ %6 = tail call { i8, i32 } @llvm.x86.addcarry.32(i8 %5, i32 0, i32 42)
+ %7 = extractvalue { i8, i32 } %6, 1
+ %8 = add i32 %7, %2
+ ret i32 %8
+}
+
+; Negative test: Multi-use
+define i32 @add_adc_constants_multi_use(i32 %0, i32 %1, i32 %2, ptr %3) {
+; CHECK-LABEL: add_adc_constants_multi_use:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl %esi, %eax
+; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: cmpl %eax, %edi
+; CHECK-NEXT: adcl $42, %esi
+; CHECK-NEXT: movl %esi, (%rcx)
+; CHECK-NEXT: addl %edx, %esi
+; CHECK-NEXT: cmovsl %edi, %eax
+; CHECK-NEXT: retq
+ %5 = icmp ult i32 %0, %1
+ %6 = select i1 %5, i32 43, i32 42
+ store i32 %6, ptr %3, align 4
+ %7 = add i32 %6, %2
+ %8 = icmp slt i32 %7, 0
+ %9 = select i1 %8, i32 %0, i32 %1
+ ret i32 %9
+}
|
|
Can you split the commit into 2 commits within the PR? One that adds tests with the existing codegen, and one that changes X86ISelLowering.cpp and updates the tests to show the new codegen. Then reviewers can review each commit individually within the PR to see how the output changes. |
Sure |
I didn't mean you needed to make a new PR. You can put multiple commits into one PR. The github webview will let reviewers look at each commit individually. |
…Y,Carry) (#177539) **Reference PR-** llvm/llvm-project#176713
|
Ping @RKSimon, @phoebewang |
|
Thank you @topperc and @phoebewang |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/31483 Here is the relevant piece of the build log for the reference |
It seems it is not related to current PR. |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/95/builds/20014 Here is the relevant piece of the build log for the reference |
…177539) **Reference PR-** llvm/llvm-project#176713
No description provided.