LLVM 19.0.0git
HexagonCopyToCombine.cpp
Go to the documentation of this file.
1//===------- HexagonCopyToCombine.cpp - Hexagon Copy-To-Combine Pass ------===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8// This pass replaces transfer instructions by combine instructions.
9// We walk along a basic block and look for two combinable instructions and try
10// to move them together. If we can move them next to each other we do so and
11// replace them with a combine instruction.
12//===----------------------------------------------------------------------===//
13
14#include "HexagonInstrInfo.h"
15#include "HexagonSubtarget.h"
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/DenseSet.h"
23#include "llvm/CodeGen/Passes.h"
25#include "llvm/Pass.h"
28#include "llvm/Support/Debug.h"
31
32using namespace llvm;
33
34#define DEBUG_TYPE "hexagon-copy-combine"
35
36static cl::opt<bool>
37 IsCombinesDisabled("disable-merge-into-combines", cl::Hidden,
38
39 cl::desc("Disable merging into combines"));
40static cl::opt<bool>
41 IsConst64Disabled("disable-const64", cl::Hidden,
42
43 cl::desc("Disable generation of const64"));
44static
46MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store",
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
59class HexagonCopyToCombine : public MachineFunctionPass {
60 const HexagonInstrInfo *TII;
62 const HexagonSubtarget *ST;
64
65 DenseSet<MachineInstr *> PotentiallyNewifiableTFR;
67
68public:
69 static char ID;
70
71 HexagonCopyToCombine() : MachineFunctionPass(ID) {}
72
73 void getAnalysisUsage(AnalysisUsage &AU) const override {
75 }
76
77 StringRef getPassName() const override {
78 return "Hexagon Copy-To-Combine Pass";
79 }
80
81 bool runOnMachineFunction(MachineFunction &Fn) override;
82
85 MachineFunctionProperties::Property::NoVRegs);
86 }
87
88private:
89 MachineInstr *findPairable(MachineInstr &I1, bool &DoInsertAtI1,
90 bool AllowC64);
91
92 void findPotentialNewifiableTFRs(MachineBasicBlock &);
93
94 void combine(MachineInstr &I1, MachineInstr &I2,
95 MachineBasicBlock::iterator &MI, bool DoInsertAtI1,
96 bool OptForSize);
97
98 bool isSafeToMoveTogether(MachineInstr &I1, MachineInstr &I2,
99 unsigned I1DestReg, unsigned I2DestReg,
100 bool &DoInsertAtI1);
101
102 void emitCombineRR(MachineBasicBlock::iterator &Before, unsigned DestReg,
103 MachineOperand &HiOperand, MachineOperand &LoOperand);
104
105 void emitCombineRI(MachineBasicBlock::iterator &Before, unsigned DestReg,
106 MachineOperand &HiOperand, MachineOperand &LoOperand);
107
108 void emitCombineIR(MachineBasicBlock::iterator &Before, unsigned DestReg,
109 MachineOperand &HiOperand, MachineOperand &LoOperand);
110
111 void emitCombineII(MachineBasicBlock::iterator &Before, unsigned DestReg,
112 MachineOperand &HiOperand, MachineOperand &LoOperand);
113
114 void emitConst64(MachineBasicBlock::iterator &Before, unsigned DestReg,
115 MachineOperand &HiOperand, MachineOperand &LoOperand);
116};
117
118} // End anonymous namespace.
119
120char HexagonCopyToCombine::ID = 0;
121
122INITIALIZE_PASS(HexagonCopyToCombine, "hexagon-copy-combine",
123 "Hexagon Copy-To-Combine Pass", false, false)
124
125static bool isCombinableInstType(MachineInstr &MI, const HexagonInstrInfo *TII,
127 switch (MI.getOpcode()) {
128 case Hexagon::A2_tfr: {
129 // A COPY instruction can be combined if its arguments are IntRegs (32bit).
130 const MachineOperand &Op0 = MI.getOperand(0);
131 const MachineOperand &Op1 = MI.getOperand(1);
132 assert(Op0.isReg() && Op1.isReg());
133
134 Register DestReg = Op0.getReg();
135 Register SrcReg = Op1.getReg();
136 return Hexagon::IntRegsRegClass.contains(DestReg) &&
137 Hexagon::IntRegsRegClass.contains(SrcReg);
138 }
139
140 case Hexagon::A2_tfrsi: {
141 // A transfer-immediate can be combined if its argument is a signed 8bit
142 // value.
143 const MachineOperand &Op0 = MI.getOperand(0);
144 const MachineOperand &Op1 = MI.getOperand(1);
145 assert(Op0.isReg());
146
147 Register DestReg = Op0.getReg();
148 // Ensure that TargetFlags are MO_NO_FLAG for a global. This is a
149 // workaround for an ABI bug that prevents GOT relocations on combine
150 // instructions
151 if (!Op1.isImm() && Op1.getTargetFlags() != HexagonII::MO_NO_FLAG)
152 return false;
153
154 // Only combine constant extended A2_tfrsi if we are in aggressive mode.
155 bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm());
156 return Hexagon::IntRegsRegClass.contains(DestReg) &&
157 (ShouldCombineAggressively || NotExt);
158 }
159
160 case Hexagon::V6_vassign:
161 return true;
162
163 default:
164 break;
165 }
166
167 return false;
168}
169
170template <unsigned N> static bool isGreaterThanNBitTFRI(const MachineInstr &I) {
171 if (I.getOpcode() == Hexagon::TFRI64_V4 ||
172 I.getOpcode() == Hexagon::A2_tfrsi) {
173 const MachineOperand &Op = I.getOperand(1);
174 return !Op.isImm() || !isInt<N>(Op.getImm());
175 }
176 return false;
177}
178
179/// areCombinableOperations - Returns true if the two instruction can be merge
180/// into a combine (ignoring register constraints).
182 MachineInstr &HighRegInst,
183 MachineInstr &LowRegInst, bool AllowC64) {
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:
194 llvm_unreachable("Unexpected opcode");
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 // There is no combine of two constant extended values.
205 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
206 isGreaterThanNBitTFRI<6>(LowRegInst))
207 return false;
208 }
209
210 // There is a combine of two constant extended values into CONST64,
211 // provided both constants are true immediates.
212 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
213 isGreaterThanNBitTFRI<16>(LowRegInst) && !IsConst64Disabled)
214 return (HighRegInst.getOperand(1).isImm() &&
215 LowRegInst.getOperand(1).isImm());
216
217 // There is no combine of two constant extended values, unless handled above
218 // Make both 8-bit size checks to allow both combine (#,##) and combine(##,#)
219 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
220 isGreaterThanNBitTFRI<8>(LowRegInst))
221 return false;
222
223 return true;
224}
225
226static bool isEvenReg(unsigned Reg) {
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;
232 llvm_unreachable("Invalid register");
233}
234
235static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled) {
236 for (MachineOperand &Op : MI.operands())
237 if (Op.isReg() && Op.getReg() == RegNotKilled && Op.isKill())
238 Op.setIsKill(false);
239}
240
241/// Returns true if it is unsafe to move a copy instruction from \p UseReg to
242/// \p DestReg over the instruction \p MI.
244 unsigned DestReg,
245 const TargetRegisterInfo *TRI) {
246 return (UseReg && (MI.modifiesRegister(UseReg, TRI))) ||
247 MI.modifiesRegister(DestReg, TRI) || MI.readsRegister(DestReg, TRI) ||
248 MI.hasUnmodeledSideEffects() || MI.isInlineAsm() ||
249 MI.isMetaInstruction();
250}
251
252static Register UseReg(const MachineOperand& MO) {
253 return MO.isReg() ? MO.getReg() : Register();
254}
255
256/// isSafeToMoveTogether - Returns true if it is safe to move I1 next to I2 such
257/// that the two instructions can be paired in a combine.
258bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,
259 MachineInstr &I2,
260 unsigned I1DestReg,
261 unsigned I2DestReg,
262 bool &DoInsertAtI1) {
263 Register I2UseReg = UseReg(I2.getOperand(1));
264
265 // It is not safe to move I1 and I2 into one combine if I2 has a true
266 // dependence on I1.
267 if (I2UseReg && I1.modifiesRegister(I2UseReg, TRI))
268 return false;
269
270 bool isSafe = true;
271
272 // First try to move I2 towards I1.
273 {
274 // A reverse_iterator instantiated like below starts before I2, and I1
275 // respectively.
276 // Look at instructions I in between I2 and (excluding) I1.
278 MachineBasicBlock::reverse_iterator End = I1.getIterator().getReverse();
279 // At 03 we got better results (dhrystone!) by being more conservative.
281 End = ++I1.getIterator().getReverse();
282 // If I2 kills its operand and we move I2 over an instruction that also
283 // uses I2's use reg we need to modify that (first) instruction to now kill
284 // this reg.
285 unsigned KilledOperand = 0;
286 if (I2.killsRegister(I2UseReg))
287 KilledOperand = I2UseReg;
288 MachineInstr *KillingInstr = nullptr;
289
290 for (; I != End; ++I) {
291 // If the intervening instruction I:
292 // * modifies I2's use reg
293 // * modifies I2's def reg
294 // * reads I2's def reg
295 // * or has unmodelled side effects
296 // we can't move I2 across it.
297 if (I->isDebugInstr())
298 continue;
299
300 if (isUnsafeToMoveAcross(*I, I2UseReg, I2DestReg, TRI)) {
301 isSafe = false;
302 break;
303 }
304
305 // Update first use of the killed operand.
306 if (!KillingInstr && KilledOperand &&
307 I->readsRegister(KilledOperand, TRI))
308 KillingInstr = &*I;
309 }
310 if (isSafe) {
311 // Update the intermediate instruction to with the kill flag.
312 if (KillingInstr) {
313 bool Added = KillingInstr->addRegisterKilled(KilledOperand, TRI, true);
314 (void)Added; // suppress compiler warning
315 assert(Added && "Must successfully update kill flag");
316 removeKillInfo(I2, KilledOperand);
317 }
318 DoInsertAtI1 = true;
319 return true;
320 }
321 }
322
323 // Try to move I1 towards I2.
324 {
325 // Look at instructions I in between I1 and (excluding) I2.
327 // At O3 we got better results (dhrystone) by being more conservative here.
329 End = std::next(MachineBasicBlock::iterator(I2));
330 Register I1UseReg = UseReg(I1.getOperand(1));
331 // Track killed operands. If we move across an instruction that kills our
332 // operand, we need to update the kill information on the moved I1. It kills
333 // the operand now.
334 MachineInstr *KillingInstr = nullptr;
335 unsigned KilledOperand = 0;
336
337 while(++I != End) {
338 MachineInstr &MI = *I;
339 // If the intervening instruction MI:
340 // * modifies I1's use reg
341 // * modifies I1's def reg
342 // * reads I1's def reg
343 // * or has unmodelled side effects
344 // We introduce this special case because llvm has no api to remove a
345 // kill flag for a register (a removeRegisterKilled() analogous to
346 // addRegisterKilled) that handles aliased register correctly.
347 // * or has a killed aliased register use of I1's use reg
348 // %d4 = A2_tfrpi 16
349 // %r6 = A2_tfr %r9
350 // %r8 = KILL %r8, implicit killed %d4
351 // If we want to move R6 = across the KILL instruction we would have
352 // to remove the implicit killed %d4 operand. For now, we are
353 // conservative and disallow the move.
354 // we can't move I1 across it.
355 if (MI.isDebugInstr()) {
356 if (MI.readsRegister(I1DestReg, TRI)) // Move this instruction after I2.
357 DbgMItoMove.push_back(&MI);
358 continue;
359 }
360
361 if (isUnsafeToMoveAcross(MI, I1UseReg, I1DestReg, TRI) ||
362 // Check for an aliased register kill. Bail out if we see one.
363 (!MI.killsRegister(I1UseReg) && MI.killsRegister(I1UseReg, TRI)))
364 return false;
365
366 // Check for an exact kill (registers match).
367 if (I1UseReg && MI.killsRegister(I1UseReg)) {
368 assert(!KillingInstr && "Should only see one killing instruction");
369 KilledOperand = I1UseReg;
370 KillingInstr = &MI;
371 }
372 }
373 if (KillingInstr) {
374 removeKillInfo(*KillingInstr, KilledOperand);
375 // Update I1 to set the kill flag. This flag will later be picked up by
376 // the new COMBINE instruction.
377 bool Added = I1.addRegisterKilled(KilledOperand, TRI);
378 (void)Added; // suppress compiler warning
379 assert(Added && "Must successfully update kill flag");
380 }
381 DoInsertAtI1 = false;
382 }
383
384 return true;
385}
386
387/// findPotentialNewifiableTFRs - Finds tranfers that feed stores that could be
388/// newified. (A use of a 64 bit register define can not be newified)
389void
390HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
392 for (MachineInstr &MI : BB) {
393 if (MI.isDebugInstr())
394 continue;
395
396 // Mark TFRs that feed a potential new value store as such.
397 if (TII->mayBeNewStore(MI)) {
398 // Look for uses of TFR instructions.
399 for (const MachineOperand &Op : MI.operands()) {
400 // Skip over anything except register uses.
401 if (!Op.isReg() || !Op.isUse() || !Op.getReg())
402 continue;
403
404 // Look for the defining instruction.
405 Register Reg = Op.getReg();
406 MachineInstr *DefInst = LastDef[Reg];
407 if (!DefInst)
408 continue;
409 if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))
410 continue;
411
412 // Only close newifiable stores should influence the decision.
413 // Ignore the debug instructions in between.
414 MachineBasicBlock::iterator It(DefInst);
415 unsigned NumInstsToDef = 0;
416 while (&*It != &MI) {
417 if (!It->isDebugInstr())
418 ++NumInstsToDef;
419 ++It;
420 }
421
422 if (NumInstsToDef > MaxNumOfInstsBetweenNewValueStoreAndTFR)
423 continue;
424
425 PotentiallyNewifiableTFR.insert(DefInst);
426 }
427 // Skip to next instruction.
428 continue;
429 }
430
431 // Put instructions that last defined integer or double registers into the
432 // map.
433 for (MachineOperand &Op : MI.operands()) {
434 if (Op.isReg()) {
435 if (!Op.isDef() || !Op.getReg())
436 continue;
437 Register Reg = Op.getReg();
438 if (Hexagon::DoubleRegsRegClass.contains(Reg)) {
439 for (MCPhysReg SubReg : TRI->subregs(Reg))
440 LastDef[SubReg] = &MI;
441 } else if (Hexagon::IntRegsRegClass.contains(Reg))
442 LastDef[Reg] = &MI;
443 } else if (Op.isRegMask()) {
444 for (unsigned Reg : Hexagon::IntRegsRegClass)
445 if (Op.clobbersPhysReg(Reg))
446 LastDef[Reg] = &MI;
447 }
448 }
449 }
450}
451
452bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {
453 if (skipFunction(MF.getFunction()))
454 return false;
455
456 if (IsCombinesDisabled) return false;
457
458 bool HasChanged = false;
459
460 // Get target info.
462 TRI = ST->getRegisterInfo();
463 TII = ST->getInstrInfo();
464
465 const Function &F = MF.getFunction();
466 bool OptForSize = F.hasFnAttribute(Attribute::OptimizeForSize);
467
468 // Combine aggressively (for code size)
470 MF.getTarget().getOptLevel() <= CodeGenOptLevel::Default;
471
472 // Disable CONST64 for tiny core since it takes a LD resource.
473 if (!OptForSize && ST->isTinyCore())
474 IsConst64Disabled = true;
475
476 // Traverse basic blocks.
477 for (MachineBasicBlock &MBB : MF) {
478 PotentiallyNewifiableTFR.clear();
479 findPotentialNewifiableTFRs(MBB);
480
481 // Traverse instructions in basic block.
483 MI != End;) {
484 MachineInstr &I1 = *MI++;
485
486 if (I1.isDebugInstr())
487 continue;
488
489 // Don't combine a TFR whose user could be newified (instructions that
490 // define double registers can not be newified - Programmer's Ref Manual
491 // 5.4.2 New-value stores).
492 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&I1))
493 continue;
494
495 // Ignore instructions that are not combinable.
496 if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
497 continue;
498
499 // Find a second instruction that can be merged into a combine
500 // instruction. In addition, also find all the debug instructions that
501 // need to be moved along with it.
502 bool DoInsertAtI1 = false;
503 DbgMItoMove.clear();
504 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
505 if (I2) {
506 HasChanged = true;
507 combine(I1, *I2, MI, DoInsertAtI1, OptForSize);
508 }
509 }
510 }
511
512 return HasChanged;
513}
514
515/// findPairable - Returns an instruction that can be merged with \p I1 into a
516/// COMBINE instruction or 0 if no such instruction can be found. Returns true
517/// in \p DoInsertAtI1 if the combine must be inserted at instruction \p I1
518/// false if the combine must be inserted at the returned instruction.
519MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1,
520 bool &DoInsertAtI1,
521 bool AllowC64) {
523 while (I2 != I1.getParent()->end() && I2->isDebugInstr())
524 ++I2;
525
526 Register I1DestReg = I1.getOperand(0).getReg();
527
528 for (MachineBasicBlock::iterator End = I1.getParent()->end(); I2 != End;
529 ++I2) {
530 // Bail out early if we see a second definition of I1DestReg.
531 if (I2->modifiesRegister(I1DestReg, TRI))
532 break;
533
534 // Ignore non-combinable instructions.
535 if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))
536 continue;
537
538 // Don't combine a TFR whose user could be newified.
539 if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&*I2))
540 continue;
541
542 Register I2DestReg = I2->getOperand(0).getReg();
543
544 // Check that registers are adjacent and that the first destination register
545 // is even.
546 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
547 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
548 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
549 if ((!IsI1LowReg && !IsI2LowReg) || !isEvenReg(FirstRegIndex))
550 continue;
551
552 // Check that the two instructions are combinable.
553 // The order matters because in a A2_tfrsi we might can encode a int8 as
554 // the hi reg operand but only a uint6 as the low reg operand.
555 if ((IsI2LowReg && !areCombinableOperations(TRI, I1, *I2, AllowC64)) ||
556 (IsI1LowReg && !areCombinableOperations(TRI, *I2, I1, AllowC64)))
557 break;
558
559 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
560 return &*I2;
561
562 // Not safe. Stop searching.
563 break;
564 }
565 return nullptr;
566}
567
568void HexagonCopyToCombine::combine(MachineInstr &I1, MachineInstr &I2,
570 bool DoInsertAtI1, bool OptForSize) {
571 // We are going to delete I2. If MI points to I2 advance it to the next
572 // instruction.
573 if (MI == I2.getIterator())
574 ++MI;
575
576 // Figure out whether I1 or I2 goes into the lowreg part.
577 Register I1DestReg = I1.getOperand(0).getReg();
578 Register I2DestReg = I2.getOperand(0).getReg();
579 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
580 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
581 unsigned SubLo;
582
583 const TargetRegisterClass *SuperRC = nullptr;
584 if (Hexagon::IntRegsRegClass.contains(LoRegDef)) {
585 SuperRC = &Hexagon::DoubleRegsRegClass;
586 SubLo = Hexagon::isub_lo;
587 } else if (Hexagon::HvxVRRegClass.contains(LoRegDef)) {
588 assert(ST->useHVXOps());
589 SuperRC = &Hexagon::HvxWRRegClass;
590 SubLo = Hexagon::vsub_lo;
591 } else
592 llvm_unreachable("Unexpected register class");
593
594 // Get the double word register.
595 unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
596 assert(DoubleRegDest != 0 && "Expect a valid register");
597
598 // Setup source operands.
599 MachineOperand &LoOperand = IsI1Loreg ? I1.getOperand(1) : I2.getOperand(1);
600 MachineOperand &HiOperand = IsI1Loreg ? I2.getOperand(1) : I1.getOperand(1);
601
602 // Figure out which source is a register and which a constant.
603 bool IsHiReg = HiOperand.isReg();
604 bool IsLoReg = LoOperand.isReg();
605
606 // There is a combine of two constant extended values into CONST64.
607 bool IsC64 = OptForSize && LoOperand.isImm() && HiOperand.isImm() &&
608 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
609
610 MachineBasicBlock::iterator InsertPt(DoInsertAtI1 ? I1 : I2);
611 // Emit combine.
612 if (IsHiReg && IsLoReg)
613 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
614 else if (IsHiReg)
615 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
616 else if (IsLoReg)
617 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
618 else if (IsC64 && !IsConst64Disabled)
619 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
620 else
621 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
622
623 // Move debug instructions along with I1 if it's being
624 // moved towards I2.
625 if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {
626 // Insert debug instructions at the new location before I2.
627 MachineBasicBlock *BB = InsertPt->getParent();
628 for (auto *NewMI : DbgMItoMove) {
629 // If iterator MI is pointing to DEBUG_VAL, make sure
630 // MI now points to next relevant instruction.
631 if (NewMI == MI)
632 ++MI;
633 BB->splice(InsertPt, BB, NewMI);
634 }
635 }
636
637 I1.eraseFromParent();
638 I2.eraseFromParent();
639}
640
641void HexagonCopyToCombine::emitConst64(MachineBasicBlock::iterator &InsertPt,
642 unsigned DoubleDestReg,
643 MachineOperand &HiOperand,
644 MachineOperand &LoOperand) {
645 LLVM_DEBUG(dbgs() << "Found a CONST64\n");
646
647 DebugLoc DL = InsertPt->getDebugLoc();
648 MachineBasicBlock *BB = InsertPt->getParent();
649 assert(LoOperand.isImm() && HiOperand.isImm() &&
650 "Both operands must be immediate");
651
652 int64_t V = HiOperand.getImm();
653 V = (V << 32) | (0x0ffffffffLL & LoOperand.getImm());
654 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg)
655 .addImm(V);
656}
657
658void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt,
659 unsigned DoubleDestReg,
660 MachineOperand &HiOperand,
661 MachineOperand &LoOperand) {
662 DebugLoc DL = InsertPt->getDebugLoc();
663 MachineBasicBlock *BB = InsertPt->getParent();
664
665 // Handle globals.
666 if (HiOperand.isGlobal()) {
667 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
668 .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(),
669 HiOperand.getTargetFlags())
670 .addImm(LoOperand.getImm());
671 return;
672 }
673 if (LoOperand.isGlobal()) {
674 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
675 .addImm(HiOperand.getImm())
676 .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(),
677 LoOperand.getTargetFlags());
678 return;
679 }
680
681 // Handle block addresses.
682 if (HiOperand.isBlockAddress()) {
683 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
684 .addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(),
685 HiOperand.getTargetFlags())
686 .addImm(LoOperand.getImm());
687 return;
688 }
689 if (LoOperand.isBlockAddress()) {
690 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
691 .addImm(HiOperand.getImm())
692 .addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(),
693 LoOperand.getTargetFlags());
694 return;
695 }
696
697 // Handle jump tables.
698 if (HiOperand.isJTI()) {
699 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
700 .addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags())
701 .addImm(LoOperand.getImm());
702 return;
703 }
704 if (LoOperand.isJTI()) {
705 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
706 .addImm(HiOperand.getImm())
707 .addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags());
708 return;
709 }
710
711 // Handle constant pools.
712 if (HiOperand.isCPI()) {
713 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
714 .addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(),
715 HiOperand.getTargetFlags())
716 .addImm(LoOperand.getImm());
717 return;
718 }
719 if (LoOperand.isCPI()) {
720 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
721 .addImm(HiOperand.getImm())
722 .addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(),
723 LoOperand.getTargetFlags());
724 return;
725 }
726
727 // First preference should be given to Hexagon::A2_combineii instruction
728 // as it can include U6 (in Hexagon::A4_combineii) as well.
729 // In this instruction, HiOperand is const extended, if required.
730 if (isInt<8>(LoOperand.getImm())) {
731 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
732 .addImm(HiOperand.getImm())
733 .addImm(LoOperand.getImm());
734 return;
735 }
736
737 // In this instruction, LoOperand is const extended, if required.
738 if (isInt<8>(HiOperand.getImm())) {
739 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
740 .addImm(HiOperand.getImm())
741 .addImm(LoOperand.getImm());
742 return;
743 }
744
745 // Insert new combine instruction.
746 // DoubleRegDest = combine #HiImm, #LoImm
747 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
748 .addImm(HiOperand.getImm())
749 .addImm(LoOperand.getImm());
750}
751
752void HexagonCopyToCombine::emitCombineIR(MachineBasicBlock::iterator &InsertPt,
753 unsigned DoubleDestReg,
754 MachineOperand &HiOperand,
755 MachineOperand &LoOperand) {
756 Register LoReg = LoOperand.getReg();
757 unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill());
758
759 DebugLoc DL = InsertPt->getDebugLoc();
760 MachineBasicBlock *BB = InsertPt->getParent();
761
762 // Handle globals.
763 if (HiOperand.isGlobal()) {
764 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
765 .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(),
766 HiOperand.getTargetFlags())
767 .addReg(LoReg, LoRegKillFlag);
768 return;
769 }
770 // Handle block addresses.
771 if (HiOperand.isBlockAddress()) {
772 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
773 .addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(),
774 HiOperand.getTargetFlags())
775 .addReg(LoReg, LoRegKillFlag);
776 return;
777 }
778 // Handle jump tables.
779 if (HiOperand.isJTI()) {
780 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
781 .addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags())
782 .addReg(LoReg, LoRegKillFlag);
783 return;
784 }
785 // Handle constant pools.
786 if (HiOperand.isCPI()) {
787 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
788 .addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(),
789 HiOperand.getTargetFlags())
790 .addReg(LoReg, LoRegKillFlag);
791 return;
792 }
793 // Insert new combine instruction.
794 // DoubleRegDest = combine #HiImm, LoReg
795 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
796 .addImm(HiOperand.getImm())
797 .addReg(LoReg, LoRegKillFlag);
798}
799
800void HexagonCopyToCombine::emitCombineRI(MachineBasicBlock::iterator &InsertPt,
801 unsigned DoubleDestReg,
802 MachineOperand &HiOperand,
803 MachineOperand &LoOperand) {
804 unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill());
805 Register HiReg = HiOperand.getReg();
806
807 DebugLoc DL = InsertPt->getDebugLoc();
808 MachineBasicBlock *BB = InsertPt->getParent();
809
810 // Handle global.
811 if (LoOperand.isGlobal()) {
812 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
813 .addReg(HiReg, HiRegKillFlag)
814 .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(),
815 LoOperand.getTargetFlags());
816 return;
817 }
818 // Handle block addresses.
819 if (LoOperand.isBlockAddress()) {
820 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
821 .addReg(HiReg, HiRegKillFlag)
822 .addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(),
823 LoOperand.getTargetFlags());
824 return;
825 }
826 // Handle jump tables.
827 if (LoOperand.isJTI()) {
828 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
829 .addReg(HiOperand.getReg(), HiRegKillFlag)
830 .addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags());
831 return;
832 }
833 // Handle constant pools.
834 if (LoOperand.isCPI()) {
835 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
836 .addReg(HiOperand.getReg(), HiRegKillFlag)
837 .addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(),
838 LoOperand.getTargetFlags());
839 return;
840 }
841
842 // Insert new combine instruction.
843 // DoubleRegDest = combine HiReg, #LoImm
844 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
845 .addReg(HiReg, HiRegKillFlag)
846 .addImm(LoOperand.getImm());
847}
848
849void HexagonCopyToCombine::emitCombineRR(MachineBasicBlock::iterator &InsertPt,
850 unsigned DoubleDestReg,
851 MachineOperand &HiOperand,
852 MachineOperand &LoOperand) {
853 unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill());
854 unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill());
855 Register LoReg = LoOperand.getReg();
856 Register HiReg = HiOperand.getReg();
857
858 DebugLoc DL = InsertPt->getDebugLoc();
859 MachineBasicBlock *BB = InsertPt->getParent();
860
861 // Insert new combine instruction.
862 // DoubleRegDest = combine HiReg, LoReg
863 unsigned NewOpc;
864 if (Hexagon::DoubleRegsRegClass.contains(DoubleDestReg)) {
865 NewOpc = Hexagon::A2_combinew;
866 } else if (Hexagon::HvxWRRegClass.contains(DoubleDestReg)) {
867 assert(ST->useHVXOps());
868 NewOpc = Hexagon::V6_vcombine;
869 } else
870 llvm_unreachable("Unexpected register");
871
872 BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)
873 .addReg(HiReg, HiRegKillFlag)
874 .addReg(LoReg, LoRegKillFlag);
875}
876
878 return new HexagonCopyToCombine();
879}
unsigned SubReg
aarch64 promote const
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
bool End
Definition: ELF_riscv.cpp:480
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)
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
Represent the analysis usage information of a pass.
This class represents an Operation in the Expression.
A debug info location.
Definition: DebugLoc.h:33
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
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 LLVMTargetMachine & 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.
Definition: MachineInstr.h:69
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr kills the specified register.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:544
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
Definition: MachineInstr.h:554
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() 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...
Definition: PassRegistry.h:37
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:65
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
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()
Definition: ilist_node.h:109
#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.
Definition: CallingConv.h:24
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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.
Definition: Debug.cpp:163
FunctionPass * createHexagonCopyToCombine()
unsigned getKillRegState(bool B)
void initializeHexagonCopyToCombinePass(PassRegistry &)