Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20551,6 +20551,19 @@ return false; } +// Transform to an x86-specific ALU node with flags if there is a chance of +// using an RMW op or only the flags are used. Otherwise, leave +// the node alone and emit a 'cmp' or 'test' instruction. +static bool isProfitableToUseFlagOp(SDValue Op) { + for (SDNode *U : Op->uses()) + if (U->getOpcode() != ISD::CopyToReg && + U->getOpcode() != ISD::SETCC && + U->getOpcode() != ISD::STORE) + return false; + + return true; +} + /// Emit nodes that will be selected as "test Op0,Op0", or something /// equivalent. static SDValue EmitTest(SDValue Op, unsigned X86CC, const SDLoc &dl, @@ -20614,15 +20627,8 @@ case ISD::SUB: case ISD::OR: case ISD::XOR: - // Transform to an x86-specific ALU node with flags if there is a chance of - // using an RMW op or only the flags are used. Otherwise, leave - // the node alone and emit a 'test' instruction. - for (SDNode::use_iterator UI = Op.getNode()->use_begin(), - UE = Op.getNode()->use_end(); UI != UE; ++UI) - if (UI->getOpcode() != ISD::CopyToReg && - UI->getOpcode() != ISD::SETCC && - UI->getOpcode() != ISD::STORE) - goto default_case; + if (!isProfitableToUseFlagOp(Op)) + break; // Otherwise use a regular EFLAGS-setting instruction. switch (ArithOp.getOpcode()) { @@ -20650,7 +20656,6 @@ Op->getOperand(1)).getValue(1); } default: - default_case: break; } @@ -21688,6 +21693,22 @@ } } + // Try to use the carry flag from the add in place of an separate CMP for: + // (seteq (add X, -1), -1). Similar for setne. + if (isAllOnesConstant(Op1) && Op0.getOpcode() == ISD::ADD && + Op0.getOperand(1) == Op1 && (CC == ISD::SETEQ || CC == ISD::SETNE)) { + if (isProfitableToUseFlagOp(Op0)) { + SDVTList VTs = DAG.getVTList(Op0.getValueType(), MVT::i32); + + SDValue New = DAG.getNode(X86ISD::ADD, dl, VTs, Op0.getOperand(0), + Op0.getOperand(1)); + DAG.ReplaceAllUsesOfValueWith(SDValue(Op0.getNode(), 0), New); + X86::CondCode CCode = CC == ISD::SETEQ ? X86::COND_AE : X86::COND_B; + X86CC = DAG.getTargetConstant(CCode, dl, MVT::i8); + return SDValue(New.getNode(), 1); + } + } + bool IsFP = Op1.getSimpleValueType().isFloatingPoint(); X86::CondCode CondCode = TranslateX86CC(CC, dl, IsFP, Op0, Op1, DAG); if (CondCode == X86::COND_INVALID) Index: llvm/test/CodeGen/X86/pr44412.ll =================================================================== --- llvm/test/CodeGen/X86/pr44412.ll +++ llvm/test/CodeGen/X86/pr44412.ll @@ -14,9 +14,8 @@ ; CHECK-NEXT: .LBB0_2: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: movl %ebx, %edi ; CHECK-NEXT: callq foo -; CHECK-NEXT: decl %ebx -; CHECK-NEXT: cmpl $-1, %ebx -; CHECK-NEXT: jne .LBB0_2 +; CHECK-NEXT: addl $-1, %ebx +; CHECK-NEXT: jb .LBB0_2 ; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: retq @@ -47,9 +46,8 @@ ; CHECK-NEXT: .LBB1_2: # =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: movl %ebx, %edi ; CHECK-NEXT: callq foo -; CHECK-NEXT: decl %ebx -; CHECK-NEXT: cmpl $-1, %ebx -; CHECK-NEXT: je .LBB1_2 +; CHECK-NEXT: addl $-1, %ebx +; CHECK-NEXT: jae .LBB1_2 ; CHECK-NEXT: .LBB1_3: ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: retq