diff options
author | Juergen Ributzka <juergen@apple.com> | 2014-06-23 21:55:44 +0000 |
---|---|---|
committer | Juergen Ributzka <juergen@apple.com> | 2014-06-23 21:55:44 +0000 |
commit | 20732d55c2fda872a32b2335febafa7327f8b066 (patch) | |
tree | e3b44e58c3dc849bab8feead770eb45918f5e823 /lib/Target/X86 | |
parent | d0976a3d200016d49448d0b08234220a7f07eb3d (diff) | |
download | llvm-20732d55c2fda872a32b2335febafa7327f8b066.tar.gz llvm-20732d55c2fda872a32b2335febafa7327f8b066.tar.bz2 llvm-20732d55c2fda872a32b2335febafa7327f8b066.tar.xz |
[FastISel][X86] Lower unsupported selects to control-flow.
The extends the select lowering coverage by emiting pseudo cmov
instructions. These insturction will be later on lowered to control-flow to
simulate the select.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211545 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86')
-rw-r--r-- | lib/Target/X86/X86FastISel.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index af9eaf32a3..6625a706d2 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -115,6 +115,8 @@ private: bool X86FastEmitSSESelect(const Instruction *I); + bool X86FastEmitPseudoSelect(const Instruction *I); + bool X86SelectSelect(const Instruction *I); bool X86SelectTrunc(const Instruction *I); @@ -1852,6 +1854,70 @@ bool X86FastISel::X86FastEmitSSESelect(const Instruction *I) { return true; } +bool X86FastISel::X86FastEmitPseudoSelect(const Instruction *I) { + MVT RetVT; + if (!isTypeLegal(I->getType(), RetVT)) + return false; + + // These are pseudo CMOV instructions and will be later expanded into control- + // flow. + unsigned Opc; + switch (RetVT.SimpleTy) { + default: return false; + case MVT::i8: Opc = X86::CMOV_GR8; break; + case MVT::i16: Opc = X86::CMOV_GR16; break; + case MVT::i32: Opc = X86::CMOV_GR32; break; + case MVT::f32: Opc = X86::CMOV_FR32; break; + case MVT::f64: Opc = X86::CMOV_FR64; break; + } + + const Value *Cond = I->getOperand(0); + X86::CondCode CC = X86::COND_NE; + // Don't emit a test if the condition comes from a compare. + if (const auto *CI = dyn_cast<CmpInst>(Cond)) { + bool NeedSwap; + std::tie(CC, NeedSwap) = getX86ConditonCode(CI->getPredicate()); + if (CC > X86::LAST_VALID_COND) + return false; + + const Value *CmpLHS = CI->getOperand(0); + const Value *CmpRHS = CI->getOperand(1); + + if (NeedSwap) + std::swap(CmpLHS, CmpRHS); + + EVT CmpVT = TLI.getValueType(CmpLHS->getType()); + if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT)) + return false; + } else { + unsigned CondReg = getRegForValue(Cond); + if (CondReg == 0) + return false; + bool CondIsKill = hasTrivialKill(Cond); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::TEST8ri)) + .addReg(CondReg, getKillRegState(CondIsKill)).addImm(1); + } + + const Value *LHS = I->getOperand(1); + const Value *RHS = I->getOperand(2); + + unsigned LHSReg = getRegForValue(LHS); + bool LHSIsKill = hasTrivialKill(LHS); + + unsigned RHSReg = getRegForValue(RHS); + bool RHSIsKill = hasTrivialKill(RHS); + + if (!LHSReg || !RHSReg) + return false; + + const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT); + + unsigned ResultReg = + FastEmitInst_rri(Opc, RC, RHSReg, RHSIsKill, LHSReg, LHSIsKill, CC); + UpdateValueMap(I, ResultReg); + return true; +} + bool X86FastISel::X86SelectSelect(const Instruction *I) { MVT RetVT; if (!isTypeLegal(I->getType(), RetVT)) @@ -1890,6 +1956,11 @@ bool X86FastISel::X86SelectSelect(const Instruction *I) { if (X86FastEmitSSESelect(I)) return true; + // Fall-back to pseudo conditional move instructions, which will be later + // converted to control-flow. + if (X86FastEmitPseudoSelect(I)) + return true; + return false; } |