mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	[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
This commit is contained in:
		| @@ -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<bool, X86::CondCode> | ||||
|   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<bool, X86::CondCode> | ||||
| 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<ExtractValueInst>(Cond)) | ||||
|     return std::make_pair(false, X86::COND_INVALID); | ||||
|     return false; | ||||
|  | ||||
|   const auto *EV = cast<ExtractValueInst>(Cond); | ||||
|   if (!isa<IntrinsicInst>(EV->getAggregateOperand())) | ||||
|     return std::make_pair(false, X86::COND_INVALID); | ||||
|     return false; | ||||
|  | ||||
|   const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand()); | ||||
|   MVT RetVT; | ||||
| @@ -294,25 +294,25 @@ X86FastISel::foldX86XALUIntrinsic(const Instruction *I, const Value *Cond) { | ||||
|   Type *RetTy = | ||||
|     cast<StructType>(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<ExtractValueInst>(Itr)) | ||||
|       return std::make_pair(false, X86::COND_INVALID); | ||||
|       return false; | ||||
|  | ||||
|     // Check that the extractvalue operand comes from the intrinsic. | ||||
|     const auto *EVI = cast<ExtractValueInst>(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<CmpInst>(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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user