diff options
| author | Craig Topper <craig.topper@intel.com> | 2017-09-02 18:53:46 +0000 |
|---|---|---|
| committer | Craig Topper <craig.topper@intel.com> | 2017-09-02 18:53:46 +0000 |
| commit | 619b759a57806a516911927f9940642eab20c037 (patch) | |
| tree | f861abd94cc73a8dd175416056885543c92c391b /llvm/lib/Target/X86/X86FastISel.cpp | |
| parent | bc6da4e40f6b389c4675812350bf096790591e8c (diff) | |
| download | bcm5719-llvm-619b759a57806a516911927f9940642eab20c037.tar.gz bcm5719-llvm-619b759a57806a516911927f9940642eab20c037.zip | |
[X86] Teach fastisel to handle zext/sext i8->i16 and sext i1->i8/i16/i32/i64
Summary:
ZExt and SExt from i8 to i16 aren't implemented in the autogenerated fast isel table because normal isel does a zext/sext to 32-bits and a subreg extract to avoid a partial register write or false dependency on the upper bits of the destination. This means without handling in fast isel we end up triggering a fast isel abort.
We had no custom sign extend handling at all so while I was there I went ahead and implemented sext i1->i8/i16/i32/i64 which was also missing. This generates an i1->i8 sign extend using a mask with 1, then an 8-bit negate, then continues with a sext from i8. A better sequence would be a wider and/negate, but would require more custom code.
Fast isel tests are a mess and I couldn't find a good home for the tests so I created a new one.
The test pr34381.ll had to have fast-isel removed because it was relying on a fast isel abort to hit the bug. The test case still seems valid with fast-isel disabled though some of the instructions changed.
Reviewers: spatel, zvi, igorb, guyblank, RKSimon
Reviewed By: guyblank
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D37320
llvm-svn: 312422
Diffstat (limited to 'llvm/lib/Target/X86/X86FastISel.cpp')
| -rw-r--r-- | llvm/lib/Target/X86/X86FastISel.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 3bdba662c5e..6fcc268b0b8 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -110,6 +110,8 @@ private: bool X86SelectZExt(const Instruction *I); + bool X86SelectSExt(const Instruction *I); + bool X86SelectBranch(const Instruction *I); bool X86SelectShift(const Instruction *I); @@ -1555,6 +1557,15 @@ bool X86FastISel::X86SelectZExt(const Instruction *I) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::SUBREG_TO_REG), ResultReg) .addImm(0).addReg(Result32).addImm(X86::sub_32bit); + } else if (DstVT == MVT::i16) { + // i8->i16 doesn't exist in the autogenerated isel table. Need to zero + // extend to 32-bits and then extract down to 16-bits. + unsigned Result32 = createResultReg(&X86::GR32RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::MOVZX32rr8), + Result32).addReg(ResultReg); + + ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, /*Kill=*/true, + X86::sub_16bit); } else if (DstVT != MVT::i8) { ResultReg = fastEmit_r(MVT::i8, DstVT.getSimpleVT(), ISD::ZERO_EXTEND, ResultReg, /*Kill=*/true); @@ -1566,6 +1577,52 @@ bool X86FastISel::X86SelectZExt(const Instruction *I) { return true; } +bool X86FastISel::X86SelectSExt(const Instruction *I) { + EVT DstVT = TLI.getValueType(DL, I->getType()); + if (!TLI.isTypeLegal(DstVT)) + return false; + + unsigned ResultReg = getRegForValue(I->getOperand(0)); + if (ResultReg == 0) + return false; + + // Handle sign-extension from i1 to i8. + MVT SrcVT = TLI.getSimpleValueType(DL, I->getOperand(0)->getType()); + if (SrcVT == MVT::i1) { + // Set the high bits to zero. + unsigned ZExtReg = fastEmitZExtFromI1(MVT::i8, ResultReg, + /*TODO: Kill=*/false); + if (ZExtReg == 0) + return false; + + // Negate the result to make an 8-bit sign extended value. + ResultReg = createResultReg(&X86::GR8RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::NEG8r), + ResultReg).addReg(ZExtReg); + + SrcVT = MVT::i8; + } + + if (DstVT == MVT::i16) { + // i8->i16 doesn't exist in the autogenerated isel table. Need to sign + // extend to 32-bits and then extract down to 16-bits. + unsigned Result32 = createResultReg(&X86::GR32RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::MOVSX32rr8), + Result32).addReg(ResultReg); + + ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, /*Kill=*/true, + X86::sub_16bit); + } else if (DstVT != MVT::i8) { + ResultReg = fastEmit_r(MVT::i8, DstVT.getSimpleVT(), ISD::SIGN_EXTEND, + ResultReg, /*Kill=*/true); + if (ResultReg == 0) + return false; + } + + updateValueMap(I, ResultReg); + return true; +} + bool X86FastISel::X86SelectBranch(const Instruction *I) { // Unconditional branches are selected by tablegen-generated code. // Handle a conditional branch. @@ -3537,6 +3594,8 @@ X86FastISel::fastSelectInstruction(const Instruction *I) { return X86SelectCmp(I); case Instruction::ZExt: return X86SelectZExt(I); + case Instruction::SExt: + return X86SelectSExt(I); case Instruction::Br: return X86SelectBranch(I); case Instruction::LShr: |

