summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86FastISel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86FastISel.cpp')
-rw-r--r--llvm/lib/Target/X86/X86FastISel.cpp59
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:
OpenPOWER on IntegriCloud