diff options
Diffstat (limited to 'llvm/lib/Target/X86/X86InstructionSelector.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86InstructionSelector.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp index afbf5d5e23d..97e2226df6b 100644 --- a/llvm/lib/Target/X86/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp @@ -750,6 +750,70 @@ bool X86InstructionSelector::selectZext(MachineInstr &I, const LLT DstTy = MRI.getType(DstReg); const LLT SrcTy = MRI.getType(SrcReg); + assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) && + "8=>32 Zext is handled by tablegen"); + assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) && + "16=>32 Zext is handled by tablegen"); + + const static struct ZextEntry { + LLT SrcTy; + LLT DstTy; + unsigned MovOp; + bool NeedSubregToReg; + } OpTable[] = { + {LLT::scalar(8), LLT::scalar(16), X86::MOVZX16rr8, false}, // i8 => i16 + {LLT::scalar(8), LLT::scalar(64), X86::MOVZX32rr8, true}, // i8 => i64 + {LLT::scalar(16), LLT::scalar(64), X86::MOVZX32rr16, true}, // i16 => i64 + {LLT::scalar(32), LLT::scalar(64), 0, true} // i32 => i64 + }; + + auto ZextEntryIt = + std::find_if(std::begin(OpTable), std::end(OpTable), + [SrcTy, DstTy](const ZextEntry &El) { + return El.DstTy == DstTy && El.SrcTy == SrcTy; + }); + + // Here we try to select Zext into a MOVZ and/or SUBREG_TO_REG instruction. + if (ZextEntryIt != std::end(OpTable)) { + const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI); + const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI); + const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB); + const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB); + + if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) || + !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) { + DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) + << " operand\n"); + return false; + } + + unsigned TransitRegTo = DstReg; + unsigned TransitRegFrom = SrcReg; + if (ZextEntryIt->MovOp) { + // If we select Zext into MOVZ + SUBREG_TO_REG, we need to have + // a transit register in between: create it here. + if (ZextEntryIt->NeedSubregToReg) { + TransitRegFrom = MRI.createVirtualRegister( + getRegClass(LLT::scalar(32), DstReg, MRI)); + TransitRegTo = TransitRegFrom; + } + + BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ZextEntryIt->MovOp)) + .addDef(TransitRegTo) + .addReg(SrcReg); + } + if (ZextEntryIt->NeedSubregToReg) { + BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(TargetOpcode::SUBREG_TO_REG)) + .addDef(DstReg) + .addImm(0) + .addReg(TransitRegFrom) + .addImm(X86::sub_32bit); + } + I.eraseFromParent(); + return true; + } + if (SrcTy != LLT::scalar(1)) return false; |