Chromium Code Reviews| Index: src/IceInstX86BaseImpl.h |
| diff --git a/src/IceInstX86BaseImpl.h b/src/IceInstX86BaseImpl.h |
| index addb59964479e5e509b8902923405ec8ab2d0491..5bcd8697a678c67ec3b19247bc0882bde3d83241 100644 |
| --- a/src/IceInstX86BaseImpl.h |
| +++ b/src/IceInstX86BaseImpl.h |
| @@ -324,12 +324,16 @@ InstImpl<TraitsType>::InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest) |
| } |
| template <typename TraitsType> |
| -InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Variable *Source) |
| +InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Operand *Source) |
| : InstX86Base(Func, InstX86Base::Push, 1, nullptr) { |
| this->addSource(Source); |
| } |
| template <typename TraitsType> |
| +InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, InstX86Label *L) |
| + : InstX86Base(Func, InstX86Base::Push, 0, nullptr), Label(L) {} |
| + |
| +template <typename TraitsType> |
| InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source) |
| : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) { |
| if (Source) |
| @@ -455,6 +459,9 @@ void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const { |
| template <typename TraitsType> |
| void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const { |
| Assembler *Asm = Func->getAssembler<Assembler>(); |
| + if (IsReturnLocation) { |
| + Asm->addRelocationAtCurrentPosition(getName(Func)); |
| + } |
| Asm->bindLocalLabel(Number); |
| } |
| @@ -552,8 +559,18 @@ void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const { |
| return; |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| assert(this->getSrcSize() == 1); |
| + const Operand *Src = this->getSrc(0); |
| + if (Traits::Is64Bit) { |
| + if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| + Str << "\t" |
| + "jmp" |
| + "\t" << CR->getName(); |
| + return; |
| + } |
| + } |
| Str << "\t" |
| - "jmp\t*"; |
| + "jmp" |
| + "\t*"; |
| getJmpTarget()->emit(Func); |
| } |
| @@ -707,8 +724,8 @@ void InstImpl<TraitsType>::emitIASOpTyGPR(const Cfg *Func, Type Ty, |
| template <typename TraitsType> |
| template <bool VarCanBeByte, bool SrcCanBeByte> |
| -void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, Type Ty, |
| - const Variable *Var, |
| +void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea, |
| + Type Ty, const Variable *Var, |
| const Operand *Src, |
| const GPREmitterRegOp &Emitter) { |
| auto *Target = InstX86Base::getTarget(Func); |
| @@ -729,7 +746,8 @@ void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, Type Ty, |
| } |
| } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) { |
| Mem->emitSegmentOverride(Asm); |
| - (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); |
| + (Asm->*(Emitter.GPRAddr))(Ty, VarReg, |
| + Mem->toAsmAddress(Asm, Target, IsLea)); |
| } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue())); |
| } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| @@ -1136,7 +1154,8 @@ void InstImpl<TraitsType>::InstX86Imul::emitIAS(const Cfg *Func) const { |
| assert(Var == this->getSrc(0)); |
| static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul, |
| &Assembler::imul}; |
| - emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); |
| + constexpr bool NotLea = false; |
| + emitIASRegOpTyGPR(Func, NotLea, Ty, Var, Src, Emitter); |
| } |
| } |
| @@ -1695,7 +1714,8 @@ void InstImpl<TraitsType>::InstX86Icmp::emitIAS(const Cfg *Func) const { |
| &Assembler::cmp}; |
| if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| if (SrcVar0->hasReg()) { |
| - emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| + constexpr bool NotLea = false; |
| + emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter); |
| return; |
| } |
| } |
| @@ -1797,7 +1817,8 @@ void InstImpl<TraitsType>::InstX86Test::emitIAS(const Cfg *Func) const { |
| &Assembler::test}; |
| if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| if (SrcVar0->hasReg()) { |
| - emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| + constexpr bool NotLea = false; |
| + emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter); |
| return; |
| } |
| } |
| @@ -1980,7 +2001,7 @@ void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const { |
| assert(this->getSrcSize() == 1); |
| assert(this->getDest()->hasReg()); |
| Str << "\t" |
| - "leal\t"; |
| + "lea" << this->getWidthString(this->getDest()->getType()) << "\t"; |
| Operand *Src0 = this->getSrc(0); |
| if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) { |
| Type Ty = Src0Var->getType(); |
| @@ -2080,7 +2101,8 @@ void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const { |
| if (isScalarIntegerType(SrcTy)) { |
| SrcTy = DestTy; |
| } |
| - emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter); |
| + constexpr bool NotLea = false; |
| + emitIASRegOpTyGPR(Func, NotLea, DestTy, Dest, Src, GPRRegEmitter); |
| return; |
| } |
| } else { |
| @@ -2257,7 +2279,32 @@ void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const { |
| Type SrcTy = Src->getType(); |
| assert(typeWidthInBytes(Dest->getType()) > 1); |
| assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
| - emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter); |
| + constexpr bool NotLea = false; |
| + emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter); |
| +} |
| + |
| +template <typename TraitsType> |
| +bool InstImpl<TraitsType>::InstX86Movzx::mayBeElided( |
| + const Variable *Dest, const Operand *SrcOpnd) const { |
| + assert(Traits::Is64Bit); |
| + const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd); |
| + |
| + // Src is not a Variable, so it does not have a register. Movzx can't be |
| + // elided. |
| + if (Src == nullptr) |
| + return false; |
| + |
| + // Movzx to/from memory can't be elided. |
| + if (!Src->hasReg() || !Dest->hasReg()) |
| + return false; |
| + |
| + // Reg/reg move with different source and dest can't be elided. |
| + if (Traits::getEncodedGPR(Src->getRegNum()) != |
| + Traits::getEncodedGPR(Dest->getRegNum())) |
| + return false; |
| + |
| + // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing. |
| + return !MustKeep; |
| } |
| template <typename TraitsType> |
| @@ -2272,15 +2319,19 @@ void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const { |
| const Variable *Dest = this->Dest; |
| if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) { |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| - Str << "\t" |
| - "mov" |
| - "\t"; |
| - Src->emit(Func); |
| - Str << ", "; |
| - Dest->asType(IceType_i32, |
| - Traits::getGprForType(IceType_i32, Dest->getRegNum())) |
| - ->emit(Func); |
| - Str << " /* movzx */"; |
| + if (mayBeElided(Dest, Src)) { |
| + Str << "\t/* elided movzx */"; |
| + } else { |
| + Str << "\t" |
| + "mov" |
| + "\t"; |
| + Src->emit(Func); |
| + Str << ", "; |
| + Dest->asType(IceType_i32, |
| + Traits::getGprForType(IceType_i32, Dest->getRegNum())) |
| + ->emit(Func); |
| + Str << " /* movzx */"; |
| + } |
| return; |
| } |
| } |
| @@ -2295,7 +2346,14 @@ void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const { |
| Type SrcTy = Src->getType(); |
| assert(typeWidthInBytes(Dest->getType()) > 1); |
| assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
| - emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter); |
| + if (Traits::Is64Bit) { |
|
Jim Stichnoth
2016/01/14 00:09:52
I would just add this to the && conjunction below
John
2016/01/14 23:18:25
I thought about this, but I decided to go with thi
|
| + if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 && |
| + mayBeElided(Dest, Src)) { |
| + return; |
| + } |
| + } |
| + constexpr bool NotLea = false; |
| + emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter); |
| } |
| template <typename TraitsType> |
| @@ -2617,23 +2675,30 @@ void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const { |
| if (!BuildDefs::dump()) |
| return; |
| Ostream &Str = Func->getContext()->getStrEmit(); |
| - assert(this->getSrcSize() == 1); |
| - // Push is currently only used for saving GPRs. |
| - const auto *Var = llvm::cast<Variable>(this->getSrc(0)); |
| - assert(Var->hasReg()); |
| Str << "\t" |
| - "push\t"; |
| - Var->emit(Func); |
| + "push" |
| + "\t"; |
| + assert(this->getSrcSize() == 1); |
| + const Operand *Src = this->getSrc(0); |
| + Src->emit(Func); |
| } |
| template <typename TraitsType> |
| void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const { |
| - assert(this->getSrcSize() == 1); |
| - // Push is currently only used for saving GPRs. |
| - const auto *Var = llvm::cast<Variable>(this->getSrc(0)); |
| - assert(Var->hasReg()); |
| Assembler *Asm = Func->getAssembler<Assembler>(); |
| - Asm->pushl(Traits::getEncodedGPR(Var->getRegNum())); |
| + |
| + assert(this->getSrcSize() == 1); |
| + const Operand *Src = this->getSrc(0); |
| + |
| + if (const auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| + Asm->pushl(Traits::getEncodedGPR(Var->getRegNum())); |
| + } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| + Asm->pushl(AssemblerImmediate(Const32->getValue())); |
| + } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| + Asm->pushl(CR); |
| + } else { |
| + llvm_unreachable("Unexpected operand type"); |
| + } |
| } |
| template <typename TraitsType> |