summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorJuergen Ributzka <juergen@apple.com>2014-06-25 22:50:59 +0000
committerJuergen Ributzka <juergen@apple.com>2014-06-25 22:50:59 +0000
commit0956faba3d5940cb4e23c33a0030fdea48aa3c22 (patch)
tree2dc5f0a651aff15cc9667467799b872b870af1c8 /lib/Target
parentdd0966efd46abd56920e11915c86a0537eb4bc9f (diff)
downloadllvm-0956faba3d5940cb4e23c33a0030fdea48aa3c22.tar.gz
llvm-0956faba3d5940cb4e23c33a0030fdea48aa3c22.tar.bz2
llvm-0956faba3d5940cb4e23c33a0030fdea48aa3c22.tar.xz
[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
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/X86/X86FastISel.cpp138
1 files changed, 55 insertions, 83 deletions
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 0d7037258b..5f849f0fde 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<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);
-
- if (FoldIntrinsic) {
- // Fake request the condition, otherwise the intrinsic might be completely
- // optimized away.
- unsigned TmpReg = getRegForValue(Cond);
- if (TmpReg == 0)
- return false;
+ } 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;
- 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;