Skip to content

Commit b7836d8

Browse files
Yashwant SinghYashwant Singh
Yashwant Singh
authored and
Yashwant Singh
committed
[CodeGen]Allow targets to use target specific COPY instructions for live range splitting
Replacing D143754. Right now the LiveRangeSplitting during register allocation uses TargetOpcode::COPY instruction for splitting. For AMDGPU target that creates a problem as we have both vector and scalar copies. Vector copies perform a copy over a vector register but only on the lanes(threads) that are active. This is mostly sufficient however we do run into cases when we have to copy the entire vector register and not just active lane data. One major place where we need that is live range splitting. Allowing targets to use their own copy instructions(if defined) will provide a lot of flexibility and ease to lower these pseudo instructions to correct MIR. - Introduce getTargetCopyOpcode() virtual function and use if to generate copy in Live range splitting. - Replace necessary MI.isCopy() checks with TII.isCopyInstr() in register allocator pipeline. Reviewed By: arsenm, cdevadas, kparzysz Differential Revision: https://reviews.llvm.org/D150388
1 parent eb98aba commit b7836d8

15 files changed

+148
-107
lines changed

llvm/include/llvm/CodeGen/TargetInstrInfo.h

+17
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,16 @@ class TargetInstrInfo : public MCInstrInfo {
10441044
return isCopyInstrImpl(MI);
10451045
}
10461046

1047+
bool isFullCopyInstr(const MachineInstr &MI) const {
1048+
auto DestSrc = isCopyInstr(MI);
1049+
if (!DestSrc)
1050+
return false;
1051+
1052+
const MachineOperand *DestRegOp = DestSrc->Destination;
1053+
const MachineOperand *SrcRegOp = DestSrc->Source;
1054+
return !DestRegOp->getSubReg() && !SrcRegOp->getSubReg();
1055+
}
1056+
10471057
/// If the specific machine instruction is an instruction that adds an
10481058
/// immediate value and a physical register, and stores the result in
10491059
/// the given physical register \c Reg, return a pair of the source
@@ -1958,6 +1968,13 @@ class TargetInstrInfo : public MCInstrInfo {
19581968
return false;
19591969
}
19601970

1971+
/// Allows targets to use appropriate copy instruction while spilitting live
1972+
/// range of a register in register allocation.
1973+
virtual unsigned getLiveRangeSplitOpcode(Register Reg,
1974+
const MachineFunction &MF) const {
1975+
return TargetOpcode::COPY;
1976+
}
1977+
19611978
/// During PHI eleimination lets target to make necessary checks and
19621979
/// insert the copy to the PHI destination register in a target specific
19631980
/// manner.

llvm/lib/CodeGen/CalcSpillWeights.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ bool VirtRegAuxInfo::isRematerializable(const LiveInterval &LI,
9797
// Trace copies introduced by live range splitting. The inline
9898
// spiller can rematerialize through these copies, so the spill
9999
// weight must reflect this.
100-
while (MI->isFullCopy()) {
100+
while (TII.isFullCopyInstr(*MI)) {
101101
// The copy destination must match the interval register.
102102
if (MI->getOperand(0).getReg() != Reg)
103103
return false;
@@ -224,7 +224,16 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
224224
continue;
225225

226226
NumInstr++;
227-
if (MI->isIdentityCopy() || MI->isImplicitDef())
227+
bool identityCopy = false;
228+
auto DestSrc = TII.isCopyInstr(*MI);
229+
if (DestSrc) {
230+
const MachineOperand *DestRegOp = DestSrc->Destination;
231+
const MachineOperand *SrcRegOp = DestSrc->Source;
232+
identityCopy = DestRegOp->getReg() == SrcRegOp->getReg() &&
233+
DestRegOp->getSubReg() == SrcRegOp->getSubReg();
234+
}
235+
236+
if (identityCopy || MI->isImplicitDef())
228237
continue;
229238
if (!Visited.insert(MI).second)
230239
continue;
@@ -258,7 +267,7 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
258267
}
259268

260269
// Get allocation hints from copies.
261-
if (!MI->isCopy())
270+
if (!TII.isCopyInstr(*MI))
262271
continue;
263272
Register HintReg = copyHint(MI, LI.reg(), TRI, MRI);
264273
if (!HintReg)

llvm/lib/CodeGen/InlineSpiller.cpp

+15-14
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,11 @@ Spiller *llvm::createInlineSpiller(MachineFunctionPass &Pass,
256256
// This minimizes register pressure and maximizes the store-to-load distance for
257257
// spill slots which can be important in tight loops.
258258

259-
/// If MI is a COPY to or from Reg, return the other register, otherwise return
260-
/// 0.
261-
static Register isCopyOf(const MachineInstr &MI, Register Reg) {
262-
assert(!MI.isBundled());
263-
if (!MI.isCopy())
259+
/// isFullCopyOf - If MI is a COPY to or from Reg, return the other register,
260+
/// otherwise return 0.
261+
static Register isCopyOf(const MachineInstr &MI, Register Reg,
262+
const TargetInstrInfo &TII) {
263+
if (!TII.isCopyInstr(MI))
264264
return Register();
265265

266266
const MachineOperand &DstOp = MI.getOperand(0);
@@ -277,9 +277,10 @@ static Register isCopyOf(const MachineInstr &MI, Register Reg) {
277277
}
278278

279279
/// Check for a copy bundle as formed by SplitKit.
280-
static Register isCopyOfBundle(const MachineInstr &FirstMI, Register Reg) {
280+
static Register isCopyOfBundle(const MachineInstr &FirstMI, Register Reg,
281+
const TargetInstrInfo &TII) {
281282
if (!FirstMI.isBundled())
282-
return isCopyOf(FirstMI, Reg);
283+
return isCopyOf(FirstMI, Reg, TII);
283284

284285
assert(!FirstMI.isBundledWithPred() && FirstMI.isBundledWithSucc() &&
285286
"expected to see first instruction in bundle");
@@ -288,7 +289,7 @@ static Register isCopyOfBundle(const MachineInstr &FirstMI, Register Reg) {
288289
MachineBasicBlock::const_instr_iterator I = FirstMI.getIterator();
289290
while (I->isBundledWithSucc()) {
290291
const MachineInstr &MI = *I;
291-
if (!MI.isCopy())
292+
if (!TII.isCopyInstr(FirstMI))
292293
return Register();
293294

294295
const MachineOperand &DstOp = MI.getOperand(0);
@@ -358,7 +359,7 @@ bool InlineSpiller::isSnippet(const LiveInterval &SnipLI) {
358359
MachineInstr &MI = *RI++;
359360

360361
// Allow copies to/from Reg.
361-
if (isCopyOfBundle(MI, Reg))
362+
if (isCopyOfBundle(MI, Reg, TII))
362363
continue;
363364

364365
// Allow stack slot loads.
@@ -396,7 +397,7 @@ void InlineSpiller::collectRegsToSpill() {
396397
return;
397398

398399
for (MachineInstr &MI : llvm::make_early_inc_range(MRI.reg_bundles(Reg))) {
399-
Register SnipReg = isCopyOfBundle(MI, Reg);
400+
Register SnipReg = isCopyOfBundle(MI, Reg, TII);
400401
if (!isSibling(SnipReg))
401402
continue;
402403
LiveInterval &SnipLI = LIS.getInterval(SnipReg);
@@ -519,14 +520,14 @@ void InlineSpiller::eliminateRedundantSpills(LiveInterval &SLI, VNInfo *VNI) {
519520
// Find all spills and copies of VNI.
520521
for (MachineInstr &MI :
521522
llvm::make_early_inc_range(MRI.use_nodbg_bundles(Reg))) {
522-
if (!MI.isCopy() && !MI.mayStore())
523+
if (!MI.mayStore() && !TII.isCopyInstr(MI))
523524
continue;
524525
SlotIndex Idx = LIS.getInstructionIndex(MI);
525526
if (LI->getVNInfoAt(Idx) != VNI)
526527
continue;
527528

528529
// Follow sibling copies down the dominator tree.
529-
if (Register DstReg = isCopyOfBundle(MI, Reg)) {
530+
if (Register DstReg = isCopyOfBundle(MI, Reg, TII)) {
530531
if (isSibling(DstReg)) {
531532
LiveInterval &DstLI = LIS.getInterval(DstReg);
532533
VNInfo *DstVNI = DstLI.getVNInfoAt(Idx.getRegSlot());
@@ -870,7 +871,7 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr *, unsigned>> Ops,
870871
if (Ops.back().first != MI || MI->isBundled())
871872
return false;
872873

873-
bool WasCopy = MI->isCopy();
874+
bool WasCopy = TII.isCopyInstr(*MI).has_value();
874875
Register ImpReg;
875876

876877
// TII::foldMemoryOperand will do what we need here for statepoint
@@ -1155,7 +1156,7 @@ void InlineSpiller::spillAroundUses(Register Reg) {
11551156
Idx = VNI->def;
11561157

11571158
// Check for a sibling copy.
1158-
Register SibReg = isCopyOfBundle(MI, Reg);
1159+
Register SibReg = isCopyOfBundle(MI, Reg, TII);
11591160
if (SibReg && isSibling(SibReg)) {
11601161
// This may actually be a copy between snippets.
11611162
if (isRegToSpill(SibReg)) {

llvm/lib/CodeGen/LiveRangeEdit.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,8 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
352352
// unlikely to change anything. We typically don't want to shrink the
353353
// PIC base register that has lots of uses everywhere.
354354
// Always shrink COPY uses that probably come from live range splitting.
355-
if ((MI->readsVirtualRegister(Reg) && (MI->isCopy() || MO.isDef())) ||
355+
if ((MI->readsVirtualRegister(Reg) &&
356+
(MO.isDef() || TII.isCopyInstr(*MI))) ||
356357
(MO.readsReg() && (MRI.hasOneNonDBGUse(Reg) || useIsKill(LI, MO))))
357358
ToShrink.insert(&LI);
358359
else if (MO.readsReg())

llvm/lib/CodeGen/LiveRangeShrink.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/CodeGen/MachineInstr.h"
2424
#include "llvm/CodeGen/MachineOperand.h"
2525
#include "llvm/CodeGen/MachineRegisterInfo.h"
26+
#include "llvm/CodeGen/TargetInstrInfo.h"
2627
#include "llvm/InitializePasses.h"
2728
#include "llvm/Pass.h"
2829
#include "llvm/Support/Debug.h"
@@ -109,6 +110,7 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
109110
return false;
110111

111112
MachineRegisterInfo &MRI = MF.getRegInfo();
113+
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
112114

113115
LLVM_DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n');
114116

@@ -197,7 +199,7 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) {
197199
// is because it needs more accurate model to handle register
198200
// pressure correctly.
199201
MachineInstr &DefInstr = *MRI.def_instr_begin(Reg);
200-
if (!DefInstr.isCopy())
202+
if (!TII.isCopyInstr(DefInstr))
201203
NumEligibleUse++;
202204
Insert = FindDominatedInstruction(DefInstr, Insert, IOM);
203205
} else {

llvm/lib/CodeGen/RegAllocGreedy.cpp

+12-9
Original file line numberDiff line numberDiff line change
@@ -1282,10 +1282,12 @@ static LaneBitmask getInstReadLaneMask(const MachineRegisterInfo &MRI,
12821282
/// VirtReg.
12831283
static bool readsLaneSubset(const MachineRegisterInfo &MRI,
12841284
const MachineInstr *MI, const LiveInterval &VirtReg,
1285-
const TargetRegisterInfo *TRI, SlotIndex Use) {
1285+
const TargetRegisterInfo *TRI, SlotIndex Use,
1286+
const TargetInstrInfo *TII) {
12861287
// Early check the common case.
1287-
if (MI->isCopy() &&
1288-
MI->getOperand(0).getSubReg() == MI->getOperand(1).getSubReg())
1288+
auto DestSrc = TII->isCopyInstr(*MI);
1289+
if (DestSrc &&
1290+
DestSrc->Destination->getSubReg() == DestSrc->Source->getSubReg())
12891291
return false;
12901292

12911293
// FIXME: We're only considering uses, but should be consider defs too?
@@ -1344,14 +1346,14 @@ unsigned RAGreedy::tryInstructionSplit(const LiveInterval &VirtReg,
13441346
// the allocation.
13451347
for (const SlotIndex Use : Uses) {
13461348
if (const MachineInstr *MI = Indexes->getInstructionFromIndex(Use)) {
1347-
if (MI->isFullCopy() ||
1349+
if (TII->isFullCopyInstr(*MI) ||
13481350
(SplitSubClass &&
13491351
SuperRCNumAllocatableRegs ==
13501352
getNumAllocatableRegsForConstraints(MI, VirtReg.reg(), SuperRC,
13511353
TII, TRI, RegClassInfo)) ||
13521354
// TODO: Handle split for subranges with subclass constraints?
13531355
(!SplitSubClass && VirtReg.hasSubRanges() &&
1354-
!readsLaneSubset(*MRI, MI, VirtReg, TRI, Use))) {
1356+
!readsLaneSubset(*MRI, MI, VirtReg, TRI, Use, TII))) {
13551357
LLVM_DEBUG(dbgs() << " skip:\t" << Use << '\t' << *MI);
13561358
continue;
13571359
}
@@ -2138,7 +2140,7 @@ void RAGreedy::initializeCSRCost() {
21382140
/// \p Out is not cleared before being populated.
21392141
void RAGreedy::collectHintInfo(Register Reg, HintsInfo &Out) {
21402142
for (const MachineInstr &Instr : MRI->reg_nodbg_instructions(Reg)) {
2141-
if (!Instr.isFullCopy())
2143+
if (!TII->isFullCopyInstr(Instr))
21422144
continue;
21432145
// Look for the other end of the copy.
21442146
Register OtherReg = Instr.getOperand(0).getReg();
@@ -2453,9 +2455,10 @@ RAGreedy::RAGreedyStats RAGreedy::computeStats(MachineBasicBlock &MBB) {
24532455
MI.getOpcode() == TargetOpcode::STATEPOINT;
24542456
};
24552457
for (MachineInstr &MI : MBB) {
2456-
if (MI.isCopy()) {
2457-
const MachineOperand &Dest = MI.getOperand(0);
2458-
const MachineOperand &Src = MI.getOperand(1);
2458+
auto DestSrc = TII->isCopyInstr(MI);
2459+
if (DestSrc) {
2460+
const MachineOperand &Dest = *DestSrc->Destination;
2461+
const MachineOperand &Src = *DestSrc->Source;
24592462
Register SrcReg = Src.getReg();
24602463
Register DestReg = Dest.getReg();
24612464
// Only count `COPY`s with a virtual register as source or destination.

llvm/lib/CodeGen/SplitKit.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,10 @@ void SplitEditor::forceRecompute(unsigned RegIdx, const VNInfo &ParentVNI) {
514514
VFP = ValueForcePair(nullptr, true);
515515
}
516516

517-
SlotIndex SplitEditor::buildSingleSubRegCopy(Register FromReg, Register ToReg,
518-
MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore,
519-
unsigned SubIdx, LiveInterval &DestLI, bool Late, SlotIndex Def) {
520-
const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
517+
SlotIndex SplitEditor::buildSingleSubRegCopy(
518+
Register FromReg, Register ToReg, MachineBasicBlock &MBB,
519+
MachineBasicBlock::iterator InsertBefore, unsigned SubIdx,
520+
LiveInterval &DestLI, bool Late, SlotIndex Def, const MCInstrDesc &Desc) {
521521
bool FirstCopy = !Def.isValid();
522522
MachineInstr *CopyMI = BuildMI(MBB, InsertBefore, DebugLoc(), Desc)
523523
.addReg(ToReg, RegState::Define | getUndefRegState(FirstCopy)
@@ -536,7 +536,8 @@ SlotIndex SplitEditor::buildSingleSubRegCopy(Register FromReg, Register ToReg,
536536
SlotIndex SplitEditor::buildCopy(Register FromReg, Register ToReg,
537537
LaneBitmask LaneMask, MachineBasicBlock &MBB,
538538
MachineBasicBlock::iterator InsertBefore, bool Late, unsigned RegIdx) {
539-
const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
539+
const MCInstrDesc &Desc =
540+
TII.get(TII.getLiveRangeSplitOpcode(FromReg, *MBB.getParent()));
540541
SlotIndexes &Indexes = *LIS.getSlotIndexes();
541542
if (LaneMask.all() || LaneMask == MRI.getMaxLaneMaskForVReg(FromReg)) {
542543
// The full vreg is copied.
@@ -564,7 +565,7 @@ SlotIndex SplitEditor::buildCopy(Register FromReg, Register ToReg,
564565
SlotIndex Def;
565566
for (unsigned BestIdx : SubIndexes) {
566567
Def = buildSingleSubRegCopy(FromReg, ToReg, MBB, InsertBefore, BestIdx,
567-
DestLI, Late, Def);
568+
DestLI, Late, Def, Desc);
568569
}
569570

570571
BumpPtrAllocator &Allocator = LIS.getVNInfoAllocator();
@@ -1584,7 +1585,9 @@ bool SplitAnalysis::shouldSplitSingleBlock(const BlockInfo &BI,
15841585
if (BI.LiveIn && BI.LiveOut)
15851586
return true;
15861587
// No point in isolating a copy. It has no register class constraints.
1587-
if (LIS.getInstructionFromIndex(BI.FirstInstr)->isCopyLike())
1588+
MachineInstr *MI = LIS.getInstructionFromIndex(BI.FirstInstr);
1589+
bool copyLike = TII.isCopyInstr(*MI) || MI->isSubregToReg();
1590+
if (copyLike)
15881591
return false;
15891592
// Finally, don't isolate an end point that was created by earlier splits.
15901593
return isOriginalEndpoint(BI.FirstInstr);

llvm/lib/CodeGen/SplitKit.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,11 @@ class LLVM_LIBRARY_VISIBILITY SplitEditor {
428428
bool Late, unsigned RegIdx);
429429

430430
SlotIndex buildSingleSubRegCopy(Register FromReg, Register ToReg,
431-
MachineBasicBlock &MB, MachineBasicBlock::iterator InsertBefore,
432-
unsigned SubIdx, LiveInterval &DestLI, bool Late, SlotIndex Def);
431+
MachineBasicBlock &MB,
432+
MachineBasicBlock::iterator InsertBefore,
433+
unsigned SubIdx, LiveInterval &DestLI,
434+
bool Late, SlotIndex Def,
435+
const MCInstrDesc &Desc);
433436

434437
public:
435438
/// Create a new SplitEditor for editing the LiveInterval analyzed by SA.

llvm/lib/CodeGen/TargetInstrInfo.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,9 @@ MachineInstr &TargetInstrInfo::duplicate(MachineBasicBlock &MBB,
440440
// If the COPY instruction in MI can be folded to a stack operation, return
441441
// the register class to use.
442442
static const TargetRegisterClass *canFoldCopy(const MachineInstr &MI,
443+
const TargetInstrInfo &TII,
443444
unsigned FoldIdx) {
444-
assert(MI.isCopy() && "MI must be a COPY instruction");
445+
assert(TII.isCopyInstr(MI) && "MI must be a COPY instruction");
445446
if (MI.getNumOperands() != 2)
446447
return nullptr;
447448
assert(FoldIdx<2 && "FoldIdx refers no nonexistent operand");
@@ -630,10 +631,10 @@ MachineInstr *TargetInstrInfo::foldMemoryOperand(MachineInstr &MI,
630631
}
631632

632633
// Straight COPY may fold as load/store.
633-
if (!MI.isCopy() || Ops.size() != 1)
634+
if (!isCopyInstr(MI) || Ops.size() != 1)
634635
return nullptr;
635636

636-
const TargetRegisterClass *RC = canFoldCopy(MI, Ops[0]);
637+
const TargetRegisterClass *RC = canFoldCopy(MI, *this, Ops[0]);
637638
if (!RC)
638639
return nullptr;
639640

0 commit comments

Comments
 (0)