From 0956faba3d5940cb4e23c33a0030fdea48aa3c22 Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Wed, 25 Jun 2014 22:50:59 +0000 Subject: [PATCH] [FastISel][X86] More refactoring of select lowering and XALU folding. NFC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211740 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FastISel.cpp | 138 +++++++++++++-------------------- 1 file changed, 55 insertions(+), 83 deletions(-) diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 0d7037258b1..5f849f0fdee 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -111,11 +111,11 @@ private: bool X86SelectDivRem(const Instruction *I); - bool X86FastEmitCMoveSelect(const Instruction *I); + bool X86FastEmitCMoveSelect(MVT RetVT, const Instruction *I); - bool X86FastEmitSSESelect(const Instruction *I); + bool X86FastEmitSSESelect(MVT RetVT, const Instruction *I); - bool X86FastEmitPseudoSelect(const Instruction *I); + bool X86FastEmitPseudoSelect(MVT RetVT, const Instruction *I); bool X86SelectSelect(const Instruction *I); @@ -158,8 +158,8 @@ private: bool TryEmitSmallMemcpy(X86AddressMode DestAM, X86AddressMode SrcAM, uint64_t Len); - std::pair - foldX86XALUIntrinsic(const Instruction *I, const Value *Cond); + bool foldX86XALUIntrinsic(X86::CondCode &CC, const Instruction *I, + const Value *Cond); }; } // end anonymous namespace. @@ -278,15 +278,15 @@ getX86SSECondtionCode(CmpInst::Predicate Predicate) { } /// \brief Check if it is possible to fold the condition from the XALU intrinsic -/// into the user. -std::pair -X86FastISel::foldX86XALUIntrinsic(const Instruction *I, const Value *Cond) { +/// into the user. The condition code will only be updated on success. +bool X86FastISel::foldX86XALUIntrinsic(X86::CondCode &CC, const Instruction *I, + const Value *Cond) { if (!isa(Cond)) - return std::make_pair(false, X86::COND_INVALID); + return false; const auto *EV = cast(Cond); if (!isa(EV->getAggregateOperand())) - return std::make_pair(false, X86::COND_INVALID); + return false; const auto *II = cast(EV->getAggregateOperand()); MVT RetVT; @@ -294,25 +294,25 @@ X86FastISel::foldX86XALUIntrinsic(const Instruction *I, const Value *Cond) { Type *RetTy = cast(Callee->getReturnType())->getTypeAtIndex(0U); if (!isTypeLegal(RetTy, RetVT)) - return std::make_pair(false, X86::COND_INVALID); + return false; if (RetVT != MVT::i32 && RetVT != MVT::i64) - return std::make_pair(false, X86::COND_INVALID); + return false; - X86::CondCode CC; + X86::CondCode TmpCC; switch (II->getIntrinsicID()) { - default: return std::make_pair(false, X86::COND_INVALID); + default: return false; case Intrinsic::sadd_with_overflow: case Intrinsic::ssub_with_overflow: case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: CC = X86::COND_O; break; + case Intrinsic::umul_with_overflow: TmpCC = X86::COND_O; break; case Intrinsic::uadd_with_overflow: - case Intrinsic::usub_with_overflow: CC = X86::COND_B; break; + case Intrinsic::usub_with_overflow: TmpCC = X86::COND_B; break; } // Check if both instructions are in the same basic block. if (II->getParent() != I->getParent()) - return std::make_pair(false, X86::COND_INVALID); + return false; // Make sure nothing is in the way BasicBlock::const_iterator Start = I; @@ -321,15 +321,16 @@ X86FastISel::foldX86XALUIntrinsic(const Instruction *I, const Value *Cond) { // We only expect extractvalue instructions between the intrinsic and the // instruction to be selected. if (!isa(Itr)) - return std::make_pair(false, X86::COND_INVALID); + return false; // Check that the extractvalue operand comes from the intrinsic. const auto *EVI = cast(Itr); if (EVI->getAggregateOperand() != II) - return std::make_pair(false, X86::COND_INVALID); + return false; } - return std::make_pair(true, CC); + CC = TmpCC; + return true; } bool X86FastISel::isTypeLegal(Type *Ty, MVT &VT, bool AllowI1) { @@ -1335,6 +1336,7 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) { // Fold the common case of a conditional branch with a comparison // in the same block (values defined on other blocks may not have // initialized registers). + X86::CondCode CC; if (const CmpInst *CI = dyn_cast(BI->getCondition())) { if (CI->hasOneUse() && CI->getParent() == I->getParent()) { EVT VT = TLI.getValueType(CI->getOperand(0)->getType()); @@ -1382,7 +1384,6 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) { break; } - X86::CondCode CC; bool SwapArgs; unsigned BranchOpc; std::tie(CC, SwapArgs) = getX86ConditonCode(Predicate); @@ -1456,29 +1457,24 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) { return true; } } - } else { - bool FoldIntrinsic; - X86::CondCode CC; - std::tie(FoldIntrinsic, CC) = foldX86XALUIntrinsic(BI, BI->getCondition()); - if (FoldIntrinsic) { - // Fake request the condition, otherwise the intrinsic might be completely - // optimized away. - unsigned TmpReg = getRegForValue(BI->getCondition()); - if (TmpReg == 0) - return false; + } else if (foldX86XALUIntrinsic(CC, BI, BI->getCondition())) { + // Fake request the condition, otherwise the intrinsic might be completely + // optimized away. + unsigned TmpReg = getRegForValue(BI->getCondition()); + if (TmpReg == 0) + return false; - unsigned BranchOpc = X86::GetCondBranchFromCond(CC); + unsigned BranchOpc = X86::GetCondBranchFromCond(CC); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BranchOpc)) - .addMBB(TrueMBB); - FastEmitBranch(FalseMBB, DbgLoc); - uint32_t BranchWeight = 0; - if (FuncInfo.BPI) - BranchWeight = FuncInfo.BPI->getEdgeWeight(BI->getParent(), - TrueMBB->getBasicBlock()); - FuncInfo.MBB->addSuccessor(TrueMBB, BranchWeight); - return true; - } + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BranchOpc)) + .addMBB(TrueMBB); + FastEmitBranch(FalseMBB, DbgLoc); + uint32_t BranchWeight = 0; + if (FuncInfo.BPI) + BranchWeight = FuncInfo.BPI->getEdgeWeight(BI->getParent(), + TrueMBB->getBasicBlock()); + FuncInfo.MBB->addSuccessor(TrueMBB, BranchWeight); + return true; } // Otherwise do a clumsy setcc and re-test it. @@ -1735,27 +1731,19 @@ bool X86FastISel::X86SelectDivRem(const Instruction *I) { /// \brief Emit a conditional move instruction (if the are supported) to lower /// the select. -bool X86FastISel::X86FastEmitCMoveSelect(const Instruction *I) { - MVT RetVT; - if (!isTypeLegal(I->getType(), RetVT)) - return false; - +bool X86FastISel::X86FastEmitCMoveSelect(MVT RetVT, const Instruction *I) { // Check if the subtarget supports these instructions. if (!Subtarget->hasCMov()) return false; // FIXME: Add support for i8. - unsigned Opc; - switch (RetVT.SimpleTy) { - default: return false; - case MVT::i16: Opc = X86::CMOVNE16rr; break; - case MVT::i32: Opc = X86::CMOVNE32rr; break; - case MVT::i64: Opc = X86::CMOVNE64rr; break; - } + if (RetVT < MVT::i16 || RetVT > MVT::i64) + return false; const Value *Cond = I->getOperand(0); const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT); bool NeedTest = true; + X86::CondCode CC = X86::COND_NE; // Optimize conditons coming from a compare if both instructions are in the // same basic block (values defined in other basic blocks may not have @@ -1782,11 +1770,9 @@ bool X86FastISel::X86FastEmitCMoveSelect(const Instruction *I) { break; } - X86::CondCode CC; bool NeedSwap; std::tie(CC, NeedSwap) = getX86ConditonCode(Predicate); assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code."); - Opc = X86::getCMovFromCond(CC, RC->getSize()); const Value *CmpLHS = CI->getOperand(0); const Value *CmpRHS = CI->getOperand(1); @@ -1816,21 +1802,14 @@ bool X86FastISel::X86FastEmitCMoveSelect(const Instruction *I) { } } NeedTest = false; - } else { - bool FoldIntrinsic; - X86::CondCode CC; - std::tie(FoldIntrinsic, CC) = foldX86XALUIntrinsic(I, Cond); + } else if (foldX86XALUIntrinsic(CC, I, Cond)) { + // Fake request the condition, otherwise the intrinsic might be completely + // optimized away. + unsigned TmpReg = getRegForValue(Cond); + if (TmpReg == 0) + return false; - if (FoldIntrinsic) { - // Fake request the condition, otherwise the intrinsic might be completely - // optimized away. - unsigned TmpReg = getRegForValue(Cond); - if (TmpReg == 0) - return false; - - Opc = X86::getCMovFromCond(CC, RC->getSize()); - NeedTest = false; - } + NeedTest = false; } if (NeedTest) { @@ -1860,6 +1839,7 @@ bool X86FastISel::X86FastEmitCMoveSelect(const Instruction *I) { if (!LHSReg || !RHSReg) return false; + unsigned Opc = X86::getCMovFromCond(CC, RC->getSize()); unsigned ResultReg = FastEmitInst_rr(Opc, RC, RHSReg, RHSIsKill, LHSReg, LHSIsKill); UpdateValueMap(I, ResultReg); @@ -1871,11 +1851,7 @@ bool X86FastISel::X86FastEmitCMoveSelect(const Instruction *I) { /// Try to use SSE1/SSE2 instructions to simulate a select without branches. /// This lowers fp selects into a CMP/AND/ANDN/OR sequence when the necessary /// SSE instructions are available. -bool X86FastISel::X86FastEmitSSESelect(const Instruction *I) { - MVT RetVT; - if (!isTypeLegal(I->getType(), RetVT)) - return false; - +bool X86FastISel::X86FastEmitSSESelect(MVT RetVT, const Instruction *I) { // Optimize conditons coming from a compare if both instructions are in the // same basic block (values defined in other basic blocks may not have // initialized registers). @@ -1956,11 +1932,7 @@ bool X86FastISel::X86FastEmitSSESelect(const Instruction *I) { return true; } -bool X86FastISel::X86FastEmitPseudoSelect(const Instruction *I) { - MVT RetVT; - if (!isTypeLegal(I->getType(), RetVT)) - return false; - +bool X86FastISel::X86FastEmitPseudoSelect(MVT RetVT, const Instruction *I) { // These are pseudo CMOV instructions and will be later expanded into control- // flow. unsigned Opc; @@ -2055,16 +2027,16 @@ bool X86FastISel::X86SelectSelect(const Instruction *I) { } // First try to use real conditional move instructions. - if (X86FastEmitCMoveSelect(I)) + if (X86FastEmitCMoveSelect(RetVT, I)) return true; // Try to use a sequence of SSE instructions to simulate a conditonal move. - if (X86FastEmitSSESelect(I)) + if (X86FastEmitSSESelect(RetVT, I)) return true; // Fall-back to pseudo conditional move instructions, which will be later // converted to control-flow. - if (X86FastEmitPseudoSelect(I)) + if (X86FastEmitPseudoSelect(RetVT, I)) return true; return false;