LLVM: lib/Target/Hexagon/HexagonCopyToCombine.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
31
32using namespace llvm;
33
34#define DEBUG_TYPE "hexagon-copy-combine"
35
38
39 cl::desc("Disable merging into combines"));
42
43 cl::desc("Disable generation of const64"));
44static
48 cl::desc("Maximum distance between a tfr feeding a store we "
49 "consider the store still to be newifiable"));
50
51namespace llvm {
54}
55
56
57namespace {
58
64
67
68public:
69 static char ID;
70
72
75 }
76
78 return "Hexagon Copy-To-Combine Pass";
79 }
80
82
85 MachineFunctionProperties::Property::NoVRegs);
86 }
87
88private:
90 bool AllowC64);
91
93
96 bool OptForSize);
97
99 unsigned I1DestReg, unsigned I2DestReg,
100 bool &DoInsertAtI1);
101
104
107
110
113
116};
117
118}
119
120char HexagonCopyToCombine::ID = 0;
121
123 "Hexagon Copy-To-Combine Pass", false, false)
124
127 switch (MI.getOpcode()) {
128 case Hexagon::A2_tfr: {
129
133
136 return Hexagon::IntRegsRegClass.contains(DestReg) &&
137 Hexagon::IntRegsRegClass.contains(SrcReg);
138 }
139
140 case Hexagon::A2_tfrsi: {
141
142
146
148
149
150
152 return false;
153
154
155 bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm());
156 return Hexagon::IntRegsRegClass.contains(DestReg) &&
158 }
159
160 case Hexagon::V6_vassign:
161 return true;
162
163 default:
164 break;
165 }
166
167 return false;
168}
169
171 if (I.getOpcode() == Hexagon::TFRI64_V4 ||
172 I.getOpcode() == Hexagon::A2_tfrsi) {
174 return .isImm() || !isInt(Op.getImm());
175 }
176 return false;
177}
178
179
180
184 unsigned HiOpc = HighRegInst.getOpcode();
185 unsigned LoOpc = LowRegInst.getOpcode();
186
187 auto verifyOpc = [](unsigned Opc) -> void {
188 switch (Opc) {
189 case Hexagon::A2_tfr:
190 case Hexagon::A2_tfrsi:
191 case Hexagon::V6_vassign:
192 break;
193 default:
195 }
196 };
197 verifyOpc(HiOpc);
198 verifyOpc(LoOpc);
199
200 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
201 return HiOpc == LoOpc;
202
203 if (!AllowC64) {
204
205 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
206 isGreaterThanNBitTFRI<6>(LowRegInst))
207 return false;
208 }
209
210
211
212 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
216
217
218
219 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
220 isGreaterThanNBitTFRI<8>(LowRegInst))
221 return false;
222
223 return true;
224}
225
228 if (Hexagon::IntRegsRegClass.contains(Reg))
229 return (Reg - Hexagon::R0) % 2 == 0;
230 if (Hexagon::HvxVRRegClass.contains(Reg))
231 return (Reg - Hexagon::V0) % 2 == 0;
233}
234
237 if (Op.isReg() && Op.getReg() == RegNotKilled && Op.isKill())
238 Op.setIsKill(false);
239}
240
241
242
244 unsigned DestReg,
247 MI.modifiesRegister(DestReg, TRI) || MI.readsRegister(DestReg, TRI) ||
248 MI.hasUnmodeledSideEffects() || MI.isInlineAsm() ||
249 MI.isMetaInstruction();
250}
251
254}
255
256
257
258bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,
260 unsigned I1DestReg,
261 unsigned I2DestReg,
262 bool &DoInsertAtI1) {
264
265
266
267 if (I2UseReg && I1.modifiesRegister(I2UseReg, TRI))
268 return false;
269
270 bool isSafe = true;
271
272
273 {
274
275
276
279
281 End = ++I1.getIterator().getReverse();
282
283
284
285 unsigned KilledOperand = 0;
287 KilledOperand = I2UseReg;
289
291
292
293
294
295
296
297 if (I->isDebugInstr())
298 continue;
299
301 isSafe = false;
302 break;
303 }
304
305
306 if (!KillingInstr && KilledOperand &&
307 I->readsRegister(KilledOperand, TRI))
308 KillingInstr = &*I;
309 }
310 if (isSafe) {
311
312 if (KillingInstr) {
314 (void)Added;
315 assert(Added && "Must successfully update kill flag");
317 }
318 DoInsertAtI1 = true;
319 return true;
320 }
321 }
322
323
324 {
325
327
331
332
333
335 unsigned KilledOperand = 0;
336
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355 if (MI.isDebugInstr()) {
356 if (MI.readsRegister(I1DestReg, TRI))
357 DbgMItoMove.push_back(&MI);
358 continue;
359 }
360
362
363 (.killsRegister(I1UseReg, nullptr) &&
364 MI.killsRegister(I1UseReg, TRI)))
365 return false;
366
367
368 if (I1UseReg && MI.killsRegister(I1UseReg, nullptr)) {
369 assert(!KillingInstr && "Should only see one killing instruction");
370 KilledOperand = I1UseReg;
371 KillingInstr = &MI;
372 }
373 }
374 if (KillingInstr) {
376
377
378 bool Added = I1.addRegisterKilled(KilledOperand, TRI);
379 (void)Added;
380 assert(Added && "Must successfully update kill flag");
381 }
382 DoInsertAtI1 = false;
383 }
384
385 return true;
386}
387
388
389
390void
391HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
394 if (MI.isDebugInstr())
395 continue;
396
397
399
401
402 if (.isReg() ||
.isUse() ||
.getReg())
403 continue;
404
405
408 if (!DefInst)
409 continue;
411 continue;
412
413
414
416 unsigned NumInstsToDef = 0;
417 while (&*It != &MI) {
418 if (!It->isDebugInstr())
419 ++NumInstsToDef;
420 ++It;
421 }
422
424 continue;
425
426 PotentiallyNewifiableTFR.insert(DefInst);
427 }
428
429 continue;
430 }
431
432
433
435 if (Op.isReg()) {
436 if (.isDef() ||
.getReg())
437 continue;
439 if (Hexagon::DoubleRegsRegClass.contains(Reg)) {
442 } else if (Hexagon::IntRegsRegClass.contains(Reg))
444 } else if (Op.isRegMask()) {
445 for (unsigned Reg : Hexagon::IntRegsRegClass)
446 if (Op.clobbersPhysReg(Reg))
448 }
449 }
450 }
451}
452
453bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {
455 return false;
456
458
459 bool HasChanged = false;
460
461
463 TRI = ST->getRegisterInfo();
465
467 bool OptForSize = F.hasFnAttribute(Attribute::OptimizeForSize);
468
469
472
473
474 if (!OptForSize && ST->isTinyCore())
476
477
479 PotentiallyNewifiableTFR.clear();
480 findPotentialNewifiableTFRs(MBB);
481
482
486
487 if (I1.isDebugInstr())
488 continue;
489
490
491
492
494 continue;
495
496
498 continue;
499
500
501
502
503 bool DoInsertAtI1 = false;
504 DbgMItoMove.clear();
505 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
506 if (I2) {
507 HasChanged = true;
508 combine(I1, *I2, MI, DoInsertAtI1, OptForSize);
509 }
510 }
511 }
512
513 return HasChanged;
514}
515
516
517
518
519
521 bool &DoInsertAtI1,
522 bool AllowC64) {
524 while (I2 != I1.getParent()->end() && I2->isDebugInstr())
525 ++I2;
526
527 Register I1DestReg = I1.getOperand(0).getReg();
528
530 ++I2) {
531
532 if (I2->modifiesRegister(I1DestReg, TRI))
533 break;
534
535
537 continue;
538
539
541 continue;
542
543 Register I2DestReg = I2->getOperand(0).getReg();
544
545
546
547 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
548 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
549 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
550 if ((!IsI1LowReg && !IsI2LowReg) || (FirstRegIndex))
551 continue;
552
553
554
555
558 break;
559
560 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
561 return &*I2;
562
563
564 break;
565 }
566 return nullptr;
567}
568
571 bool DoInsertAtI1, bool OptForSize) {
572
573
575 ++MI;
576
577
578 Register I1DestReg = I1.getOperand(0).getReg();
580 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
581 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
582 unsigned SubLo;
583
585 if (Hexagon::IntRegsRegClass.contains(LoRegDef)) {
586 SuperRC = &Hexagon::DoubleRegsRegClass;
587 SubLo = Hexagon::isub_lo;
588 } else if (Hexagon::HvxVRRegClass.contains(LoRegDef)) {
590 SuperRC = &Hexagon::HvxWRRegClass;
591 SubLo = Hexagon::vsub_lo;
592 } else
594
595
596 unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
597 assert(DoubleRegDest != 0 && "Expect a valid register");
598
599
602
603
604 bool IsHiReg = HiOperand.isReg();
605 bool IsLoReg = LoOperand.isReg();
606
607
608 bool IsC64 = OptForSize && LoOperand.isImm() && HiOperand.isImm() &&
609 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
610
612
613 if (IsHiReg && IsLoReg)
614 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
615 else if (IsHiReg)
616 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
617 else if (IsLoReg)
618 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
620 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
621 else
622 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
623
624
625
626 if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {
627
629 for (auto *NewMI : DbgMItoMove) {
630
631
632 if (NewMI == MI)
633 ++MI;
634 BB->splice(InsertPt, BB, NewMI);
635 }
636 }
637
638 I1.eraseFromParent();
640}
641
643 unsigned DoubleDestReg,
647
648 DebugLoc DL = InsertPt->getDebugLoc();
651 "Both operands must be immediate");
652
653 int64_t V = HiOperand.getImm();
654 V = (V << 32) | (0x0ffffffffLL & LoOperand.getImm());
655 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg)
657}
658
660 unsigned DoubleDestReg,
663 DebugLoc DL = InsertPt->getDebugLoc();
665
666
668 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
672 return;
673 }
675 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
679 return;
680 }
681
682
684 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
688 return;
689 }
691 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
695 return;
696 }
697
698
699 if (HiOperand.isJTI()) {
700 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
703 return;
704 }
705 if (LoOperand.isJTI()) {
706 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
709 return;
710 }
711
712
713 if (HiOperand.isCPI()) {
714 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
718 return;
719 }
720 if (LoOperand.isCPI()) {
721 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
725 return;
726 }
727
728
729
730
731 if (isInt<8>(LoOperand.getImm())) {
732 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
735 return;
736 }
737
738
739 if (isInt<8>(HiOperand.getImm())) {
740 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
743 return;
744 }
745
746
747
748 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
751}
752
754 unsigned DoubleDestReg,
759
760 DebugLoc DL = InsertPt->getDebugLoc();
762
763
765 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
768 .addReg(LoReg, LoRegKillFlag);
769 return;
770 }
771
773 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
776 .addReg(LoReg, LoRegKillFlag);
777 return;
778 }
779
780 if (HiOperand.isJTI()) {
781 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
783 .addReg(LoReg, LoRegKillFlag);
784 return;
785 }
786
787 if (HiOperand.isCPI()) {
788 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
791 .addReg(LoReg, LoRegKillFlag);
792 return;
793 }
794
795
796 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
798 .addReg(LoReg, LoRegKillFlag);
799}
800
802 unsigned DoubleDestReg,
807
808 DebugLoc DL = InsertPt->getDebugLoc();
810
811
813 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
814 .addReg(HiReg, HiRegKillFlag)
817 return;
818 }
819
821 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
822 .addReg(HiReg, HiRegKillFlag)
825 return;
826 }
827
828 if (LoOperand.isJTI()) {
829 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
832 return;
833 }
834
835 if (LoOperand.isCPI()) {
836 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
840 return;
841 }
842
843
844
845 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
846 .addReg(HiReg, HiRegKillFlag)
848}
849
851 unsigned DoubleDestReg,
858
859 DebugLoc DL = InsertPt->getDebugLoc();
861
862
863
864 unsigned NewOpc;
865 if (Hexagon::DoubleRegsRegClass.contains(DoubleDestReg)) {
866 NewOpc = Hexagon::A2_combinew;
867 } else if (Hexagon::HvxWRRegClass.contains(DoubleDestReg)) {
869 NewOpc = Hexagon::V6_vcombine;
870 } else
872
873 BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)
874 .addReg(HiReg, HiRegKillFlag)
875 .addReg(LoReg, LoRegKillFlag);
876}
877
879 return new HexagonCopyToCombine();
880}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
static cl::opt< bool > IsConst64Disabled("disable-const64", cl::Hidden, cl::desc("Disable generation of const64"))
static bool isEvenReg(unsigned Reg)
static bool isUnsafeToMoveAcross(MachineInstr &MI, unsigned UseReg, unsigned DestReg, const TargetRegisterInfo *TRI)
Returns true if it is unsafe to move a copy instruction from UseReg to DestReg over the instruction M...
static cl::opt< bool > IsCombinesDisabled("disable-merge-into-combines", cl::Hidden, cl::desc("Disable merging into combines"))
const HexagonInstrInfo bool ShouldCombineAggressively
static bool areCombinableOperations(const TargetRegisterInfo *TRI, MachineInstr &HighRegInst, MachineInstr &LowRegInst, bool AllowC64)
areCombinableOperations - Returns true if the two instruction can be merge into a combine (ignoring r...
static cl::opt< unsigned > MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store", cl::Hidden, cl::init(4), cl::desc("Maximum distance between a tfr feeding a store we " "consider the store still to be newifiable"))
static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled)
static bool isGreaterThanNBitTFRI(const MachineInstr &I)
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Represent the analysis usage information of a pass.
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
FunctionPass class - This class is used to implement most global optimizations.
bool mayBeNewStore(const MachineInstr &MI) const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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 TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr kills the specified register.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createHexagonCopyToCombine()
unsigned getKillRegState(bool B)
void initializeHexagonCopyToCombinePass(PassRegistry &)