diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3014,7 +3014,8 @@ return SDValue(); } -static SDValue getAsCarry(const TargetLowering &TLI, SDValue V) { +static SDValue getAsCarry(const TargetLowering &TLI, SDValue V, + bool ForceCarryReconstruction = false) { bool Masked = false; // First, peel away TRUNCATE/ZERO_EXTEND/AND nodes due to legalization. @@ -3030,9 +3031,15 @@ continue; } + if (ForceCarryReconstruction && V.getValueType() == MVT::i1) + return V; + break; } + if (ForceCarryReconstruction && Masked) + return V; + // If this is not a carry, return. if (V.getResNo() != 1) return SDValue(); @@ -3539,11 +3546,8 @@ return SDValue(); // Verify that the carry/borrow in is plausibly a carry/borrow bit. - // TODO: make getAsCarry() aware of how partial carries are merged. - if (CarryIn.getOpcode() != ISD::ZERO_EXTEND) - return SDValue(); - CarryIn = CarryIn.getOperand(0); - if (CarryIn.getValueType() != MVT::i1) + CarryIn = getAsCarry(TLI, CarryIn, true); + if (!CarryIn) return SDValue(); SDLoc DL(N); diff --git a/llvm/test/CodeGen/X86/addcarry.ll b/llvm/test/CodeGen/X86/addcarry.ll --- a/llvm/test/CodeGen/X86/addcarry.ll +++ b/llvm/test/CodeGen/X86/addcarry.ll @@ -637,7 +637,7 @@ ; CHECK-LABEL: addcarry_fake_carry: ; CHECK: # %bb.0: ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: btl $0, %edx +; CHECK-NEXT: addl $-1, %edx ; CHECK-NEXT: adcq %rsi, %rax ; CHECK-NEXT: setb %dl ; CHECK-NEXT: retq diff --git a/llvm/test/CodeGen/X86/subcarry.ll b/llvm/test/CodeGen/X86/subcarry.ll --- a/llvm/test/CodeGen/X86/subcarry.ll +++ b/llvm/test/CodeGen/X86/subcarry.ll @@ -346,7 +346,7 @@ ; CHECK-LABEL: subcarry_fake_carry: ; CHECK: # %bb.0: ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: btl $0, %edx +; CHECK-NEXT: addl $-1, %edx ; CHECK-NEXT: sbbq %rsi, %rax ; CHECK-NEXT: setb %dl ; CHECK-NEXT: retq