Skip to content

Commit cea97fc

Browse files
committed
GlobalISel: Relax verification of physical register copy types
This was picking a concrete size for a physical register, and enforcing exact match on the virtual register's type size. Some targets add multiple types to a register class, and some are smaller than the full bit width. For example x86 adds f32 to 128-bit xmm registers, and AMDGPU adds i16/f16 to 32-bit registers. It might be better to represent these cases as a copy of the full register and an extraction of the subpart, but a lot of code assumes you can directly copy. This will help fix the current usage of the DAG calling convention infrastructure which is incompatible with how GlobalISel is now using it. The API is somewhat cumbersome here, but I just mirrored the existing functions, except now with LLTs (and allow returning null on failure, unlike the MVT version). I think the concept of selecting register classes based on type is flawed to begin with, but I'm trying to keep this compatible with the existing handling.
1 parent 6998f8a commit cea97fc

File tree

4 files changed

+132
-15
lines changed

4 files changed

+132
-15
lines changed

llvm/include/llvm/CodeGen/TargetRegisterInfo.h

+20
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ class TargetRegisterInfo : public MCRegisterInfo {
301301
return false;
302302
}
303303

304+
/// Return true if the given TargetRegisterClass is compatible with LLT T.
305+
bool isTypeLegalForClass(const TargetRegisterClass &RC, LLT T) const {
306+
for (auto I = legalclasstypes_begin(RC); *I != MVT::Other; ++I) {
307+
MVT VT(*I);
308+
if (VT == MVT::Untyped)
309+
return true;
310+
311+
if (LLT(VT) == T)
312+
return true;
313+
}
314+
return false;
315+
}
316+
304317
/// Loop over all of the value types that can be represented by values
305318
/// in the given register class.
306319
vt_iterator legalclasstypes_begin(const TargetRegisterClass &RC) const {
@@ -320,6 +333,13 @@ class TargetRegisterInfo : public MCRegisterInfo {
320333
const TargetRegisterClass *getMinimalPhysRegClass(MCRegister Reg,
321334
MVT VT = MVT::Other) const;
322335

336+
/// Returns the Register Class of a physical register of the given type,
337+
/// picking the most sub register class of the right type that contains this
338+
/// physreg. If there is no register class compatible with the given type,
339+
/// returns nullptr.
340+
const TargetRegisterClass *getMinimalPhysRegClassLLT(MCRegister Reg,
341+
LLT Ty = LLT()) const;
342+
323343
/// Return the maximal subclass of the given register class that is
324344
/// allocatable or NULL.
325345
const TargetRegisterClass *

llvm/lib/CodeGen/MachineVerifier.cpp

+41-15
Original file line numberDiff line numberDiff line change
@@ -1678,28 +1678,54 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
16781678
case TargetOpcode::COPY: {
16791679
const MachineOperand &DstOp = MI->getOperand(0);
16801680
const MachineOperand &SrcOp = MI->getOperand(1);
1681-
LLT DstTy = MRI->getType(DstOp.getReg());
1682-
LLT SrcTy = MRI->getType(SrcOp.getReg());
1681+
const Register SrcReg = SrcOp.getReg();
1682+
const Register DstReg = DstOp.getReg();
1683+
1684+
LLT DstTy = MRI->getType(DstReg);
1685+
LLT SrcTy = MRI->getType(SrcReg);
16831686
if (SrcTy.isValid() && DstTy.isValid()) {
16841687
// If both types are valid, check that the types are the same.
16851688
if (SrcTy != DstTy) {
16861689
report("Copy Instruction is illegal with mismatching types", MI);
16871690
errs() << "Def = " << DstTy << ", Src = " << SrcTy << "\n";
16881691
}
1692+
1693+
break;
16891694
}
1690-
if (SrcTy.isValid() || DstTy.isValid()) {
1691-
// If one of them have valid types, let's just check they have the same
1692-
// size.
1693-
unsigned SrcSize = TRI->getRegSizeInBits(SrcOp.getReg(), *MRI);
1694-
unsigned DstSize = TRI->getRegSizeInBits(DstOp.getReg(), *MRI);
1695-
assert(SrcSize && "Expecting size here");
1696-
assert(DstSize && "Expecting size here");
1697-
if (SrcSize != DstSize)
1698-
if (!DstOp.getSubReg() && !SrcOp.getSubReg()) {
1699-
report("Copy Instruction is illegal with mismatching sizes", MI);
1700-
errs() << "Def Size = " << DstSize << ", Src Size = " << SrcSize
1701-
<< "\n";
1702-
}
1695+
1696+
if (!SrcTy.isValid() && !DstTy.isValid())
1697+
break;
1698+
1699+
// If we have only one valid type, this is likely a copy between a virtual
1700+
// and physical register.
1701+
unsigned SrcSize = 0;
1702+
unsigned DstSize = 0;
1703+
if (SrcReg.isPhysical() && DstTy.isValid()) {
1704+
const TargetRegisterClass *SrcRC =
1705+
TRI->getMinimalPhysRegClassLLT(SrcReg, DstTy);
1706+
if (SrcRC)
1707+
SrcSize = TRI->getRegSizeInBits(*SrcRC);
1708+
}
1709+
1710+
if (SrcSize == 0)
1711+
SrcSize = TRI->getRegSizeInBits(SrcReg, *MRI);
1712+
1713+
if (DstReg.isPhysical() && SrcTy.isValid()) {
1714+
const TargetRegisterClass *DstRC =
1715+
TRI->getMinimalPhysRegClassLLT(DstReg, SrcTy);
1716+
if (DstRC)
1717+
DstSize = TRI->getRegSizeInBits(*DstRC);
1718+
}
1719+
1720+
if (DstSize == 0)
1721+
DstSize = TRI->getRegSizeInBits(DstReg, *MRI);
1722+
1723+
if (SrcSize != 0 && DstSize != 0 && SrcSize != DstSize) {
1724+
if (!DstOp.getSubReg() && !SrcOp.getSubReg()) {
1725+
report("Copy Instruction is illegal with mismatching sizes", MI);
1726+
errs() << "Def Size = " << DstSize << ", Src Size = " << SrcSize
1727+
<< "\n";
1728+
}
17031729
}
17041730
break;
17051731
}

llvm/lib/CodeGen/TargetRegisterInfo.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,23 @@ TargetRegisterInfo::getMinimalPhysRegClass(MCRegister reg, MVT VT) const {
225225
return BestRC;
226226
}
227227

228+
const TargetRegisterClass *
229+
TargetRegisterInfo::getMinimalPhysRegClassLLT(MCRegister reg, LLT Ty) const {
230+
assert(Register::isPhysicalRegister(reg) &&
231+
"reg must be a physical register");
232+
233+
// Pick the most sub register class of the right type that contains
234+
// this physreg.
235+
const TargetRegisterClass *BestRC = nullptr;
236+
for (const TargetRegisterClass *RC : regclasses()) {
237+
if ((!Ty.isValid() || isTypeLegalForClass(*RC, Ty)) && RC->contains(reg) &&
238+
(!BestRC || BestRC->hasSubClass(RC)))
239+
BestRC = RC;
240+
}
241+
242+
return BestRC;
243+
}
244+
228245
/// getAllocatableSetForRC - Toggle the bits that represent allocatable
229246
/// registers for the specific register class.
230247
static void getAllocatableSetForRC(const MachineFunction &MF,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#RUN: not --crash llc -march=x86-64 -run-pass=none -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck %s
2+
# REQUIRES: x86-registered-target
3+
4+
# These copies have mismatched type sizes that are allowed because the
5+
# register class is defined to directly include the narrower type.
6+
---
7+
name: test_valid_copies
8+
tracksRegLiveness: true
9+
body: |
10+
bb.0:
11+
liveins: $xmm0, $xmm1, $xmm2, $xmm3, $xmm4
12+
%0:_(s32) = COPY $xmm0
13+
%1:_(s64) = COPY $xmm1
14+
%2:_(s128) = COPY $xmm2
15+
%3:_(<4 x s32>) = COPY $xmm3
16+
%4:_(<2 x s64>) = COPY $xmm4
17+
$xmm0 = COPY %0
18+
$xmm1 = COPY %1
19+
$xmm2 = COPY %2
20+
$xmm3 = COPY %3
21+
$xmm4 = COPY %4
22+
...
23+
24+
---
25+
name: test_invalid_copies
26+
tracksRegLiveness: true
27+
body: |
28+
bb.0:
29+
liveins: $xmm0, $xmm1, $xmm2, $xmm3
30+
31+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
32+
%0:_(s16) = COPY $xmm0
33+
34+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
35+
%1:_(<4 x s16>) = COPY $xmm1
36+
37+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
38+
%2:_(s256) = COPY $xmm2
39+
40+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
41+
%3:_(<8 x s32>) = COPY $xmm3
42+
43+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
44+
$xmm0 = COPY %0
45+
46+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
47+
$xmm1 = COPY %1
48+
49+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
50+
$xmm2 = COPY %2
51+
52+
; CHECK: *** Bad machine code: Copy Instruction is illegal with mismatching sizes ***
53+
$xmm3 = COPY %3
54+
...

0 commit comments

Comments
 (0)