From 481b18562077d93be3d6f24586445034c19277d6 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 31 Mar 2022 09:52:55 +0100 Subject: [PATCH] [X86] combineCarryThroughADD - recognise X86ISD::ADD(AND(X,1),-1) pattern can be folded to X86ISD::BT As mentioned on D122482, if we've generated a masked overflow test see if we can fold it to X86ISD::BT to feed a X86ISD::ADC/SBB Differential Revision: https://reviews.llvm.org/D122572 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 20 +++++++++++++++++++- llvm/test/CodeGen/X86/addcarry.ll | 3 +-- llvm/test/CodeGen/X86/combine-adc.ll | 10 ++-------- llvm/test/CodeGen/X86/subcarry.ll | 3 +-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 712ef61951278..8521b0e36f3af 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -44714,12 +44714,15 @@ static bool checkBoolTestAndOrSetCCCombine(SDValue Cond, X86::CondCode &CC0, static SDValue combineCarryThroughADD(SDValue EFLAGS, SelectionDAG &DAG) { if (EFLAGS.getOpcode() == X86ISD::ADD) { if (isAllOnesConstant(EFLAGS.getOperand(1))) { + bool FoundAndLSB = false; SDValue Carry = EFLAGS.getOperand(0); while (Carry.getOpcode() == ISD::TRUNCATE || Carry.getOpcode() == ISD::ZERO_EXTEND || (Carry.getOpcode() == ISD::AND && - isOneConstant(Carry.getOperand(1)))) + isOneConstant(Carry.getOperand(1)))) { + FoundAndLSB |= Carry.getOpcode() == ISD::AND; Carry = Carry.getOperand(0); + } if (Carry.getOpcode() == X86ISD::SETCC || Carry.getOpcode() == X86ISD::SETCC_CARRY) { // TODO: Merge this code with equivalent in combineAddOrSubToADCOrSBB? @@ -44750,6 +44753,21 @@ static SDValue combineCarryThroughADD(SDValue EFLAGS, SelectionDAG &DAG) { CarryOp1.getOpcode() == X86ISD::ADD && isOneConstant(CarryOp1.getOperand(1))) return CarryOp1; + } else if (FoundAndLSB) { + SDLoc DL(Carry); + SDValue BitNo = DAG.getConstant(0, DL, Carry.getValueType()); + if (Carry.getOpcode() == ISD::SRL) { + BitNo = Carry.getOperand(1); + Carry = Carry.getOperand(0); + } + if (Carry.getScalarValueSizeInBits() < 32) + Carry = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Carry); + EVT CarryVT = Carry.getValueType(); + if (DAG.getTargetLoweringInfo().isTypeLegal(CarryVT)) { + if (CarryVT != BitNo.getValueType()) + BitNo = DAG.getNode(ISD::ANY_EXTEND, DL, CarryVT, BitNo); + return DAG.getNode(X86ISD::BT, DL, MVT::i32, Carry, BitNo); + } } } } diff --git a/llvm/test/CodeGen/X86/addcarry.ll b/llvm/test/CodeGen/X86/addcarry.ll index 74ccb7ee486a0..d15a075b583d5 100644 --- a/llvm/test/CodeGen/X86/addcarry.ll +++ b/llvm/test/CodeGen/X86/addcarry.ll @@ -640,8 +640,7 @@ define { i64, i1 } @addcarry_fake_carry(i64 %a, i64 %b, i1 %carryin) { ; CHECK-LABEL: addcarry_fake_carry: ; CHECK: # %bb.0: ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: andb $1, %dl -; CHECK-NEXT: addb $-1, %dl +; CHECK-NEXT: btl $0, %edx ; CHECK-NEXT: adcq %rsi, %rax ; CHECK-NEXT: setb %dl ; CHECK-NEXT: retq diff --git a/llvm/test/CodeGen/X86/combine-adc.ll b/llvm/test/CodeGen/X86/combine-adc.ll index 37f4fe195d806..1470d34ae93fe 100644 --- a/llvm/test/CodeGen/X86/combine-adc.ll +++ b/llvm/test/CodeGen/X86/combine-adc.ll @@ -67,24 +67,18 @@ define i32 @PR40483_add2(i32*, i32) nounwind { ret i32 %10 } -; FIXME: Fail to convert add+lshr+and to BT define i32 @adc_merge_constants(i32 %a0) nounwind { ; X86-LABEL: adc_merge_constants: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: shrl $11, %ecx -; X86-NEXT: andb $1, %cl ; X86-NEXT: xorl %eax, %eax -; X86-NEXT: addb $-1, %cl +; X86-NEXT: btl $11, {{[0-9]+}}(%esp) ; X86-NEXT: adcl $54, %eax ; X86-NEXT: retl ; ; X64-LABEL: adc_merge_constants: ; X64: # %bb.0: -; X64-NEXT: shrl $11, %edi -; X64-NEXT: andb $1, %dil ; X64-NEXT: xorl %eax, %eax -; X64-NEXT: addb $-1, %dil +; X64-NEXT: btl $11, %edi ; X64-NEXT: adcl $54, %eax ; X64-NEXT: retq %bit = lshr i32 %a0, 11 diff --git a/llvm/test/CodeGen/X86/subcarry.ll b/llvm/test/CodeGen/X86/subcarry.ll index ecb43031f632c..b4828aa092a3b 100644 --- a/llvm/test/CodeGen/X86/subcarry.ll +++ b/llvm/test/CodeGen/X86/subcarry.ll @@ -349,8 +349,7 @@ define { i64, i1 } @subcarry_fake_carry(i64 %a, i64 %b, i1 %carryin) { ; CHECK-LABEL: subcarry_fake_carry: ; CHECK: # %bb.0: ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: andb $1, %dl -; CHECK-NEXT: addb $-1, %dl +; CHECK-NEXT: btl $0, %edx ; CHECK-NEXT: sbbq %rsi, %rax ; CHECK-NEXT: setb %dl ; CHECK-NEXT: retq