Aggressive LEA
Convert adds with a constant operand to lea on -aggressive-lea
BUG=none
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/2135403002 .
diff --git a/src/IceClFlags.def b/src/IceClFlags.def
index d5e1a26..f13afbe 100644
--- a/src/IceClFlags.def
+++ b/src/IceClFlags.def
@@ -95,6 +95,10 @@
cl::desc("Exit with success status, even if errors found"), \
cl::init(false)) \
\
+ X(AggressiveLea, bool, dev_opt_flag, "aggressive-lea", \
+ cl::desc("Convert additions to lea when it reduces code size"), \
+ cl::init(false)) \
+ \
X(BitcodeAsText, bool, dev_opt_flag, "bitcode-as-text", \
cl::desc("Accept textual form of PNaCl bitcode " \
"records (i.e. not .ll assembly)"), \
diff --git a/src/IceInstX86Base.h b/src/IceInstX86Base.h
index de7d2f7..1221351 100644
--- a/src/IceInstX86Base.h
+++ b/src/IceInstX86Base.h
@@ -622,6 +622,13 @@
Type Ty = Var->getType();
const Operand *Src = this->getSrc(0);
constexpr bool IsLea = K == InstX86Base::Lea;
+
+ if (IsLea) {
+ if (auto *Add = deoptLeaToAddOrNull(Func)) {
+ Add->emitIAS(Func);
+ return;
+ }
+ }
emitIASRegOpTyGPR(Func, IsLea, Ty, Var, Src, Emitter);
}
void dump(const Cfg *Func) const override {
@@ -632,6 +639,7 @@
Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " ";
this->dumpSources(Func);
}
+
static bool classof(const Inst *Instr) {
return InstX86Base::isClassof(Instr, InstX86Base::K);
}
@@ -642,6 +650,23 @@
this->addSource(Src);
}
+ Inst *deoptLeaToAddOrNull(const Cfg *Func) const {
+ // Revert back to Add when the Lea is a 2-address instruction.
+ // Caller has to emit, this just produces the add instruction.
+ if (auto *MemOp = llvm::dyn_cast<X86OperandMem>(this->getSrc(0))) {
+ if (getFlags().getAggressiveLea() &&
+ MemOp->getBase()->getRegNum() == this->getDest()->getRegNum() &&
+ MemOp->getIndex() == nullptr && MemOp->getShift() == 0) {
+ auto *Add = InstImpl<TraitsType>::InstX86Add::create(
+ const_cast<Cfg *>(Func), this->getDest(), MemOp->getOffset());
+ // TODO(manasijm): Remove const_cast by emitting code for add
+ // directly.
+ return Add;
+ }
+ }
+ return nullptr;
+ }
+
static const char *Opcode;
static const GPREmitterRegOp Emitter;
};
diff --git a/src/IceInstX86BaseImpl.h b/src/IceInstX86BaseImpl.h
index cfc36d4..4b9ea41 100644
--- a/src/IceInstX86BaseImpl.h
+++ b/src/IceInstX86BaseImpl.h
@@ -2025,6 +2025,11 @@
void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
+ if (auto *Add = this->deoptLeaToAddOrNull(Func)) {
+ Add->emit(Func);
+ return;
+ }
+
Ostream &Str = Func->getContext()->getStrEmit();
assert(this->getSrcSize() == 1);
assert(this->getDest()->hasReg());
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index a3df730..1562e4e 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -2187,11 +2187,25 @@
case InstArithmetic::_num:
llvm_unreachable("Unknown arithmetic operator");
break;
- case InstArithmetic::Add:
+ case InstArithmetic::Add: {
+ const bool ValidType =
+ Ty == IceType_i32 || (Ty == IceType_i64 && Traits::Is64Bit);
+ auto *Const = llvm::dyn_cast<Constant>(Instr->getSrc(1));
+ const bool ValidKind =
+ Const != nullptr && (llvm::isa<ConstantInteger32>(Const) ||
+ llvm::isa<ConstantRelocatable>(Const));
+ if (getFlags().getAggressiveLea() && ValidType && ValidKind) {
+ auto *Var = legalizeToReg(Src0);
+ auto *Mem = Traits::X86OperandMem::create(Func, IceType_void, Var, Const);
+ T = makeReg(Ty);
+ _lea(T, _sandbox_mem_reference(Mem));
+ _mov(Dest, T);
+ break;
+ }
_mov(T, Src0);
_add(T, Src1);
_mov(Dest, T);
- break;
+ } break;
case InstArithmetic::And:
_mov(T, Src0);
_and(T, Src1);