Skip to content

Commit 7ef1381

Browse files
committed
[RISCV] Support overlapping constraints
1 parent 6273c5d commit 7ef1381

File tree

11 files changed

+443
-6
lines changed

11 files changed

+443
-6
lines changed

llvm/include/llvm/CodeGen/LiveRegMatrix.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class LiveRegMatrix {
4141
friend class LiveRegMatrixWrapperLegacy;
4242
friend class LiveRegMatrixAnalysis;
4343
const TargetRegisterInfo *TRI = nullptr;
44+
const MachineRegisterInfo *MRI;
4445
LiveIntervals *LIS = nullptr;
4546
VirtRegMap *VRM = nullptr;
4647

@@ -108,6 +109,12 @@ class LiveRegMatrix {
108109
InterferenceKind checkInterference(const LiveInterval &VirtReg,
109110
MCRegister PhysReg);
110111

112+
/// Check for target interference before assigning VirtReg to PhysReg.Add
113+
/// commentMore actions
114+
SmallVector<const LiveInterval *, 8>
115+
getTargetInterferenceLiveI(const LiveInterval &VirtReg,
116+
MCRegister PhysReg) const;
117+
111118
/// Check for interference in the segment [Start, End) that may prevent
112119
/// assignment to PhysReg. If this function returns true, there is
113120
/// interference in the segment [Start, End) of some other interval already

llvm/include/llvm/CodeGen/TargetRegisterInfo.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define LLVM_CODEGEN_TARGETREGISTERINFO_H
1717

1818
#include "llvm/ADT/ArrayRef.h"
19+
#include "llvm/ADT/BitVector.h"
1920
#include "llvm/ADT/SmallVector.h"
2021
#include "llvm/ADT/StringRef.h"
2122
#include "llvm/ADT/iterator_range.h"
@@ -42,6 +43,7 @@ class RegScavenger;
4243
class VirtRegMap;
4344
class LiveIntervals;
4445
class LiveInterval;
46+
class LiveRange;
4547
class TargetRegisterClass {
4648
public:
4749
using iterator = const MCPhysReg *;
@@ -1230,6 +1232,20 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
12301232
return false;
12311233
}
12321234

1235+
virtual bool enableTargetInterference() const { return false; }
1236+
1237+
virtual BitVector getTargetInterferenceReg(const LiveInterval &VirtReg,
1238+
MCRegister PhysReg,
1239+
const MachineRegisterInfo *MRI,
1240+
const VirtRegMap *VRM) const {
1241+
return BitVector();
1242+
}
1243+
1244+
virtual bool needUpdateECSlot(const LiveRange &LR, LiveRange &newLR,
1245+
const LiveIntervals &LIS) const {
1246+
return false;
1247+
}
1248+
12331249
/// Some targets delay assigning the frame until late and use a placeholder
12341250
/// to represent it earlier. This method can be used to identify the frame
12351251
/// register placeholder.

llvm/lib/CodeGen/LiveRegMatrix.cpp

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ bool LiveRegMatrixWrapperLegacy::runOnMachineFunction(MachineFunction &MF) {
6060
void LiveRegMatrix::init(MachineFunction &MF, LiveIntervals &pLIS,
6161
VirtRegMap &pVRM) {
6262
TRI = MF.getSubtarget().getRegisterInfo();
63+
MRI = &MF.getRegInfo();
6364
LIS = &pLIS;
6465
VRM = &pVRM;
6566

@@ -83,6 +84,14 @@ void LiveRegMatrix::releaseMemory() {
8384
}
8485
}
8586

87+
static LiveRange copyLiveRange(const LiveRange &LR) {
88+
LiveRange NewLR;
89+
for (auto Seg : LR.segments)
90+
NewLR.addSegment(Seg);
91+
NewLR.valnos.append(LR.vni_begin(), LR.vni_end());
92+
return NewLR;
93+
}
94+
8695
template <typename Callable>
8796
static bool foreachUnit(const TargetRegisterInfo *TRI,
8897
const LiveInterval &VRegInterval, MCRegister PhysReg,
@@ -117,7 +126,12 @@ void LiveRegMatrix::assign(const LiveInterval &VirtReg, MCRegister PhysReg) {
117126
foreachUnit(
118127
TRI, VirtReg, PhysReg, [&](unsigned Unit, const LiveRange &Range) {
119128
LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI) << ' ' << Range);
120-
Matrix[Unit].unify(VirtReg, Range);
129+
LiveRange NewLR;
130+
if (TRI->enableTargetInterference() &&
131+
TRI->needUpdateECSlot(Range, NewLR = copyLiveRange(Range), *LIS))
132+
Matrix[Unit].unify(VirtReg, NewLR);
133+
else
134+
Matrix[Unit].unify(VirtReg, Range);
121135
return false;
122136
});
123137

@@ -134,7 +148,13 @@ void LiveRegMatrix::unassign(const LiveInterval &VirtReg) {
134148
foreachUnit(TRI, VirtReg, PhysReg,
135149
[&](unsigned Unit, const LiveRange &Range) {
136150
LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI));
137-
Matrix[Unit].extract(VirtReg, Range);
151+
LiveRange NewLR;
152+
if (TRI->enableTargetInterference() &&
153+
TRI->needUpdateECSlot(Range, NewLR = copyLiveRange(Range),
154+
*LIS))
155+
Matrix[Unit].extract(VirtReg, NewLR);
156+
else
157+
Matrix[Unit].extract(VirtReg, Range);
138158
return false;
139159
});
140160

@@ -150,6 +170,31 @@ bool LiveRegMatrix::isPhysRegUsed(MCRegister PhysReg) const {
150170
return false;
151171
}
152172

173+
SmallVector<const LiveInterval *, 8>
174+
LiveRegMatrix::getTargetInterferenceLiveI(const LiveInterval &VirtReg,
175+
MCRegister PhysReg) const {
176+
SmallVector<const LiveInterval *, 8> LiveIs;
177+
if (!TRI->enableTargetInterference())
178+
return LiveIs;
179+
180+
BitVector IntfReg = TRI->getTargetInterferenceReg(VirtReg, PhysReg, MRI, VRM);
181+
182+
for (auto Reg : IntfReg.set_bits()) {
183+
for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
184+
LiveIntervalUnion LiveUnion = Matrix[*Units];
185+
LiveIntervalUnion::ConstSegmentIter LiveUnionI = LiveUnion.begin();
186+
while (LiveUnionI != LiveUnion.end()) {
187+
const LiveRange *LiveR = *LiveUnionI;
188+
LiveRange NewLiveR = copyLiveRange(*LiveR);
189+
if (TRI->needUpdateECSlot(LiveR, NewLiveR, *LIS))
190+
LiveIs.push_back(*LiveUnionI);
191+
++LiveUnionI;
192+
}
193+
}
194+
}
195+
return LiveIs;
196+
}
197+
153198
bool LiveRegMatrix::checkRegMaskInterference(const LiveInterval &VirtReg,
154199
MCRegister PhysReg) {
155200
// Check if the cached information is valid.
@@ -178,7 +223,12 @@ bool LiveRegMatrix::checkRegUnitInterference(const LiveInterval &VirtReg,
178223
bool Result = foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit,
179224
const LiveRange &Range) {
180225
const LiveRange &UnitRange = LIS->getRegUnit(Unit);
181-
return Range.overlaps(UnitRange, CP, *LIS->getSlotIndexes());
226+
LiveRange NewLR;
227+
if (TRI->enableTargetInterference() &&
228+
TRI->needUpdateECSlot(Range, NewLR = copyLiveRange(Range), *LIS))
229+
return NewLR.overlaps(UnitRange, CP, *LIS->getSlotIndexes());
230+
else
231+
return Range.overlaps(UnitRange, CP, *LIS->getSlotIndexes());
182232
});
183233
return Result;
184234
}
@@ -204,9 +254,24 @@ LiveRegMatrix::checkInterference(const LiveInterval &VirtReg,
204254
if (checkRegUnitInterference(VirtReg, PhysReg))
205255
return IK_RegUnit;
206256

257+
if (TRI->enableTargetInterference() &&
258+
TRI->getTargetInterferenceReg(VirtReg, PhysReg, MRI, VRM).any())
259+
return IK_VirtReg;
260+
207261
// Check the matrix for virtual register interference.
208262
bool Interference = foreachUnit(TRI, VirtReg, PhysReg,
209263
[&](MCRegUnit Unit, const LiveRange &LR) {
264+
LiveRange NewLR;
265+
if (TRI->enableTargetInterference() &&
266+
TRI->needUpdateECSlot(
267+
LR, NewLR = copyLiveRange(LR), *LIS)) {
268+
// Update LiveRange could make cache
269+
// information stable. Refresh cache to
270+
// handle it.
271+
invalidateVirtRegs();
272+
return query(NewLR, Unit)
273+
.checkInterference();
274+
}
210275
return query(LR, Unit).checkInterference();
211276
});
212277
if (Interference)

llvm/lib/CodeGen/MachineCopyPropagation.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,17 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
921921
// later.
922922
if (MO.isTied())
923923
ReadRegister(Reg, MI, RegularUse);
924+
// If it be used by another instruction, it should not be deleted.Add commentMore actions
925+
for (const MachineOperand &UseMO : MI.uses()) {
926+
if (!UseMO.isReg())
927+
continue;
928+
MCRegister UseReg = UseMO.getReg().asMCReg();
929+
if (UseReg == MCRegister::NoRegister)
930+
continue;
931+
if (!TRI->regsOverlap(Reg, UseReg))
932+
continue;
933+
ReadRegister(UseReg, MI, RegularUse);
934+
}
924935
Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
925936
}
926937

llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,15 @@ bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost(
262262
LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
263263
// If there is 10 or more interferences, chances are one is heavier.
264264
const auto &Interferences = Q.interferingVRegs(EvictInterferenceCutoff);
265-
if (Interferences.size() >= EvictInterferenceCutoff)
265+
SmallVector<const LiveInterval *, 8> Intfs =
266+
Matrix->getTargetInterferenceLiveI(VirtReg, PhysReg);
267+
Intfs.append(Interferences.begin(), Interferences.end());
268+
269+
if (Intfs.size() >= EvictInterferenceCutoff)
266270
return false;
267271

268272
// Check if any interfering live range is heavier than MaxWeight.
269-
for (const LiveInterval *Intf : reverse(Interferences)) {
273+
for (const LiveInterval *Intf : reverse(Intfs)) {
270274
assert(Intf->reg().isVirtual() &&
271275
"Only expecting virtual register interference from query");
272276

llvm/lib/CodeGen/RegAllocGreedy.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,10 @@ void RAGreedy::evictInterference(const LiveInterval &VirtReg,
635635
Intfs.append(IVR.begin(), IVR.end());
636636
}
637637

638+
SmallVector<const LiveInterval *, 8> TargetIntfs =
639+
Matrix->getTargetInterferenceLiveI(VirtReg, PhysReg);
640+
Intfs.append(TargetIntfs.begin(), TargetIntfs.end());
641+
638642
// Evict them second. This will invalidate the queries.
639643
for (const LiveInterval *Intf : Intfs) {
640644
// The same VirtReg may be present in multiple RegUnits. Skip duplicates.

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,86 @@ void RISCVInstrInfo::genAlternativeCodeSequence(
26552655
}
26562656
}
26572657

2658+
int RISCVInstrInfo::getOverlapConstraintsFromMI(uint16_t RVVPseudoOpcode) {
2659+
const RISCVVPseudosTable::PseudoInfo *RVV =
2660+
RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
2661+
2662+
if (!RVV)
2663+
return 0;
2664+
2665+
return RVV->TargetOverlapConstraintType;
2666+
}
2667+
2668+
static bool getConstrainsBetweenDstAndSrc(const MachineInstr *MBBI,
2669+
MachineOperand DestMO,
2670+
MachineOperand SrcMO,
2671+
int OverlapConstraintsType) {
2672+
MCRegister DestReg = DestMO.getReg();
2673+
MCRegister SrcReg = SrcMO.getReg();
2674+
2675+
unsigned DestRegIndex = RISCVRegisterInfo::getMCRegIndex(
2676+
DestReg, &MBBI->getParent()->getParent()->getRegInfo());
2677+
unsigned DestRegLMUL = RISCVRegisterInfo::getMCRegLMUL(DestReg);
2678+
unsigned SrcRegIndex = RISCVRegisterInfo::getMCRegIndex(
2679+
SrcReg, &MBBI->getParent()->getParent()->getRegInfo());
2680+
unsigned SrcRegLMUL = RISCVRegisterInfo::getMCRegLMUL(SrcReg);
2681+
2682+
if (OverlapConstraintsType == 2)
2683+
return RISCVRegisterInfo::isRVVConstraintsType2(DestRegIndex, DestRegLMUL,
2684+
SrcRegIndex, SrcRegLMUL);
2685+
if (OverlapConstraintsType == 3)
2686+
return RISCVRegisterInfo::isRVVConstraintsType3(DestRegIndex, DestRegLMUL,
2687+
SrcRegIndex, SrcRegLMUL);
2688+
2689+
return false;
2690+
}
2691+
2692+
// FIXME: Are we need support register like V26_V27?
2693+
static bool isVectorPhyRegClass(MCRegister Reg) {
2694+
return (RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg) ||
2695+
RISCVMCRegisterClasses[RISCV::VRM2RegClassID].contains(Reg) ||
2696+
RISCVMCRegisterClasses[RISCV::VRM4RegClassID].contains(Reg) ||
2697+
RISCVMCRegisterClasses[RISCV::VRM8RegClassID].contains(Reg));
2698+
}
2699+
2700+
static bool getConstraintsWithDestAndAllSrc(const MachineInstr *MBBI,
2701+
int OverlapConstraintsType) {
2702+
bool NeedConstraint = false;
2703+
int DestOperand = 0; // assume Early-Clobber Operand is 0.
2704+
2705+
if (!MBBI->getOperand(DestOperand).isReg() ||
2706+
!MBBI->getOperand(DestOperand).getReg().isPhysical())
2707+
return false;
2708+
2709+
for (auto &MO : MBBI->uses()) {
2710+
if (!MO.isReg())
2711+
continue;
2712+
if (MO.isTied())
2713+
continue;
2714+
if (MO.getReg().isPhysical() && !MO.isImplicit() &&
2715+
isVectorPhyRegClass(MO.getReg()))
2716+
NeedConstraint |= getConstrainsBetweenDstAndSrc(
2717+
MBBI, MBBI->getOperand(DestOperand), MO, OverlapConstraintsType);
2718+
}
2719+
2720+
return NeedConstraint;
2721+
}
2722+
2723+
static bool hasTargetInterference(const MachineInstr *MBBI) {
2724+
int OverlapConstraintsType =
2725+
RISCVInstrInfo::getOverlapConstraintsFromMI(MBBI->getOpcode());
2726+
if (OverlapConstraintsType == 2 || OverlapConstraintsType == 3)
2727+
return getConstraintsWithDestAndAllSrc(MBBI, OverlapConstraintsType);
2728+
2729+
return false;
2730+
}
2731+
2732+
static bool isEarlyClobberMI(const MachineInstr *MBBI) {
2733+
return llvm::any_of(MBBI->defs(), [](const MachineOperand &DefMO) {
2734+
return DefMO.isReg() && DefMO.isEarlyClobber();
2735+
});
2736+
}
2737+
26582738
bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
26592739
StringRef &ErrInfo) const {
26602740
MCInstrDesc const &Desc = MI.getDesc();
@@ -2922,6 +3002,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
29223002
return false;
29233003
}
29243004

3005+
if (hasTargetInterference(&MI) && isEarlyClobberMI(&MI))
3006+
return false;
3007+
29253008
return true;
29263009
}
29273010

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
286286
finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern,
287287
SmallVectorImpl<MachineInstr *> &InsInstrs) const override;
288288

289+
static int getOverlapConstraintsFromMI(uint16_t RVVPseudoOpcode);
290+
289291
void genAlternativeCodeSequence(
290292
MachineInstr &Root, unsigned Pattern,
291293
SmallVectorImpl<MachineInstr *> &InsInstrs,
@@ -398,6 +400,7 @@ namespace RISCVVPseudosTable {
398400
struct PseudoInfo {
399401
uint16_t Pseudo;
400402
uint16_t BaseInstr;
403+
uint16_t TargetOverlapConstraintType;
401404
};
402405

403406
#define GET_RISCVVPseudosTable_DECL

llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ defset list<VTypeInfoToWide> AllWidenableBFloatToFloatVectors = {
556556
class RISCVVPseudo {
557557
Pseudo Pseudo = !cast<Pseudo>(NAME); // Used as a key.
558558
Instruction BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst);
559+
bits<2> TargetOverlapConstraintType = 1;
559560
// SEW = 0 is used to denote that the Pseudo is not SEW specific (or unknown).
560561
bits<8> SEW = 0;
561562
bit IncludeInInversePseudoTable = 1;
@@ -565,7 +566,7 @@ class RISCVVPseudo {
565566
def RISCVVPseudosTable : GenericTable {
566567
let FilterClass = "RISCVVPseudo";
567568
let CppTypeName = "PseudoInfo";
568-
let Fields = [ "Pseudo", "BaseInstr" ];
569+
let Fields = [ "Pseudo", "BaseInstr", "TargetOverlapConstraintType"];
569570
let PrimaryKey = [ "Pseudo" ];
570571
let PrimaryKeyName = "getPseudoInfo";
571572
let PrimaryKeyEarlyOut = true;

0 commit comments

Comments
 (0)