Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -34876,7 +34876,7 @@ // When legalizing carry, we create carries via add X, -1 // If that comes from an actual carry, via setcc, we use the // carry directly. -static SDValue combineCarryThroughADD(SDValue EFLAGS) { +static SDValue combineCarryThroughADD(SDValue EFLAGS, SelectionDAG &DAG) { if (EFLAGS.getOpcode() == X86ISD::ADD) { if (isAllOnesConstant(EFLAGS.getOperand(1))) { SDValue Carry = EFLAGS.getOperand(0); @@ -34889,8 +34889,27 @@ Carry = Carry.getOperand(0); if (Carry.getOpcode() == X86ISD::SETCC || Carry.getOpcode() == X86ISD::SETCC_CARRY) { - if (Carry.getConstantOperandVal(0) == X86::COND_B) - return Carry.getOperand(1); + // TODO: Merge this code with equivalent in combineAddOrSubToADCOrSBB? + uint64_t CarryCC = Carry.getConstantOperandVal(0); + SDValue CarryOp1 = Carry.getOperand(1); + if (CarryCC == X86::COND_B) + return CarryOp1; + if (CarryCC == X86::COND_A) { + // Try to convert COND_A into COND_B in an attempt to facilitate + // materializing "setb reg". + // + // Do not flip "e > c", where "c" is a constant, because Cmp + // instruction cannot take an immediate as its first operand. + // + if (CarryOp1.getOpcode() == X86ISD::SUB && CarryOp1.hasOneUse() && + CarryOp1.getValueType().isInteger() && + !isa(CarryOp1.getOperand(1))) { + SDValue SubCommute = + DAG.getNode(X86ISD::SUB, SDLoc(CarryOp1), CarryOp1->getVTList(), + CarryOp1.getOperand(1), CarryOp1.getOperand(0)); + return SDValue(SubCommute.getNode(), CarryOp1.getResNo()); + } + } } } } @@ -34905,7 +34924,7 @@ SelectionDAG &DAG, const X86Subtarget &Subtarget) { if (CC == X86::COND_B) - if (SDValue Flags = combineCarryThroughADD(EFLAGS)) + if (SDValue Flags = combineCarryThroughADD(EFLAGS, DAG)) return Flags; if (SDValue R = checkBoolTestSetCCCombine(EFLAGS, CC)) @@ -40558,7 +40577,7 @@ } static SDValue combineSBB(SDNode *N, SelectionDAG &DAG) { - if (SDValue Flags = combineCarryThroughADD(N->getOperand(2))) { + if (SDValue Flags = combineCarryThroughADD(N->getOperand(2), DAG)) { MVT VT = N->getSimpleValueType(0); SDVTList VTs = DAG.getVTList(VT, MVT::i32); return DAG.getNode(X86ISD::SBB, SDLoc(N), VTs, @@ -40601,7 +40620,7 @@ return DCI.CombineTo(N, Res1, CarryOut); } - if (SDValue Flags = combineCarryThroughADD(N->getOperand(2))) { + if (SDValue Flags = combineCarryThroughADD(N->getOperand(2), DAG)) { MVT VT = N->getSimpleValueType(0); SDVTList VTs = DAG.getVTList(VT, MVT::i32); return DAG.getNode(X86ISD::ADC, SDLoc(N), VTs, Index: llvm/trunk/test/CodeGen/X86/combine-sbb.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/combine-sbb.ll +++ llvm/trunk/test/CodeGen/X86/combine-sbb.ll @@ -126,19 +126,15 @@ ; X86: # %bb.0: ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl (%ecx), %edx -; X86-NEXT: cmpl {{[0-9]+}}(%esp), %edx -; X86-NEXT: seta %dl -; X86-NEXT: addb $-1, %dl +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: cmpl (%ecx), %edx ; X86-NEXT: sbbl 4(%ecx), %eax ; X86-NEXT: setb %al ; X86-NEXT: retl ; ; X64-LABEL: PR24545: ; X64: # %bb.0: -; X64-NEXT: cmpl %edi, (%rdx) -; X64-NEXT: seta %al -; X64-NEXT: addb $-1, %al +; X64-NEXT: cmpl (%rdx), %edi ; X64-NEXT: sbbl 4(%rdx), %esi ; X64-NEXT: setb %al ; X64-NEXT: retq