blob: bbf57f9571d3c53ba177fddbeb7de2d1df1274e3 [file] [log] [blame]
Preston Gurd8b7ab4b2013-04-25 20:29:37 +00001//===-- X86FixupLEAs.cpp - use or replace LEA instructions -----------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Preston Gurd8b7ab4b2013-04-25 20:29:37 +00006//
7//===----------------------------------------------------------------------===//
8//
Sanjay Patel63604412014-07-16 20:18:49 +00009// This file defines the pass that finds instructions that can be
10// re-written as LEA instructions in order to reduce pipeline delays.
Michael Kuperstein12982a82015-11-11 11:44:31 +000011// When optimizing for size it replaces suitable LEAs with INC or DEC.
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000012//
13//===----------------------------------------------------------------------===//
14
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000015#include "X86.h"
16#include "X86InstrInfo.h"
17#include "X86Subtarget.h"
18#include "llvm/ADT/Statistic.h"
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000019#include "llvm/CodeGen/MachineFunctionPass.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000021#include "llvm/CodeGen/Passes.h"
Simon Pilgrima3a9d8122018-04-13 15:09:39 +000022#include "llvm/CodeGen/TargetSchedule.h"
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000023#include "llvm/Support/Debug.h"
24#include "llvm/Support/raw_ostream.h"
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000025using namespace llvm;
26
Lama Saba2ea271b2017-05-18 08:11:50 +000027#define FIXUPLEA_DESC "X86 LEA Fixup"
28#define FIXUPLEA_NAME "x86-fixup-LEAs"
29
30#define DEBUG_TYPE FIXUPLEA_NAME
Chandler Carruth84e68b22014-04-22 02:41:26 +000031
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000032STATISTIC(NumLEAs, "Number of LEA instructions created");
33
34namespace {
Eric Christopher31b81ce2014-06-03 21:01:35 +000035class FixupLEAPass : public MachineFunctionPass {
36 enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
Lama Saba2ea271b2017-05-18 08:11:50 +000037
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000038 /// Given a machine register, look for the instruction
Eric Christopher31b81ce2014-06-03 21:01:35 +000039 /// which writes it in the current basic block. If found,
40 /// try to replace it with an equivalent LEA instruction.
Eric Christopher572e03a2015-06-19 01:53:21 +000041 /// If replacement succeeds, then also process the newly created
Eric Christopher31b81ce2014-06-03 21:01:35 +000042 /// instruction.
43 void seekLEAFixup(MachineOperand &p, MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +000044 MachineBasicBlock &MBB);
Preston Gurd128920d2013-04-25 21:31:33 +000045
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000046 /// Given a memory access or LEA instruction
Eric Christopher31b81ce2014-06-03 21:01:35 +000047 /// whose address mode uses a base and/or index register, look for
48 /// an opportunity to replace the instruction which sets the base or index
49 /// register with an equivalent LEA instruction.
50 void processInstruction(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +000051 MachineBasicBlock &MBB);
Preston Gurd128920d2013-04-25 21:31:33 +000052
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000053 /// Given a LEA instruction which is unprofitable
Simon Pilgrimd5d72242018-11-01 14:57:07 +000054 /// on SlowLEA targets try to replace it with an equivalent ADD instruction.
55 void processInstructionForSlowLEA(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +000056 MachineBasicBlock &MBB);
Lama Saba2ea271b2017-05-18 08:11:50 +000057
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000058 /// Given a LEA instruction which is unprofitable
Lama Saba2ea271b2017-05-18 08:11:50 +000059 /// on SNB+ try to replace it with other instructions.
60 /// According to Intel's Optimization Reference Manual:
61 /// " For LEA instructions with three source operands and some specific
62 /// situations, instruction latency has increased to 3 cycles, and must
63 /// dispatch via port 1:
64 /// - LEA that has all three source operands: base, index, and offset
65 /// - LEA that uses base and index registers where the base is EBP, RBP,
66 /// or R13
67 /// - LEA that uses RIP relative addressing mode
68 /// - LEA that uses 16-bit addressing mode "
69 /// This function currently handles the first 2 cases only.
70 MachineInstr *processInstrForSlow3OpLEA(MachineInstr &MI,
Craig Topper965d1302019-04-30 17:56:28 +000071 MachineBasicBlock &MBB);
Lama Saba2ea271b2017-05-18 08:11:50 +000072
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000073 /// Look for LEAs that add 1 to reg or subtract 1 from reg
Michael Kuperstein12982a82015-11-11 11:44:31 +000074 /// and convert them to INC or DEC respectively.
75 bool fixupIncDec(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +000076 MachineBasicBlock &MBB) const;
Michael Kuperstein12982a82015-11-11 11:44:31 +000077
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000078 /// Determine if an instruction references a machine register
Eric Christopher31b81ce2014-06-03 21:01:35 +000079 /// and, if so, whether it reads or writes the register.
80 RegUsageState usesRegister(MachineOperand &p, MachineBasicBlock::iterator I);
Preston Gurd128920d2013-04-25 21:31:33 +000081
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000082 /// Step backwards through a basic block, looking
Eric Christopher31b81ce2014-06-03 21:01:35 +000083 /// for an instruction which writes a register within
84 /// a maximum of INSTR_DISTANCE_THRESHOLD instruction latency cycles.
85 MachineBasicBlock::iterator searchBackwards(MachineOperand &p,
86 MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +000087 MachineBasicBlock &MBB);
Preston Gurd128920d2013-04-25 21:31:33 +000088
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000089 /// if an instruction can be converted to an
Eric Christopher31b81ce2014-06-03 21:01:35 +000090 /// equivalent LEA, insert the new instruction into the basic block
91 /// and return a pointer to it. Otherwise, return zero.
Craig Topper965d1302019-04-30 17:56:28 +000092 MachineInstr *postRAConvertToLEA(MachineBasicBlock &MBB,
Eric Christopher31b81ce2014-06-03 21:01:35 +000093 MachineBasicBlock::iterator &MBBI) const;
Preston Gurd8b7ab4b2013-04-25 20:29:37 +000094
Eric Christopher31b81ce2014-06-03 21:01:35 +000095public:
Lama Saba2ea271b2017-05-18 08:11:50 +000096 static char ID;
97
98 StringRef getPassName() const override { return FIXUPLEA_DESC; }
99
100 FixupLEAPass() : MachineFunctionPass(ID) {
101 initializeFixupLEAPassPass(*PassRegistry::getPassRegistry());
102 }
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000103
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000104 /// Loop over all of the basic blocks,
Eric Christopher31b81ce2014-06-03 21:01:35 +0000105 /// replacing instructions by equivalent LEA instructions
106 /// if needed and when possible.
107 bool runOnMachineFunction(MachineFunction &MF) override;
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000108
Derek Schuff1dbf7a52016-04-04 17:09:25 +0000109 // This pass runs after regalloc and doesn't support VReg operands.
110 MachineFunctionProperties getRequiredProperties() const override {
111 return MachineFunctionProperties().set(
Matthias Braun1eb47362016-08-25 01:27:13 +0000112 MachineFunctionProperties::Property::NoVRegs);
Derek Schuff1dbf7a52016-04-04 17:09:25 +0000113 }
114
Eric Christopher31b81ce2014-06-03 21:01:35 +0000115private:
Simon Pilgrima3a9d8122018-04-13 15:09:39 +0000116 TargetSchedModel TSM;
Eric Christopher31b81ce2014-06-03 21:01:35 +0000117 const X86InstrInfo *TII; // Machine instruction info.
118};
Reid Kleckner0ad69fc2017-05-16 19:55:03 +0000119}
Lama Saba52e89252017-05-16 16:01:36 +0000120
Lama Saba2ea271b2017-05-18 08:11:50 +0000121char FixupLEAPass::ID = 0;
122
123INITIALIZE_PASS(FixupLEAPass, FIXUPLEA_NAME, FIXUPLEA_DESC, false, false)
124
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000125MachineInstr *
Craig Topper965d1302019-04-30 17:56:28 +0000126FixupLEAPass::postRAConvertToLEA(MachineBasicBlock &MBB,
Preston Gurd128920d2013-04-25 21:31:33 +0000127 MachineBasicBlock::iterator &MBBI) const {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000128 MachineInstr &MI = *MBBI;
129 switch (MI.getOpcode()) {
Alexey Volkov6226de62014-05-20 08:55:50 +0000130 case X86::MOV32rr:
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000131 case X86::MOV64rr: {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000132 const MachineOperand &Src = MI.getOperand(1);
133 const MachineOperand &Dest = MI.getOperand(0);
134 MachineInstr *NewMI =
Craig Topper965d1302019-04-30 17:56:28 +0000135 BuildMI(MBB, MBBI, MI.getDebugLoc(),
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000136 TII->get(MI.getOpcode() == X86::MOV32rr ? X86::LEA32r
137 : X86::LEA64r))
Diana Picus116bbab2017-01-13 09:58:52 +0000138 .add(Dest)
139 .add(Src)
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000140 .addImm(1)
141 .addReg(0)
142 .addImm(0)
143 .addReg(0);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000144 return NewMI;
145 }
Craig Topperffd86622019-04-02 20:52:10 +0000146 }
147
148 if (!MI.isConvertibleTo3Addr())
149 return nullptr;
150
151 switch (MI.getOpcode()) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000152 case X86::ADD64ri32:
153 case X86::ADD64ri8:
154 case X86::ADD64ri32_DB:
155 case X86::ADD64ri8_DB:
156 case X86::ADD32ri:
157 case X86::ADD32ri8:
158 case X86::ADD32ri_DB:
159 case X86::ADD32ri8_DB:
160 case X86::ADD16ri:
161 case X86::ADD16ri8:
162 case X86::ADD16ri_DB:
163 case X86::ADD16ri8_DB:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000164 if (!MI.getOperand(2).isImm()) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000165 // convertToThreeAddress will call getImm()
166 // which requires isImm() to be true
Craig Topper062a2ba2014-04-25 05:30:21 +0000167 return nullptr;
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000168 }
Preston Gurdf03a6e72013-09-30 23:51:22 +0000169 break;
Preston Gurdf0b62882013-09-30 23:18:42 +0000170 case X86::ADD16rr:
171 case X86::ADD16rr_DB:
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000172 if (MI.getOperand(1).getReg() != MI.getOperand(2).getReg()) {
Preston Gurdf0b62882013-09-30 23:18:42 +0000173 // if src1 != src2, then convertToThreeAddress will
174 // need to create a Virtual register, which we cannot do
175 // after register allocation.
Craig Topper062a2ba2014-04-25 05:30:21 +0000176 return nullptr;
Preston Gurdf0b62882013-09-30 23:18:42 +0000177 }
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000178 }
Craig Topper965d1302019-04-30 17:56:28 +0000179 MachineFunction::iterator MFI = MBB.getIterator();
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000180 return TII->convertToThreeAddress(MFI, MI, nullptr);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000181}
182
Eric Christopher31b81ce2014-06-03 21:01:35 +0000183FunctionPass *llvm::createX86FixupLEAs() { return new FixupLEAPass(); }
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000184
Craig Topperdd66ace2019-05-01 06:53:03 +0000185static bool isLEA(unsigned Opcode) {
Craig Topperbf292382019-05-02 22:46:23 +0000186 return Opcode == X86::LEA32r || Opcode == X86::LEA64r ||
187 Opcode == X86::LEA64_32r;
Craig Topperdd66ace2019-05-01 06:53:03 +0000188}
189
Craig Topper965d1302019-04-30 17:56:28 +0000190bool FixupLEAPass::runOnMachineFunction(MachineFunction &MF) {
191 if (skipFunction(MF.getFunction()))
Andrew Kaylor2bee5ef2016-04-26 21:44:24 +0000192 return false;
193
Craig Topper965d1302019-04-30 17:56:28 +0000194 const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
Andrea Di Biagio4ae974e2018-11-07 12:26:00 +0000195 bool IsSlowLEA = ST.slowLEA();
196 bool IsSlow3OpsLEA = ST.slow3OpsLEA();
Craig Topper965d1302019-04-30 17:56:28 +0000197 bool LEAUsesAG = ST.LEAusesAG();
Andrea Di Biagio4ae974e2018-11-07 12:26:00 +0000198
Craig Topper965d1302019-04-30 17:56:28 +0000199 bool OptIncDec = !ST.slowIncDec() || MF.getFunction().hasOptSize();
200 bool OptLEA = LEAUsesAG || IsSlowLEA || IsSlow3OpsLEA;
Michael Kuperstein12982a82015-11-11 11:44:31 +0000201
202 if (!OptLEA && !OptIncDec)
Eric Christopher0d5c99e2014-05-22 01:46:02 +0000203 return false;
204
Craig Topper965d1302019-04-30 17:56:28 +0000205 TSM.init(&ST);
Eric Christopherd361ff82015-02-05 19:27:01 +0000206 TII = ST.getInstrInfo();
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000207
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000208 LLVM_DEBUG(dbgs() << "Start X86FixupLEAs\n";);
Craig Topper965d1302019-04-30 17:56:28 +0000209 for (MachineBasicBlock &MBB : MF) {
210 // First pass. Try to remove or optimize existing LEAs.
211 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
Craig Topperdd66ace2019-05-01 06:53:03 +0000212 if (!isLEA(I->getOpcode()))
213 continue;
214
Craig Topper965d1302019-04-30 17:56:28 +0000215 if (OptIncDec && fixupIncDec(I, MBB))
216 continue;
217
218 if (IsSlowLEA) {
219 processInstructionForSlowLEA(I, MBB);
220 } else if (IsSlow3OpsLEA) {
221 if (auto *NewMI = processInstrForSlow3OpLEA(*I, MBB)) {
222 MBB.erase(I);
223 I = NewMI;
224 }
225 }
226 }
227
228 // Second pass for creating LEAs. This may reverse some of the
229 // transformations above.
230 if (LEAUsesAG) {
231 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
232 processInstruction(I, MBB);
233 }
234 }
235
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000236 LLVM_DEBUG(dbgs() << "End X86FixupLEAs\n";);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000237
238 return true;
239}
240
Eric Christopher31b81ce2014-06-03 21:01:35 +0000241FixupLEAPass::RegUsageState
242FixupLEAPass::usesRegister(MachineOperand &p, MachineBasicBlock::iterator I) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000243 RegUsageState RegUsage = RU_NotUsed;
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000244 MachineInstr &MI = *I;
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000245
Craig Topperc5903c92019-04-02 00:50:58 +0000246 for (unsigned i = 0; i < MI.getNumOperands(); ++i) {
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000247 MachineOperand &opnd = MI.getOperand(i);
Eric Christopher31b81ce2014-06-03 21:01:35 +0000248 if (opnd.isReg() && opnd.getReg() == p.getReg()) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000249 if (opnd.isDef())
250 return RU_Write;
251 RegUsage = RU_Read;
252 }
253 }
254 return RegUsage;
255}
256
257/// getPreviousInstr - Given a reference to an instruction in a basic
258/// block, return a reference to the previous instruction in the block,
259/// wrapping around to the last instruction of the block if the block
260/// branches to itself.
Eric Christopher31b81ce2014-06-03 21:01:35 +0000261static inline bool getPreviousInstr(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +0000262 MachineBasicBlock &MBB) {
263 if (I == MBB.begin()) {
264 if (MBB.isPredecessor(&MBB)) {
265 I = --MBB.end();
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000266 return true;
Eric Christopher31b81ce2014-06-03 21:01:35 +0000267 } else
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000268 return false;
269 }
270 --I;
271 return true;
272}
273
Eric Christopher31b81ce2014-06-03 21:01:35 +0000274MachineBasicBlock::iterator
275FixupLEAPass::searchBackwards(MachineOperand &p, MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +0000276 MachineBasicBlock &MBB) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000277 int InstrDistance = 1;
278 MachineBasicBlock::iterator CurInst;
279 static const int INSTR_DISTANCE_THRESHOLD = 5;
280
281 CurInst = I;
282 bool Found;
Craig Topper965d1302019-04-30 17:56:28 +0000283 Found = getPreviousInstr(CurInst, MBB);
Eric Christopher31b81ce2014-06-03 21:01:35 +0000284 while (Found && I != CurInst) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000285 if (CurInst->isCall() || CurInst->isInlineAsm())
286 break;
287 if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
288 break; // too far back to make a difference
Eric Christopher31b81ce2014-06-03 21:01:35 +0000289 if (usesRegister(p, CurInst) == RU_Write) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000290 return CurInst;
291 }
Simon Pilgrima3a9d8122018-04-13 15:09:39 +0000292 InstrDistance += TSM.computeInstrLatency(&*CurInst);
Craig Topper965d1302019-04-30 17:56:28 +0000293 Found = getPreviousInstr(CurInst, MBB);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000294 }
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000295 return MachineBasicBlock::iterator();
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000296}
297
Craig Topperc5903c92019-04-02 00:50:58 +0000298static inline bool isInefficientLEAReg(unsigned Reg) {
Craig Topperb2cc9a12018-08-03 03:45:19 +0000299 return Reg == X86::EBP || Reg == X86::RBP ||
300 Reg == X86::R13D || Reg == X86::R13;
Lama Saba2ea271b2017-05-18 08:11:50 +0000301}
302
303static inline bool isRegOperand(const MachineOperand &Op) {
304 return Op.isReg() && Op.getReg() != X86::NoRegister;
305}
Andrea Di Biagio4ae974e2018-11-07 12:26:00 +0000306
307/// Returns true if this LEA uses base an index registers, and the base register
308/// is known to be inefficient for the subtarget.
Andrea Di Biagiob6022aa2018-07-19 16:42:15 +0000309// TODO: use a variant scheduling class to model the latency profile
310// of LEA instructions, and implement this logic as a scheduling predicate.
Lama Saba2ea271b2017-05-18 08:11:50 +0000311static inline bool hasInefficientLEABaseReg(const MachineOperand &Base,
312 const MachineOperand &Index) {
313 return Base.isReg() && isInefficientLEAReg(Base.getReg()) &&
314 isRegOperand(Index);
315}
316
317static inline bool hasLEAOffset(const MachineOperand &Offset) {
318 return (Offset.isImm() && Offset.getImm() != 0) || Offset.isGlobal();
319}
320
Craig Topperc5903c92019-04-02 00:50:58 +0000321static inline unsigned getADDrrFromLEA(unsigned LEAOpcode) {
Lama Saba2ea271b2017-05-18 08:11:50 +0000322 switch (LEAOpcode) {
323 default:
324 llvm_unreachable("Unexpected LEA instruction");
Lama Saba2ea271b2017-05-18 08:11:50 +0000325 case X86::LEA32r:
326 return X86::ADD32rr;
327 case X86::LEA64_32r:
328 case X86::LEA64r:
329 return X86::ADD64rr;
330 }
331}
332
Craig Topperc5903c92019-04-02 00:50:58 +0000333static inline unsigned getADDriFromLEA(unsigned LEAOpcode,
334 const MachineOperand &Offset) {
Lama Saba2ea271b2017-05-18 08:11:50 +0000335 bool IsInt8 = Offset.isImm() && isInt<8>(Offset.getImm());
336 switch (LEAOpcode) {
337 default:
338 llvm_unreachable("Unexpected LEA instruction");
Lama Saba2ea271b2017-05-18 08:11:50 +0000339 case X86::LEA32r:
340 case X86::LEA64_32r:
341 return IsInt8 ? X86::ADD32ri8 : X86::ADD32ri;
342 case X86::LEA64r:
343 return IsInt8 ? X86::ADD64ri8 : X86::ADD64ri32;
344 }
Michael Kuperstein12982a82015-11-11 11:44:31 +0000345}
346
347/// isLEASimpleIncOrDec - Does this LEA have one these forms:
348/// lea %reg, 1(%reg)
349/// lea %reg, -1(%reg)
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000350static inline bool isLEASimpleIncOrDec(MachineInstr &LEA) {
351 unsigned SrcReg = LEA.getOperand(1 + X86::AddrBaseReg).getReg();
352 unsigned DstReg = LEA.getOperand(0).getReg();
Craig Topper1f02ac32018-12-22 01:34:47 +0000353 const MachineOperand &AddrDisp = LEA.getOperand(1 + X86::AddrDisp);
Michael Kuperstein12982a82015-11-11 11:44:31 +0000354 return SrcReg == DstReg &&
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000355 LEA.getOperand(1 + X86::AddrIndexReg).getReg() == 0 &&
356 LEA.getOperand(1 + X86::AddrSegmentReg).getReg() == 0 &&
Craig Topper1f02ac32018-12-22 01:34:47 +0000357 AddrDisp.isImm() &&
358 (AddrDisp.getImm() == 1 || AddrDisp.getImm() == -1);
Michael Kuperstein12982a82015-11-11 11:44:31 +0000359}
360
361bool FixupLEAPass::fixupIncDec(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +0000362 MachineBasicBlock &MBB) const {
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000363 MachineInstr &MI = *I;
Michael Kuperstein12982a82015-11-11 11:44:31 +0000364
Craig Topper965d1302019-04-30 17:56:28 +0000365 if (isLEASimpleIncOrDec(MI) && TII->isSafeToClobberEFLAGS(MBB, I)) {
Craig Topperc5903c92019-04-02 00:50:58 +0000366 unsigned NewOpcode;
Craig Topper1f02ac32018-12-22 01:34:47 +0000367 bool isINC = MI.getOperand(1 + X86::AddrDisp).getImm() == 1;
Craig Topperdd66ace2019-05-01 06:53:03 +0000368 switch (MI.getOpcode()) {
Michael Kuperstein12982a82015-11-11 11:44:31 +0000369 case X86::LEA32r:
370 case X86::LEA64_32r:
371 NewOpcode = isINC ? X86::INC32r : X86::DEC32r;
372 break;
373 case X86::LEA64r:
374 NewOpcode = isINC ? X86::INC64r : X86::DEC64r;
375 break;
376 }
377
378 MachineInstr *NewMI =
Craig Topper965d1302019-04-30 17:56:28 +0000379 BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode))
Diana Picus116bbab2017-01-13 09:58:52 +0000380 .add(MI.getOperand(0))
Craig Topper1f02ac32018-12-22 01:34:47 +0000381 .add(MI.getOperand(1 + X86::AddrBaseReg));
Craig Topper965d1302019-04-30 17:56:28 +0000382 MBB.erase(I);
Michael Kuperstein12982a82015-11-11 11:44:31 +0000383 I = static_cast<MachineBasicBlock::iterator>(NewMI);
384 return true;
385 }
386 return false;
387}
388
Eric Christopher31b81ce2014-06-03 21:01:35 +0000389void FixupLEAPass::processInstruction(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +0000390 MachineBasicBlock &MBB) {
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000391 // Process a load, store, or LEA instruction.
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000392 MachineInstr &MI = *I;
393 const MCInstrDesc &Desc = MI.getDesc();
Craig Topper477649a2016-04-28 05:58:46 +0000394 int AddrOffset = X86II::getMemoryOperandNo(Desc.TSFlags);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000395 if (AddrOffset >= 0) {
396 AddrOffset += X86II::getOperandBias(Desc);
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000397 MachineOperand &p = MI.getOperand(AddrOffset + X86::AddrBaseReg);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000398 if (p.isReg() && p.getReg() != X86::ESP) {
Craig Topper965d1302019-04-30 17:56:28 +0000399 seekLEAFixup(p, I, MBB);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000400 }
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000401 MachineOperand &q = MI.getOperand(AddrOffset + X86::AddrIndexReg);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000402 if (q.isReg() && q.getReg() != X86::ESP) {
Craig Topper965d1302019-04-30 17:56:28 +0000403 seekLEAFixup(q, I, MBB);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000404 }
405 }
406}
407
Eric Christopher31b81ce2014-06-03 21:01:35 +0000408void FixupLEAPass::seekLEAFixup(MachineOperand &p,
409 MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +0000410 MachineBasicBlock &MBB) {
411 MachineBasicBlock::iterator MBI = searchBackwards(p, I, MBB);
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000412 if (MBI != MachineBasicBlock::iterator()) {
Craig Topper965d1302019-04-30 17:56:28 +0000413 MachineInstr *NewMI = postRAConvertToLEA(MBB, MBI);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000414 if (NewMI) {
415 ++NumLEAs;
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000416 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MBI->dump(););
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000417 // now to replace with an equivalent LEA...
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000418 LLVM_DEBUG(dbgs() << "FixLEA: Replaced by: "; NewMI->dump(););
Craig Topper965d1302019-04-30 17:56:28 +0000419 MBB.erase(MBI);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000420 MachineBasicBlock::iterator J =
Eric Christopher31b81ce2014-06-03 21:01:35 +0000421 static_cast<MachineBasicBlock::iterator>(NewMI);
Craig Topper965d1302019-04-30 17:56:28 +0000422 processInstruction(J, MBB);
Preston Gurd8b7ab4b2013-04-25 20:29:37 +0000423 }
424 }
425}
426
Simon Pilgrimd5d72242018-11-01 14:57:07 +0000427void FixupLEAPass::processInstructionForSlowLEA(MachineBasicBlock::iterator &I,
Craig Topper965d1302019-04-30 17:56:28 +0000428 MachineBasicBlock &MBB) {
Duncan P. N. Exon Smith7b4c18e2016-07-12 03:18:50 +0000429 MachineInstr &MI = *I;
Craig Topperc5903c92019-04-02 00:50:58 +0000430 const unsigned Opcode = MI.getOpcode();
Craig Topper1f02ac32018-12-22 01:34:47 +0000431
432 const MachineOperand &Dst = MI.getOperand(0);
433 const MachineOperand &Base = MI.getOperand(1 + X86::AddrBaseReg);
434 const MachineOperand &Scale = MI.getOperand(1 + X86::AddrScaleAmt);
435 const MachineOperand &Index = MI.getOperand(1 + X86::AddrIndexReg);
436 const MachineOperand &Offset = MI.getOperand(1 + X86::AddrDisp);
437 const MachineOperand &Segment = MI.getOperand(1 + X86::AddrSegmentReg);
438
439 if (Segment.getReg() != 0 || !Offset.isImm() ||
Craig Topper965d1302019-04-30 17:56:28 +0000440 !TII->isSafeToClobberEFLAGS(MBB, I))
Alexey Volkov6226de62014-05-20 08:55:50 +0000441 return;
Craig Topper1f02ac32018-12-22 01:34:47 +0000442 const unsigned DstR = Dst.getReg();
443 const unsigned SrcR1 = Base.getReg();
444 const unsigned SrcR2 = Index.getReg();
Alexey Volkov6226de62014-05-20 08:55:50 +0000445 if ((SrcR1 == 0 || SrcR1 != DstR) && (SrcR2 == 0 || SrcR2 != DstR))
446 return;
Craig Topper1f02ac32018-12-22 01:34:47 +0000447 if (Scale.getImm() > 1)
Alexey Volkov6226de62014-05-20 08:55:50 +0000448 return;
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000449 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););
450 LLVM_DEBUG(dbgs() << "FixLEA: Replaced by: ";);
Craig Topper66f09ad2014-06-08 22:29:17 +0000451 MachineInstr *NewMI = nullptr;
Alexey Volkov6226de62014-05-20 08:55:50 +0000452 // Make ADD instruction for two registers writing to LEA's destination
453 if (SrcR1 != 0 && SrcR2 != 0) {
Lama Saba2ea271b2017-05-18 08:11:50 +0000454 const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(Opcode));
Craig Topper1f02ac32018-12-22 01:34:47 +0000455 const MachineOperand &Src = SrcR1 == DstR ? Index : Base;
Lama Saba2ea271b2017-05-18 08:11:50 +0000456 NewMI =
Craig Topper965d1302019-04-30 17:56:28 +0000457 BuildMI(MBB, I, MI.getDebugLoc(), ADDrr, DstR).addReg(DstR).add(Src);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000458 LLVM_DEBUG(NewMI->dump(););
Alexey Volkov6226de62014-05-20 08:55:50 +0000459 }
460 // Make ADD instruction for immediate
Craig Topper1f02ac32018-12-22 01:34:47 +0000461 if (Offset.getImm() != 0) {
Lama Saba2ea271b2017-05-18 08:11:50 +0000462 const MCInstrDesc &ADDri =
Craig Topper1f02ac32018-12-22 01:34:47 +0000463 TII->get(getADDriFromLEA(Opcode, Offset));
464 const MachineOperand &SrcR = SrcR1 == DstR ? Base : Index;
Craig Topper965d1302019-04-30 17:56:28 +0000465 NewMI = BuildMI(MBB, I, MI.getDebugLoc(), ADDri, DstR)
Diana Picus116bbab2017-01-13 09:58:52 +0000466 .add(SrcR)
Craig Topper1f02ac32018-12-22 01:34:47 +0000467 .addImm(Offset.getImm());
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000468 LLVM_DEBUG(NewMI->dump(););
Alexey Volkov6226de62014-05-20 08:55:50 +0000469 }
470 if (NewMI) {
Craig Topper965d1302019-04-30 17:56:28 +0000471 MBB.erase(I);
Lama Saba2ea271b2017-05-18 08:11:50 +0000472 I = NewMI;
Alexey Volkov6226de62014-05-20 08:55:50 +0000473 }
474}
475
Lama Saba2ea271b2017-05-18 08:11:50 +0000476MachineInstr *
477FixupLEAPass::processInstrForSlow3OpLEA(MachineInstr &MI,
Craig Topper965d1302019-04-30 17:56:28 +0000478 MachineBasicBlock &MBB) {
Craig Topperc5903c92019-04-02 00:50:58 +0000479 const unsigned LEAOpcode = MI.getOpcode();
Lama Saba2ea271b2017-05-18 08:11:50 +0000480
Craig Topper1f02ac32018-12-22 01:34:47 +0000481 const MachineOperand &Dst = MI.getOperand(0);
482 const MachineOperand &Base = MI.getOperand(1 + X86::AddrBaseReg);
483 const MachineOperand &Scale = MI.getOperand(1 + X86::AddrScaleAmt);
484 const MachineOperand &Index = MI.getOperand(1 + X86::AddrIndexReg);
485 const MachineOperand &Offset = MI.getOperand(1 + X86::AddrDisp);
486 const MachineOperand &Segment = MI.getOperand(1 + X86::AddrSegmentReg);
Lama Saba2ea271b2017-05-18 08:11:50 +0000487
Andrea Di Biagiob6022aa2018-07-19 16:42:15 +0000488 if (!(TII->isThreeOperandsLEA(MI) ||
Lama Saba2ea271b2017-05-18 08:11:50 +0000489 hasInefficientLEABaseReg(Base, Index)) ||
Craig Topper965d1302019-04-30 17:56:28 +0000490 !TII->isSafeToClobberEFLAGS(MBB, MI) ||
Lama Saba2ea271b2017-05-18 08:11:50 +0000491 Segment.getReg() != X86::NoRegister)
492 return nullptr;
493
Craig Topperc5903c92019-04-02 00:50:58 +0000494 unsigned DstR = Dst.getReg();
495 unsigned BaseR = Base.getReg();
496 unsigned IndexR = Index.getReg();
Lama Saba2ea271b2017-05-18 08:11:50 +0000497 unsigned SSDstR =
498 (LEAOpcode == X86::LEA64_32r) ? getX86SubSuperRegister(DstR, 64) : DstR;
499 bool IsScale1 = Scale.getImm() == 1;
500 bool IsInefficientBase = isInefficientLEAReg(BaseR);
501 bool IsInefficientIndex = isInefficientLEAReg(IndexR);
502
503 // Skip these cases since it takes more than 2 instructions
504 // to replace the LEA instruction.
505 if (IsInefficientBase && SSDstR == BaseR && !IsScale1)
506 return nullptr;
507 if (LEAOpcode == X86::LEA64_32r && IsInefficientBase &&
508 (IsInefficientIndex || !IsScale1))
509 return nullptr;
510
511 const DebugLoc DL = MI.getDebugLoc();
512 const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(LEAOpcode));
513 const MCInstrDesc &ADDri = TII->get(getADDriFromLEA(LEAOpcode, Offset));
514
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000515 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MI.dump(););
516 LLVM_DEBUG(dbgs() << "FixLEA: Replaced by: ";);
Lama Saba2ea271b2017-05-18 08:11:50 +0000517
518 // First try to replace LEA with one or two (for the 3-op LEA case)
519 // add instructions:
520 // 1.lea (%base,%index,1), %base => add %index,%base
521 // 2.lea (%base,%index,1), %index => add %base,%index
522 if (IsScale1 && (DstR == BaseR || DstR == IndexR)) {
523 const MachineOperand &Src = DstR == BaseR ? Index : Base;
524 MachineInstr *NewMI =
Craig Topper965d1302019-04-30 17:56:28 +0000525 BuildMI(MBB, MI, DL, ADDrr, DstR).addReg(DstR).add(Src);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000526 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000527 // Create ADD instruction for the Offset in case of 3-Ops LEA.
528 if (hasLEAOffset(Offset)) {
Craig Topper965d1302019-04-30 17:56:28 +0000529 NewMI = BuildMI(MBB, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000530 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000531 }
532 return NewMI;
533 }
534 // If the base is inefficient try switching the index and base operands,
535 // otherwise just break the 3-Ops LEA inst into 2-Ops LEA + ADD instruction:
536 // lea offset(%base,%index,scale),%dst =>
537 // lea (%base,%index,scale); add offset,%dst
538 if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
Craig Topper965d1302019-04-30 17:56:28 +0000539 MachineInstr *NewMI = BuildMI(MBB, MI, DL, TII->get(LEAOpcode))
Lama Saba2ea271b2017-05-18 08:11:50 +0000540 .add(Dst)
541 .add(IsInefficientBase ? Index : Base)
542 .add(Scale)
543 .add(IsInefficientBase ? Base : Index)
544 .addImm(0)
545 .add(Segment);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000546 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000547 // Create ADD instruction for the Offset in case of 3-Ops LEA.
548 if (hasLEAOffset(Offset)) {
Craig Topper965d1302019-04-30 17:56:28 +0000549 NewMI = BuildMI(MBB, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000550 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000551 }
552 return NewMI;
553 }
554 // Handle the rest of the cases with inefficient base register:
555 assert(SSDstR != BaseR && "SSDstR == BaseR should be handled already!");
556 assert(IsInefficientBase && "efficient base should be handled already!");
557
558 // lea (%base,%index,1), %dst => mov %base,%dst; add %index,%dst
559 if (IsScale1 && !hasLEAOffset(Offset)) {
Serguei Katkov1ce71372018-01-26 04:49:26 +0000560 bool BIK = Base.isKill() && BaseR != IndexR;
Craig Topper965d1302019-04-30 17:56:28 +0000561 TII->copyPhysReg(MBB, MI, DL, DstR, BaseR, BIK);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000562 LLVM_DEBUG(MI.getPrevNode()->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000563
564 MachineInstr *NewMI =
Craig Topper965d1302019-04-30 17:56:28 +0000565 BuildMI(MBB, MI, DL, ADDrr, DstR).addReg(DstR).add(Index);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000566 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000567 return NewMI;
568 }
569 // lea offset(%base,%index,scale), %dst =>
570 // lea offset( ,%index,scale), %dst; add %base,%dst
Craig Topper965d1302019-04-30 17:56:28 +0000571 MachineInstr *NewMI = BuildMI(MBB, MI, DL, TII->get(LEAOpcode))
Lama Saba2ea271b2017-05-18 08:11:50 +0000572 .add(Dst)
573 .addReg(0)
574 .add(Scale)
575 .add(Index)
576 .add(Offset)
577 .add(Segment);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000578 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000579
Craig Topper965d1302019-04-30 17:56:28 +0000580 NewMI = BuildMI(MBB, MI, DL, ADDrr, DstR).addReg(DstR).add(Base);
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000581 LLVM_DEBUG(NewMI->dump(););
Lama Saba2ea271b2017-05-18 08:11:50 +0000582 return NewMI;
583}