LLVM: lib/Target/X86/X86FixupLEAs.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
28using namespace llvm;
29
30#define FIXUPLEA_DESC "X86 LEA Fixup"
31#define FIXUPLEA_NAME "x86-fixup-LEAs"
32
33#define DEBUG_TYPE FIXUPLEA_NAME
34
35STATISTIC(NumLEAs, "Number of LEA instructions created");
36
37namespace {
39 enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
40
41
42
43
44
45
47 MachineBasicBlock &MBB);
48
49
50
51
52
54 MachineBasicBlock &MBB);
55
56
57
59 MachineBasicBlock &MBB);
60
61
62
63
64
65
66
67
68
69
70
71
72
74 MachineBasicBlock &MBB, bool OptIncDec);
75
76
77
79 MachineBasicBlock &MBB, bool OptIncDec,
80 bool UseLEAForSP) const;
81
82
83
84
85
86
87
88
90
91
92
94 MachineBasicBlock &MBB) const;
95
96
97
98
99
100
103 bool &AluDestRef, MachineOperand **KilledBase,
104 MachineOperand **KilledIndex) const;
105
106
107
109
110
111
112
115 MachineBasicBlock &MBB);
116
117
118
119
120 MachineInstr *postRAConvertToLEA(MachineBasicBlock &MBB,
122
123public:
124 static char ID;
125
126 StringRef getPassName() const override { return FIXUPLEA_DESC; }
127
128 FixupLEAPass() : MachineFunctionPass(ID) { }
129
130
131
132
133 bool runOnMachineFunction(MachineFunction &MF) override;
134
135
136 MachineFunctionProperties getRequiredProperties() const override {
137 return MachineFunctionProperties().setNoVRegs();
138 }
139
140 void getAnalysisUsage(AnalysisUsage &AU) const override {
141 AU.addRequired();
142 AU.addRequired();
144 }
145
146private:
147 TargetSchedModel TSM;
148 const X86InstrInfo *TII = nullptr;
149 const X86RegisterInfo *TRI = nullptr;
150};
151}
152
153char FixupLEAPass::ID = 0;
154
156
161 switch (MI.getOpcode()) {
162 case X86::MOV32rr:
163 case X86::MOV64rr: {
164 const MachineOperand &Src = MI.getOperand(1);
165 const MachineOperand &Dest = MI.getOperand(0);
166 MachineInstr *NewMI =
167 BuildMI(MBB, MBBI, MI.getDebugLoc(),
168 TII->get(MI.getOpcode() == X86::MOV32rr ? X86::LEA32r
169 : X86::LEA64r))
170 .add(Dest)
171 .add(Src)
172 .addImm(1)
173 .addReg(0)
174 .addImm(0)
175 .addReg(0);
176 return NewMI;
177 }
178 }
179
180 if (.isConvertibleTo3Addr())
181 return nullptr;
182
183 switch (MI.getOpcode()) {
184 default:
185
186 return nullptr;
187 case X86::ADD64ri32:
188 case X86::ADD64ri32_DB:
189 case X86::ADD32ri:
190 case X86::ADD32ri_DB:
191 if (!MI.getOperand(2).isImm()) {
192
193
194 return nullptr;
195 }
196 break;
197 case X86::SHL64ri:
198 case X86::SHL32ri:
199 case X86::INC64r:
200 case X86::INC32r:
201 case X86::DEC64r:
202 case X86::DEC32r:
203 case X86::ADD64rr:
204 case X86::ADD64rr_DB:
205 case X86::ADD32rr:
206 case X86::ADD32rr_DB:
207
208 break;
209 }
210 return TII->convertToThreeAddress(MI, nullptr, nullptr);
211}
212
214
215static bool isLEA(unsigned Opcode) {
216 return Opcode == X86::LEA32r || Opcode == X86::LEA64r ||
217 Opcode == X86::LEA64_32r;
218}
219
220bool FixupLEAPass::runOnMachineFunction(MachineFunction &MF) {
222 return false;
223
224 const X86Subtarget &ST = MF.getSubtarget();
225 bool IsSlowLEA = ST.slowLEA();
226 bool IsSlow3OpsLEA = ST.slow3OpsLEA();
227 bool LEAUsesAG = ST.leaUsesAG();
228
230 bool UseLEAForSP = ST.useLeaForSP();
231
232 TSM.init(&ST);
234 TRI = ST.getRegisterInfo();
235 auto *PSI = &getAnalysis().getPSI();
236 auto *MBFI = (PSI && PSI->hasProfileSummary())
237 ? &getAnalysis().getBFI()
238 : nullptr;
239
241 for (MachineBasicBlock &MBB : MF) {
242
243 bool OptIncDecPerBB =
246 if ((I->getOpcode()))
247 continue;
248
249 if (optTwoAddrLEA(I, MBB, OptIncDecPerBB, UseLEAForSP))
250 continue;
251
252 if (IsSlowLEA)
253 processInstructionForSlowLEA(I, MBB);
254 else if (IsSlow3OpsLEA)
255 processInstrForSlow3OpLEA(I, MBB, OptIncDecPerBB);
256 }
257
258
259
260 if (LEAUsesAG) {
262 processInstruction(I, MBB);
263 }
264 }
265
267
268 return true;
269}
270
271FixupLEAPass::RegUsageState
273 RegUsageState RegUsage = RU_NotUsed;
275
276 for (const MachineOperand &MO : MI.operands()) {
277 if (MO.isReg() && MO.getReg() == p.getReg()) {
278 if (MO.isDef())
279 return RU_Write;
281 }
282 }
284}
285
286
287
288
289
293 if (MBB.isPredecessor(&MBB)) {
295 return true;
296 } else
297 return false;
298 }
299 --I;
300 return true;
301}
302
305 MachineBasicBlock &MBB) {
306 int InstrDistance = 1;
308 static const int INSTR_DISTANCE_THRESHOLD = 5;
309
310 CurInst = I;
311 bool Found;
313 while (Found && I != CurInst) {
314 if (CurInst->isCall() || CurInst->isInlineAsm())
315 break;
316 if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
317 break;
318 if (usesRegister(p, CurInst) == RU_Write) {
319 return CurInst;
320 }
321 InstrDistance += TSM.computeInstrLatency(&*CurInst);
323 }
325}
326
328 return Reg == X86::EBP || Reg == X86::RBP ||
329 Reg == X86::R13D || Reg == X86::R13;
330}
331
332
333
334
335
339 Index.getReg().isValid();
340}
341
346
348 switch (LEAOpcode) {
349 default:
351 case X86::LEA32r:
352 case X86::LEA64_32r:
353 return X86::ADD32rr;
354 case X86::LEA64r:
355 return X86::ADD64rr;
356 }
357}
358
360 switch (LEAOpcode) {
361 default:
363 case X86::LEA32r:
364 case X86::LEA64_32r:
365 return X86::SUB32rr;
366 case X86::LEA64r:
367 return X86::SUB64rr;
368 }
369}
370
373 switch (LEAOpcode) {
374 default:
376 case X86::LEA32r:
377 case X86::LEA64_32r:
378 return X86::ADD32ri;
379 case X86::LEA64r:
380 return X86::ADD64ri32;
381 }
382}
383
385 switch (LEAOpcode) {
386 default:
388 case X86::LEA32r:
389 case X86::LEA64_32r:
390 return IsINC ? X86::INC32r : X86::DEC32r;
391 case X86::LEA64r:
392 return IsINC ? X86::INC64r : X86::DEC64r;
393 }
394}
395
398 MachineBasicBlock &MBB) const {
399 const int InstrDistanceThreshold = 5;
400 int InstrDistance = 1;
402
403 unsigned LEAOpcode = I->getOpcode();
406 Register DestReg = I->getOperand(0).getReg();
407
408 while (CurInst != MBB.end()) {
409 if (CurInst->isCall() || CurInst->isInlineAsm())
410 break;
411 if (InstrDistance > InstrDistanceThreshold)
412 break;
413
414
415 for (unsigned I = 0, E = CurInst->getNumOperands(); I != E; ++I) {
416 MachineOperand &Opnd = CurInst->getOperand(I);
417 if (Opnd.isReg()) {
418 if (Opnd.getReg() == DestReg) {
421
422 unsigned AluOpcode = CurInst->getOpcode();
423 if (AluOpcode != AddOpcode && AluOpcode != SubOpcode)
425
426 MachineOperand &Opnd2 = CurInst->getOperand(3 - I);
427 MachineOperand AluDest = CurInst->getOperand(0);
430
431
432
433
434 if (!CurInst->registerDefIsDead(X86::EFLAGS, TRI))
436
437 return CurInst;
438 }
439 if (TRI->regsOverlap(DestReg, Opnd.getReg()))
441 }
442 }
443
444 InstrDistance++;
445 ++CurInst;
446 }
448}
449
452 bool &BaseIndexDef, bool &AluDestRef,
453 MachineOperand **KilledBase,
454 MachineOperand **KilledIndex) const {
455 BaseIndexDef = AluDestRef = false;
456 *KilledBase = *KilledIndex = nullptr;
459 Register AluDestReg = AluI->getOperand(0).getReg();
460
461 for (MachineInstr &CurInst : llvm::make_range(std::next(LeaI), AluI)) {
462 for (MachineOperand &Opnd : CurInst.operands()) {
463 if (!Opnd.isReg())
464 continue;
466 if (TRI->regsOverlap(Reg, AluDestReg))
467 AluDestRef = true;
468 if (TRI->regsOverlap(Reg, BaseReg)) {
469 if (Opnd.isDef())
470 BaseIndexDef = true;
471 else if (Opnd.isKill())
472 *KilledBase = &Opnd;
473 }
474 if (TRI->regsOverlap(Reg, IndexReg)) {
475 if (Opnd.isDef())
476 BaseIndexDef = true;
477 else if (Opnd.isKill())
478 *KilledIndex = &Opnd;
479 }
480 }
481 }
482}
483
485 MachineBasicBlock &MBB) const {
486
489 return false;
490
491
492 bool BaseIndexDef, AluDestRef;
493 MachineOperand *KilledBase, *KilledIndex;
494 checkRegUsage(I, AluI, BaseIndexDef, AluDestRef, &KilledBase, &KilledIndex);
495
497 if (BaseIndexDef) {
498 if (AluDestRef)
499 return false;
500 InsertPos = I;
501 KilledBase = KilledIndex = nullptr;
502 }
503
504
505 Register AluDestReg = AluI->getOperand(0).getReg();
508 if (I->getOpcode() == X86::LEA64_32r) {
509 BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);
510 IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);
511 }
512 if (AluDestReg == IndexReg) {
513 if (BaseReg == IndexReg)
514 return false;
516 std::swap(KilledBase, KilledIndex);
517 }
518 if (BaseReg == IndexReg)
519 KilledBase = nullptr;
520
521
522 MachineInstr *NewMI1, *NewMI2;
523 unsigned NewOpcode = AluI->getOpcode();
524 NewMI1 = BuildMI(MBB, InsertPos, AluI->getDebugLoc(), TII->get(NewOpcode),
525 AluDestReg)
529 NewMI2 = BuildMI(MBB, InsertPos, AluI->getDebugLoc(), TII->get(NewOpcode),
530 AluDestReg)
534
535
536 if (KilledBase)
538 if (KilledIndex)
540
544 I = NewMI1;
545 return true;
546}
547
549 MachineBasicBlock &MBB, bool OptIncDec,
550 bool UseLEAForSP) const {
552
556 const MachineOperand &Disp = MI.getOperand(1 + X86::AddrDisp);
558
562 return false;
563
564 Register DestReg = MI.getOperand(0).getReg();
567
568
569 if (UseLEAForSP && (DestReg == X86::ESP || DestReg == X86::RSP))
570 return false;
571
572
573 if (MI.getOpcode() == X86::LEA64_32r) {
574 if (BaseReg)
575 BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);
576 if (IndexReg)
577 IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);
578 }
579
580 MachineInstr *NewMI = nullptr;
581
582
583
584
586 (DestReg == BaseReg || DestReg == IndexReg)) {
588 if (DestReg != BaseReg)
590
591 if (MI.getOpcode() == X86::LEA64_32r) {
592
597 } else {
600 }
601 } else if (DestReg == BaseReg && !IndexReg) {
602
603
604
605
606
607
608
609 if (OptIncDec && (Disp.getImm() == 1 || Disp.getImm() == -1)) {
610 bool IsINC = Disp.getImm() == 1;
612
613 if (MI.getOpcode() == X86::LEA64_32r) {
614
617 } else {
620 }
621 } else {
623 if (MI.getOpcode() == X86::LEA64_32r) {
624
628 } else {
631 }
632 }
634
635
636
637
639 } else
640 return false;
641
644 I = NewMI;
645 return true;
646}
647
649 MachineBasicBlock &MBB) {
650
652 const MCInstrDesc &Desc = MI.getDesc();
654 if (AddrOffset >= 0) {
657 if (p.isReg() && p.getReg() != X86::ESP) {
659 }
661 if (q.isReg() && q.getReg() != X86::ESP) {
663 }
664 }
665}
666
667void FixupLEAPass::seekLEAFixup(MachineOperand &p,
669 MachineBasicBlock &MBB) {
672 MachineInstr *NewMI = postRAConvertToLEA(MBB, MBI);
673 if (NewMI) {
674 ++NumLEAs;
675 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MBI->dump(););
676
682 processInstruction(J, MBB);
683 }
684 }
685}
686
688 MachineBasicBlock &MBB) {
690 const unsigned Opcode = MI.getOpcode();
691
692 const MachineOperand &Dst = MI.getOperand(0);
698
702 return;
703 const Register DstR = Dst.getReg();
706 if ((!SrcR1 || SrcR1 != DstR) && (!SrcR2 || SrcR2 != DstR))
707 return;
708 if (Scale.getImm() > 1)
709 return;
710 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););
712 MachineInstr *NewMI = nullptr;
713
714 if (SrcR1 && SrcR2) {
716 const MachineOperand &Src = SrcR1 == DstR ? Index : Base;
717 NewMI =
720 }
721
722 if (Offset.getImm() != 0) {
723 const MCInstrDesc &ADDri =
725 const MachineOperand &SrcR = SrcR1 == DstR ? Base : Index;
726 NewMI = BuildMI(MBB, I, MI.getDebugLoc(), ADDri, DstR)
727 .add(SrcR)
730 }
731 if (NewMI) {
734 I = NewMI;
735 }
736}
737
739 MachineBasicBlock &MBB,
740 bool OptIncDec) {
742 const unsigned LEAOpcode = MI.getOpcode();
743
744 const MachineOperand &Dest = MI.getOperand(0);
750
755 return;
756
760
761 if (MI.getOpcode() == X86::LEA64_32r) {
762 if (BaseReg)
763 BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);
764 if (IndexReg)
765 IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);
766 }
767
768 bool IsScale1 = Scale.getImm() == 1;
771
772
773
774 if (IsInefficientBase && DestReg == BaseReg && !IsScale1)
775 return;
776
779
780 MachineInstr *NewMI = nullptr;
781 bool BaseOrIndexIsDst = DestReg == BaseReg || DestReg == IndexReg;
782
783
784
785
786
787
788 if (IsScale1 && BaseReg == IndexReg &&
789 (hasLEAOffset(Offset) || (IsInefficientBase && !BaseOrIndexIsDst))) {
791 .add(Dest)
794 .add(Index)
796 .add(Segment);
798
801 I = NewMI;
802 return;
803 } else if (IsScale1 && BaseOrIndexIsDst) {
804
805
806
807
808
810 if (DestReg != BaseReg)
812
813 if (MI.getOpcode() == X86::LEA64_32r) {
814
820 } else {
824 }
825 } else if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
826
827
828
829
831 .add(Dest)
832 .add(IsInefficientBase ? Index : Base)
833 .add(Scale)
834 .add(IsInefficientBase ? Base : Index)
836 .add(Segment);
838 }
839
840
841
842 if (NewMI) {
843
845 if (OptIncDec && Offset.isImm() &&
846 (Offset.getImm() == 1 || Offset.getImm() == -1)) {
847 unsigned NewOpc =
852 } else {
858 }
859 }
860
863 I = NewMI;
864 return;
865 }
866
867
868 assert(DestReg != BaseReg && "DestReg == BaseReg should be handled already!");
869 assert(IsInefficientBase && "efficient base should be handled already!");
870
871
872 if (LEAOpcode == X86::LEA64_32r)
873 return;
874
875
877 bool BIK = Base.isKill() && BaseReg != IndexReg;
880
884 .add(Index);
886
889 I = NewMI;
890 return;
891 }
892
893
894
896 .add(Dest)
898 .add(Scale)
899 .add(Index)
901 .add(Segment);
903
909
912 I = NewMI;
913}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static unsigned getINCDECFromLEA(unsigned LEAOpcode, bool IsINC)
Definition X86FixupLEAs.cpp:384
static bool isLEA(unsigned Opcode)
Definition X86FixupLEAs.cpp:215
static bool hasLEAOffset(const MachineOperand &Offset)
Definition X86FixupLEAs.cpp:342
static bool isInefficientLEAReg(Register Reg)
Definition X86FixupLEAs.cpp:327
static bool hasInefficientLEABaseReg(const MachineOperand &Base, const MachineOperand &Index)
Returns true if this LEA uses base and index registers, and the base register is known to be ineffici...
Definition X86FixupLEAs.cpp:336
static unsigned getADDriFromLEA(unsigned LEAOpcode, const MachineOperand &Offset)
Definition X86FixupLEAs.cpp:371
static bool getPreviousInstr(MachineBasicBlock::iterator &I, MachineBasicBlock &MBB)
getPreviousInstr - Given a reference to an instruction in a basic block, return a reference to the pr...
Definition X86FixupLEAs.cpp:290
#define FIXUPLEA_DESC
Definition X86FixupLEAs.cpp:30
static unsigned getADDrrFromLEA(unsigned LEAOpcode)
Definition X86FixupLEAs.cpp:347
#define FIXUPLEA_NAME
Definition X86FixupLEAs.cpp:31
static unsigned getSUBrrFromLEA(unsigned LEAOpcode)
Definition X86FixupLEAs.cpp:359
AnalysisUsage & addRequired()
FunctionPass class - This class is used to implement most global optimizations.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, unsigned MaxOperand=UINT_MAX)
Create substitutions for any tracked values in Old, to point at New.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
LLVM_ABI void dump() const
LLVM_ABI bool addRegisterDead(Register Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI defined a register without a use.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const
Emit instructions to copy a pair of physical registers.
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
int getMemoryOperandNo(uint64_t TSFlags)
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createX86FixupLEAs()
Return a pass that selectively replaces certain instructions (like add, sub, inc, dec,...
Definition X86FixupLEAs.cpp:213
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.