Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -130,7 +130,7 @@ /// supported by the target. SDValue ExpandVSELECT(SDValue Op); SDValue ExpandSELECT(SDValue Op); - SDValue ExpandLoad(SDValue Op); + std::pair ExpandLoad(SDValue Op); SDValue ExpandStore(SDValue Op); SDValue ExpandFNEG(SDValue Op); SDValue ExpandFSUB(SDValue Op); @@ -265,9 +265,13 @@ return TranslateLegalizeResults(Op, Lowered); } LLVM_FALLTHROUGH; - case TargetLowering::Expand: + case TargetLowering::Expand: { Changed = true; - return ExpandLoad(Op); + std::pair Tmp = ExpandLoad(Result); + AddLegalizedOperand(Op.getValue(0), Tmp.first); + AddLegalizedOperand(Op.getValue(1), Tmp.second); + return Op.getResNo() ? Tmp.first : Tmp.second; + } } } } else if (Op.getOpcode() == ISD::STORE) { @@ -290,9 +294,12 @@ } return TranslateLegalizeResults(Op, Lowered); } - case TargetLowering::Expand: + case TargetLowering::Expand: { Changed = true; - return ExpandStore(Op); + SDValue Chain = ExpandStore(Result); + AddLegalizedOperand(Op, Chain); + return Chain; + } } } } @@ -628,7 +635,7 @@ return Promoted; } -SDValue VectorLegalizer::ExpandLoad(SDValue Op) { +std::pair VectorLegalizer::ExpandLoad(SDValue Op) { LoadSDNode *LD = cast(Op.getNode()); EVT SrcVT = LD->getMemoryVT(); @@ -763,16 +770,12 @@ } } - AddLegalizedOperand(Op.getValue(0), Value); - AddLegalizedOperand(Op.getValue(1), NewChain); - - return (Op.getResNo() ? NewChain : Value); + return std::make_pair(Value, NewChain); } SDValue VectorLegalizer::ExpandStore(SDValue Op) { StoreSDNode *ST = cast(Op.getNode()); SDValue TF = TLI.scalarizeVectorStore(ST, DAG); - AddLegalizedOperand(Op, TF); return TF; } Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -21682,6 +21682,36 @@ } } + // 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)) { + // 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' instruction. + auto CheckAddUsers = [](SDValue Op) { + 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) + return false; + + return true; + }; + + if (CheckAddUsers(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_B : X86::COND_AE; + 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: jae .LBB0_2 ; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: retq