<div dir="ltr">To test this functionality we need tests with LEA instructions that are to be replaced with ADDs.<div>LEA is x86 specific instruction so it can't be coded in LLVM IR directly.</div><div>Also transformation is done after RAL and it's highly dependent on LEA's arguments.</div>
<div>To summarize there should be an ability to pass LEA as Machine Instruction with pre-allocated registers.</div><div>All other ways to make LEA from sequence of ADDs are very unreliable due to possible RAL changes.</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-05-20 13:17 GMT+04:00 Joey Gouly <span dir="ltr"><<a href="mailto:joey.gouly@arm.com" target="_blank">joey.gouly@arm.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
No tests?<br>
<div class="HOEnZb"><div class="h5"><br>
-----Original Message-----<br>
From: <a href="mailto:llvm-commits-bounces@cs.uiuc.edu">llvm-commits-bounces@cs.uiuc.edu</a><br>
[mailto:<a href="mailto:llvm-commits-bounces@cs.uiuc.edu">llvm-commits-bounces@cs.uiuc.edu</a>] On Behalf Of Alexey Volkov<br>
Sent: 20 May 2014 09:56<br>
To: <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
Subject: [llvm] r209198 - [X86] Tune LEA usage for Silvermont<br>
<br>
Author: volkalex<br>
Date: Tue May 20 03:55:50 2014<br>
New Revision: 209198<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=209198&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=209198&view=rev</a><br>
Log:<br>
[X86] Tune LEA usage for Silvermont<br>
<br>
According to Intel Software Optimization Manual on Silvermont in some cases<br>
LEA<br>
is better to be replaced with ADD instructions:<br>
"The rule of thumb for ADDs and LEAs is that it is justified to use LEA<br>
with a valid index and/or displacement for non-destructive destination<br>
purposes<br>
(especially useful for stack offset cases), or to use a SCALE.<br>
Otherwise, ADD(s) are preferable."<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D3826" target="_blank">http://reviews.llvm.org/D3826</a><br>
<br>
Modified:<br>
llvm/trunk/lib/Target/X86/X86.td<br>
llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp<br>
llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
llvm/trunk/lib/Target/X86/X86Subtarget.cpp<br>
llvm/trunk/lib/Target/X86/X86Subtarget.h<br>
llvm/trunk/lib/Target/X86/X86TargetMachine.cpp<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86.td<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=209
198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=209<br>
198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86.td (original)<br>
+++ llvm/trunk/lib/Target/X86/X86.td Tue May 20 03:55:50 2014<br>
@@ -166,6 +166,8 @@ def FeatureCallRegIndirect : SubtargetFe<br>
"Call register indirect">;<br>
def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true",<br>
"LEA instruction needs inputs at AG<br>
stage">;<br>
+def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true",<br>
+ "LEA instruction with certain arguments<br>
is slow">;<br>
<br>
<br>
//===----------------------------------------------------------------------=<br>
==//<br>
// X86 processors supported.<br>
@@ -226,6 +228,7 @@ def : ProcessorModel<"slm", SLMModel, [<br>
FeaturePCLMUL, FeatureAES,<br>
FeatureCallRegIndirect,<br>
FeaturePRFCHW,<br>
+ FeatureSlowLEA,<br>
FeatureSlowBTMem, FeatureFastUAMem]>;<br>
// "Arrandale" along with corei3 and corei5<br>
def : ProcessorModel<"corei7", SandyBridgeModel,<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FixupLEAs.c
pp?rev=209198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FixupLEAs.c<br>
pp?rev=209198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86FixupLEAs.cpp Tue May 20 03:55:50 2014<br>
@@ -57,6 +57,11 @@ namespace {<br>
void processInstruction(MachineBasicBlock::iterator& I,<br>
MachineFunction::iterator MFI);<br>
<br>
+ /// \brief Given a LEA instruction which is unprofitable<br>
+ /// on Silvermont try to replace it with an equivalent ADD instruction<br>
+ void processInstructionForSLM(MachineBasicBlock::iterator& I,<br>
+ MachineFunction::iterator MFI);<br>
+<br>
/// \brief Determine if an instruction references a machine register<br>
/// and, if so, whether it reads or writes the register.<br>
RegUsageState usesRegister(MachineOperand& p,<br>
@@ -86,7 +91,7 @@ namespace {<br>
private:<br>
MachineFunction *MF;<br>
const TargetMachine *TM;<br>
- const TargetInstrInfo *TII; // Machine instruction info.<br>
+ const X86InstrInfo *TII; // Machine instruction info.<br>
<br>
};<br>
char FixupLEAPass::ID = 0;<br>
@@ -98,7 +103,7 @@ FixupLEAPass::postRAConvertToLEA(Machine<br>
MachineInstr* MI = MBBI;<br>
MachineInstr* NewMI;<br>
switch (MI->getOpcode()) {<br>
- case X86::MOV32rr:<br>
+ case X86::MOV32rr:<br>
case X86::MOV64rr: {<br>
const MachineOperand& Src = MI->getOperand(1);<br>
const MachineOperand& Dest = MI->getOperand(0);<br>
@@ -146,7 +151,7 @@ FunctionPass *llvm::createX86FixupLEAs()<br>
bool FixupLEAPass::runOnMachineFunction(MachineFunction &Func) {<br>
MF = &Func;<br>
TM = &MF->getTarget();<br>
- TII = TM->getInstrInfo();<br>
+ TII = static_cast<const X86InstrInfo*>(TM->getInstrInfo());<br>
<br>
DEBUG(dbgs() << "Start X86FixupLEAs\n";);<br>
// Process all basic blocks.<br>
@@ -243,9 +248,9 @@ void FixupLEAPass::seekLEAFixup(MachineO<br>
MachineInstr* NewMI = postRAConvertToLEA(MFI, MBI);<br>
if (NewMI) {<br>
++NumLEAs;<br>
- DEBUG(dbgs() << "Candidate to replace:"; MBI->dump(););<br>
+ DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MBI->dump(););<br>
// now to replace with an equivalent LEA...<br>
- DEBUG(dbgs() << "Replaced by: "; NewMI->dump(););<br>
+ DEBUG(dbgs() << "FixLEA: Replaced by: "; NewMI->dump(););<br>
MFI->erase(MBI);<br>
MachineBasicBlock::iterator J =<br>
static_cast<MachineBasicBlock::iterator><br>
(NewMI);<br>
@@ -254,10 +259,80 @@ void FixupLEAPass::seekLEAFixup(MachineO<br>
}<br>
}<br>
<br>
+void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,<br>
+ MachineFunction::iterator MFI)<br>
{<br>
+ MachineInstr *MI = I;<br>
+ const int opcode = MI->getOpcode();<br>
+ if (opcode != X86::LEA16r && opcode != X86::LEA32r && opcode !=<br>
X86::LEA64r &&<br>
+ opcode != X86::LEA64_32r)<br>
+ return;<br>
+ if (MI->getOperand(5).getReg() != 0 || !MI->getOperand(4).isImm() ||<br>
+ !TII->isSafeToClobberEFLAGS(*MFI, I))<br>
+ return;<br>
+ const unsigned DstR = MI->getOperand(0).getReg();<br>
+ const unsigned SrcR1 = MI->getOperand(1).getReg();<br>
+ const unsigned SrcR2 = MI->getOperand(3).getReg();<br>
+ if ((SrcR1 == 0 || SrcR1 != DstR) && (SrcR2 == 0 || SrcR2 != DstR))<br>
+ return;<br>
+ if (MI->getOperand(2).getImm() > 1)<br>
+ return;<br>
+ int addrr_opcode, addri_opcode;<br>
+ switch (opcode) {<br>
+ case X86::LEA16r:<br>
+ addrr_opcode = X86::ADD16rr;<br>
+ addri_opcode = X86::ADD16ri;<br>
+ break;<br>
+ case X86::LEA32r:<br>
+ addrr_opcode = X86::ADD32rr;<br>
+ addri_opcode = X86::ADD32ri;<br>
+ break;<br>
+ case X86::LEA64_32r:<br>
+ case X86::LEA64r:<br>
+ addrr_opcode = X86::ADD64rr;<br>
+ addri_opcode = X86::ADD64ri32;<br>
+ break;<br>
+ default:<br>
+ assert(false && "Unexpected LEA instruction");<br>
+ }<br>
+ DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););<br>
+ DEBUG(dbgs() << "FixLEA: Replaced by: ";);<br>
+ MachineInstr *NewMI = 0;<br>
+ const MachineOperand &Dst = MI->getOperand(0);<br>
+ // Make ADD instruction for two registers writing to LEA's destination<br>
+ if (SrcR1 != 0 && SrcR2 != 0) {<br>
+ const MachineOperand &Src1 = MI->getOperand(SrcR1 == DstR ? 1 : 3);<br>
+ const MachineOperand &Src2 = MI->getOperand(SrcR1 == DstR ? 3 : 1);<br>
+ NewMI = BuildMI(*MF, MI->getDebugLoc(), TII->get(addrr_opcode))<br>
+ .addOperand(Dst)<br>
+ .addOperand(Src1)<br>
+ .addOperand(Src2);<br>
+ MFI->insert(I, NewMI);<br>
+ DEBUG(NewMI->dump(););<br>
+ }<br>
+ // Make ADD instruction for immediate<br>
+ if (MI->getOperand(4).getImm() != 0) {<br>
+ const MachineOperand &SrcR = MI->getOperand(SrcR1 == DstR ? 1 : 3);<br>
+ NewMI = BuildMI(*MF, MI->getDebugLoc(), TII->get(addri_opcode))<br>
+ .addOperand(Dst)<br>
+ .addOperand(SrcR)<br>
+ .addImm(MI->getOperand(4).getImm());<br>
+ MFI->insert(I, NewMI);<br>
+ DEBUG(NewMI->dump(););<br>
+ }<br>
+ if (NewMI) {<br>
+ MFI->erase(I);<br>
+ I = static_cast<MachineBasicBlock::iterator>(NewMI);<br>
+ }<br>
+}<br>
+<br>
bool FixupLEAPass::processBasicBlock(MachineFunction &MF,<br>
MachineFunction::iterator MFI) {<br>
<br>
- for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I)<br>
- processInstruction(I, MFI);<br>
+ for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I)<br>
{<br>
+ if (TM->getSubtarget<X86Subtarget>().isSLM())<br>
+ processInstructionForSLM(I, MFI);<br>
+ else<br>
+ processInstruction(I, MFI);<br>
+ }<br>
return false;<br>
}<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.c
pp?rev=209198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.c<br>
pp?rev=209198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue May 20 03:55:50 2014<br>
@@ -1728,12 +1728,8 @@ X86InstrInfo::isReallyTriviallyReMateria<br>
return true;<br>
}<br>
<br>
-/// isSafeToClobberEFLAGS - Return true if it's safe insert an instruction<br>
that<br>
-/// would clobber the EFLAGS condition register. Note the result may be<br>
-/// conservative. If it cannot definitely determine the safety after<br>
visiting<br>
-/// a few instructions in each direction it assumes it's not safe.<br>
-static bool isSafeToClobberEFLAGS(MachineBasicBlock &MBB,<br>
- MachineBasicBlock::iterator I) {<br>
+bool X86InstrInfo::isSafeToClobberEFLAGS(MachineBasicBlock &MBB,<br>
+ MachineBasicBlock::iterator I)<br>
const {<br>
MachineBasicBlock::iterator E = MBB.end();<br>
<br>
// For compile time consideration, if we are not able to determine the<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h
?rev=209198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
?rev=209198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Tue May 20 03:55:50 2014<br>
@@ -359,6 +359,13 @@ public:<br>
/// instruction that defines the specified register class.<br>
bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const<br>
override;<br>
<br>
+ /// isSafeToClobberEFLAGS - Return true if it's safe insert an<br>
instruction tha<br>
+ /// would clobber the EFLAGS condition register. Note the result may be<br>
+ /// conservative. If it cannot definitely determine the safety after<br>
visiting<br>
+ /// a few instructions in each direction it assumes it's not safe.<br>
+ bool isSafeToClobberEFLAGS(MachineBasicBlock &MBB,<br>
+ MachineBasicBlock::iterator I) const;<br>
+<br>
static bool isX86_64ExtendedReg(const MachineOperand &MO) {<br>
if (!MO.isReg()) return false;<br>
return X86II::isX86_64ExtendedReg(MO.getReg());<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.c
pp?rev=209198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.c<br>
pp?rev=209198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Tue May 20 03:55:50 2014<br>
@@ -282,6 +282,7 @@ void X86Subtarget::initializeEnvironment<br>
PadShortFunctions = false;<br>
CallRegIndirect = false;<br>
LEAUsesAG = false;<br>
+ SlowLEA = false;<br>
stackAlignment = 4;<br>
// FIXME: this is a known good value for Yonah. How about others?<br>
MaxInlineSizeThreshold = 128;<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86Subtarget.h<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h
?rev=209198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h<br>
?rev=209198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86Subtarget.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86Subtarget.h Tue May 20 03:55:50 2014<br>
@@ -178,6 +178,9 @@ protected:<br>
/// address generation (AG) time.<br>
bool LEAUsesAG;<br>
<br>
+ /// SlowLEA - True if the LEA instruction with certain arguments is slow<br>
+ bool SlowLEA;<br>
+<br>
/// Processor has AVX-512 PreFetch Instructions<br>
bool HasPFI;<br>
<br>
@@ -315,11 +318,13 @@ public:<br>
bool padShortFunctions() const { return PadShortFunctions; }<br>
bool callRegIndirect() const { return CallRegIndirect; }<br>
bool LEAusesAG() const { return LEAUsesAG; }<br>
+ bool slowLEA() const { return SlowLEA; }<br>
bool hasCDI() const { return HasCDI; }<br>
bool hasPFI() const { return HasPFI; }<br>
bool hasERI() const { return HasERI; }<br>
<br>
bool isAtom() const { return X86ProcFamily == IntelAtom; }<br>
+ bool isSLM() const { return X86ProcFamily == IntelSLM; }<br>
<br>
const Triple &getTargetTriple() const { return TargetTriple; }<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp<br>
URL:<br>
<a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachi
ne.cpp?rev=209198&r1=209197&r2=209198&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachi<br>
ne.cpp?rev=209198&r1=209197&r2=209198&view=diff</a><br>
============================================================================<br>
==<br>
--- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Tue May 20 03:55:50 2014<br>
@@ -226,7 +226,8 @@ bool X86PassConfig::addPreEmitPass() {<br>
ShouldPrint = true;<br>
}<br>
if (getOptLevel() != CodeGenOpt::None &&<br>
- getX86Subtarget().LEAusesAG()){<br>
+ (getX86Subtarget().LEAusesAG() ||<br>
+ getX86Subtarget().slowLEA())){<br>
addPass(createX86FixupLEAs());<br>
ShouldPrint = true;<br>
}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br>
<br>
<br>
<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div dir="ltr">Alexey Volkov<div>Intel Corporation</div></div>
</div>