Commit 9c2c093f by Jim Stichnoth

Subzero: x86-64: Allow immediates in 64-bit instructions.

The original code legalized *all* i64 constants into a register move, creating unnecessary instructions and slightly higher register pressure in most cases. Generally, immediates can be used in 64-bit instructions as long as the immediate can be represented as a sign-extended 32-bit value. BUG= none R=jpp@chromium.org Review URL: https://codereview.chromium.org/2063053002 .
parent 3f5cb6f3
...@@ -295,7 +295,6 @@ void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst, ...@@ -295,7 +295,6 @@ void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst,
template <typename TraitsType> template <typename TraitsType>
void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst, void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst,
const Immediate &imm) { const Immediate &imm) {
assert(Ty != IceType_i64 && "i64 not supported yet.");
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
if (Ty == IceType_i16) if (Ty == IceType_i16)
emitOperandSizeOverride(); emitOperandSizeOverride();
...@@ -2641,7 +2640,7 @@ template <typename TraitsType> ...@@ -2641,7 +2640,7 @@ template <typename TraitsType>
void AssemblerX86Base<TraitsType>::imul(Type Ty, GPRRegister reg, void AssemblerX86Base<TraitsType>::imul(Type Ty, GPRRegister reg,
const Immediate &imm) { const Immediate &imm) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
assert(Ty == IceType_i16 || Ty == IceType_i32); assert(Ty == IceType_i16 || Ty == IceType_i32 || Ty == IceType_i64);
if (Ty == IceType_i16) if (Ty == IceType_i16)
emitOperandSizeOverride(); emitOperandSizeOverride();
emitRexRB(Ty, reg, reg); emitRexRB(Ty, reg, reg);
......
...@@ -738,6 +738,10 @@ void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea, ...@@ -738,6 +738,10 @@ void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea,
Mem->toAsmAddress(Asm, Target, IsLea)); Mem->toAsmAddress(Asm, Target, IsLea));
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
(Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue())); (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
assert(Traits::Is64Bit);
assert(Utils::IsInt(32, Imm->getValue()));
(Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
} else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
const auto FixupKind = (Reloc->getName().hasStdString() && const auto FixupKind = (Reloc->getName().hasStdString() &&
Reloc->getName().toString() == GlobalOffsetTable) Reloc->getName().toString() == GlobalOffsetTable)
...@@ -765,6 +769,10 @@ void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, ...@@ -765,6 +769,10 @@ void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty,
(Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
(Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue())); (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
assert(Traits::Is64Bit);
assert(Utils::IsInt(32, Imm->getValue()));
(Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
} else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
const auto FixupKind = (Reloc->getName().hasStdString() && const auto FixupKind = (Reloc->getName().hasStdString() &&
Reloc->getName().toString() == GlobalOffsetTable) Reloc->getName().toString() == GlobalOffsetTable)
...@@ -816,6 +824,10 @@ void InstImpl<TraitsType>::emitIASGPRShift(const Cfg *Func, Type Ty, ...@@ -816,6 +824,10 @@ void InstImpl<TraitsType>::emitIASGPRShift(const Cfg *Func, Type Ty,
(Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
(Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue())); (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
} else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
assert(Traits::Is64Bit);
assert(Utils::IsInt(32, Imm->getValue()));
(Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
} else { } else {
llvm_unreachable("Unexpected operand type"); llvm_unreachable("Unexpected operand type");
} }
...@@ -2042,7 +2054,8 @@ void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const { ...@@ -2042,7 +2054,8 @@ void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const {
Type SrcTy = Src->getType(); Type SrcTy = Src->getType();
Type DestTy = this->getDest()->getType(); Type DestTy = this->getDest()->getType();
if (Traits::Is64Bit && DestTy == IceType_i64 && if (Traits::Is64Bit && DestTy == IceType_i64 &&
llvm::isa<ConstantInteger64>(Src)) { llvm::isa<ConstantInteger64>(Src) &&
!Utils::IsInt(32, llvm::cast<ConstantInteger64>(Src)->getValue())) {
Str << "\t" Str << "\t"
"movabs" "movabs"
"\t"; "\t";
......
...@@ -2228,21 +2228,24 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) { ...@@ -2228,21 +2228,24 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
break; break;
case InstArithmetic::Shl: case InstArithmetic::Shl:
_mov(T, Src0); _mov(T, Src0);
if (!llvm::isa<ConstantInteger32>(Src1)) if (!llvm::isa<ConstantInteger32>(Src1) &&
!llvm::isa<ConstantInteger64>(Src1))
Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl); Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
_shl(T, Src1); _shl(T, Src1);
_mov(Dest, T); _mov(Dest, T);
break; break;
case InstArithmetic::Lshr: case InstArithmetic::Lshr:
_mov(T, Src0); _mov(T, Src0);
if (!llvm::isa<ConstantInteger32>(Src1)) if (!llvm::isa<ConstantInteger32>(Src1) &&
!llvm::isa<ConstantInteger64>(Src1))
Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl); Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
_shr(T, Src1); _shr(T, Src1);
_mov(Dest, T); _mov(Dest, T);
break; break;
case InstArithmetic::Ashr: case InstArithmetic::Ashr:
_mov(T, Src0); _mov(T, Src0);
if (!llvm::isa<ConstantInteger32>(Src1)) if (!llvm::isa<ConstantInteger32>(Src1) &&
!llvm::isa<ConstantInteger64>(Src1))
Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl); Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl);
_sar(T, Src1); _sar(T, Src1);
_mov(Dest, T); _mov(Dest, T);
...@@ -7339,11 +7342,13 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, ...@@ -7339,11 +7342,13 @@ Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed,
// If the operand is a 64 bit constant integer we need to legalize it to a // If the operand is a 64 bit constant integer we need to legalize it to a
// register in x86-64. // register in x86-64.
if (Traits::Is64Bit) { if (Traits::Is64Bit) {
if (llvm::isa<ConstantInteger64>(Const)) { if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Const)) {
if (RegNum.hasValue()) { if (!Utils::IsInt(32, C64->getValue())) {
assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum); if (RegNum.hasValue()) {
assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum);
}
return copyToReg(Const, RegNum);
} }
return copyToReg(Const, RegNum);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment