<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>