Skip to content

Commit 5d87b5d

Browse files
author
Quentin Colombet
committed
[GISelKnownBits] Add support for PHIs
Teach the GISelKnowBits analysis how to deal with PHI operations. PHIs are essentially COPYs happening on edges, so we can just reuse the code for COPY. This is NFC COPY-wise has we leave Depth untouched when calling computeKnownBitsImpl for COPYs, like it was before this patch. Increasing Depth is however required for PHIs as they may loop back to themselves and we would end up in an infinite loop if we were not increasing Depth. Differential Revision: https://reviews.llvm.org/D73317
1 parent 81b700e commit 5d87b5d

File tree

3 files changed

+140
-14
lines changed

3 files changed

+140
-14
lines changed

llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,39 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known,
120120
TL.computeKnownBitsForTargetInstr(*this, R, Known, DemandedElts, MRI,
121121
Depth);
122122
break;
123-
case TargetOpcode::COPY: {
124-
MachineOperand Dst = MI.getOperand(0);
125-
MachineOperand Src = MI.getOperand(1);
126-
// Look through trivial copies but don't look through trivial copies of the
127-
// form `%1:(s32) = OP %0:gpr32` known-bits analysis is currently unable to
128-
// determine the bit width of a register class.
129-
//
130-
// We can't use NoSubRegister by name as it's defined by each target but
131-
// it's always defined to be 0 by tablegen.
132-
if (Dst.getSubReg() == 0 /*NoSubRegister*/ && Src.getReg().isVirtual() &&
133-
Src.getSubReg() == 0 /*NoSubRegister*/ &&
134-
MRI.getType(Src.getReg()).isValid()) {
135-
// Don't increment Depth for this one since we didn't do any work.
136-
computeKnownBitsImpl(Src.getReg(), Known, DemandedElts, Depth);
123+
case TargetOpcode::COPY:
124+
case TargetOpcode::G_PHI:
125+
case TargetOpcode::PHI: {
126+
Known.One = APInt::getAllOnesValue(BitWidth);
127+
Known.Zero = APInt::getAllOnesValue(BitWidth);
128+
// Destination registers should not have subregisters at this
129+
// point of the pipeline, otherwise the main live-range will be
130+
// defined more than once, which is against SSA.
131+
assert(MI.getOperand(0).getSubReg() == 0 && "Is this code in SSA?");
132+
// PHI's operand are a mix of registers and basic blocks interleaved.
133+
// We only care about the register ones.
134+
for (unsigned Idx = 1; Idx < MI.getNumOperands(); Idx += 2) {
135+
const MachineOperand &Src = MI.getOperand(Idx);
136+
Register SrcReg = Src.getReg();
137+
// Look through trivial copies and phis but don't look through trivial
138+
// copies or phis of the form `%1:(s32) = OP %0:gpr32`, known-bits
139+
// analysis is currently unable to determine the bit width of a
140+
// register class.
141+
//
142+
// We can't use NoSubRegister by name as it's defined by each target but
143+
// it's always defined to be 0 by tablegen.
144+
if (SrcReg.isVirtual() && Src.getSubReg() == 0 /*NoSubRegister*/ &&
145+
MRI.getType(SrcReg).isValid()) {
146+
// For COPYs we don't do anything, don't increase the depth.
147+
computeKnownBitsImpl(SrcReg, Known2, DemandedElts,
148+
Depth + (Opcode != TargetOpcode::COPY));
149+
Known.One &= Known2.One;
150+
Known.Zero &= Known2.Zero;
151+
} else {
152+
// We know nothing.
153+
Known = KnownBits(BitWidth);
154+
break;
155+
}
137156
}
138157
break;
139158
}

llvm/unittests/CodeGen/GlobalISel/GISelMITest.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,16 @@ createDummyModule(LLVMContext &Context, const LLVMTargetMachine &TM,
9999
---
100100
...
101101
name: func
102+
tracksRegLiveness: true
102103
registers:
103104
- { id: 0, class: _ }
104105
- { id: 1, class: _ }
105106
- { id: 2, class: _ }
106107
- { id: 3, class: _ }
107108
body: |
108109
bb.1:
110+
liveins: $x0, $x1, $x2, $x4
111+
109112
%0(s64) = COPY $x0
110113
%1(s64) = COPY $x1
111114
%2(s64) = COPY $x2

llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,110 @@ TEST_F(GISelMITest, TestKnownBitsCstWithClass) {
5656
EXPECT_EQ(Res.Zero.getZExtValue(), Res2.Zero.getZExtValue());
5757
}
5858

59+
// Check that we are able to track bits through PHIs
60+
// and get the intersections of everything we know on each operand.
61+
TEST_F(GISelMITest, TestKnownBitsCstPHI) {
62+
StringRef MIRString = " bb.10:\n"
63+
" %10:_(s8) = G_CONSTANT i8 3\n"
64+
" %11:_(s1) = G_IMPLICIT_DEF\n"
65+
" G_BRCOND %11(s1), %bb.11\n"
66+
" G_BR %bb.12\n"
67+
"\n"
68+
" bb.11:\n"
69+
" %12:_(s8) = G_CONSTANT i8 2\n"
70+
" G_BR %bb.12\n"
71+
"\n"
72+
" bb.12:\n"
73+
" %13:_(s8) = PHI %10(s8), %bb.10, %12(s8), %bb.11\n"
74+
" %14:_(s8) = COPY %13\n";
75+
setUp(MIRString);
76+
if (!TM)
77+
return;
78+
Register CopyReg = Copies[Copies.size() - 1];
79+
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
80+
Register SrcReg = FinalCopy->getOperand(1).getReg();
81+
Register DstReg = FinalCopy->getOperand(0).getReg();
82+
GISelKnownBits Info(*MF);
83+
KnownBits Res = Info.getKnownBits(SrcReg);
84+
EXPECT_EQ((uint64_t)2, Res.One.getZExtValue());
85+
EXPECT_EQ((uint64_t)0xfc, Res.Zero.getZExtValue());
86+
87+
KnownBits Res2 = Info.getKnownBits(DstReg);
88+
EXPECT_EQ(Res.One.getZExtValue(), Res2.One.getZExtValue());
89+
EXPECT_EQ(Res.Zero.getZExtValue(), Res2.Zero.getZExtValue());
90+
}
91+
92+
// Check that we report we know nothing when we hit a
93+
// non-generic register.
94+
// Note: this could be improved though!
95+
TEST_F(GISelMITest, TestKnownBitsCstPHIToNonGenericReg) {
96+
StringRef MIRString = " bb.10:\n"
97+
" %10:gpr32 = MOVi32imm 3\n"
98+
" %11:_(s1) = G_IMPLICIT_DEF\n"
99+
" G_BRCOND %11(s1), %bb.11\n"
100+
" G_BR %bb.12\n"
101+
"\n"
102+
" bb.11:\n"
103+
" %12:_(s8) = G_CONSTANT i8 2\n"
104+
" G_BR %bb.12\n"
105+
"\n"
106+
" bb.12:\n"
107+
" %13:_(s8) = PHI %10, %bb.10, %12(s8), %bb.11\n"
108+
" %14:_(s8) = COPY %13\n";
109+
setUp(MIRString);
110+
if (!TM)
111+
return;
112+
Register CopyReg = Copies[Copies.size() - 1];
113+
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
114+
Register SrcReg = FinalCopy->getOperand(1).getReg();
115+
Register DstReg = FinalCopy->getOperand(0).getReg();
116+
GISelKnownBits Info(*MF);
117+
KnownBits Res = Info.getKnownBits(SrcReg);
118+
EXPECT_EQ((uint64_t)0, Res.One.getZExtValue());
119+
EXPECT_EQ((uint64_t)0, Res.Zero.getZExtValue());
120+
121+
KnownBits Res2 = Info.getKnownBits(DstReg);
122+
EXPECT_EQ(Res.One.getZExtValue(), Res2.One.getZExtValue());
123+
EXPECT_EQ(Res.Zero.getZExtValue(), Res2.Zero.getZExtValue());
124+
}
125+
126+
// Check that we manage to process PHIs that loop on themselves.
127+
// For now, the analysis just stops and assumes it knows nothing,
128+
// eventually we could teach it how to properly track phis that
129+
// loop back.
130+
TEST_F(GISelMITest, TestKnownBitsCstPHIWithLoop) {
131+
StringRef MIRString =
132+
" bb.10:\n"
133+
" %10:_(s8) = G_CONSTANT i8 3\n"
134+
" %11:_(s1) = G_IMPLICIT_DEF\n"
135+
" G_BRCOND %11(s1), %bb.11\n"
136+
" G_BR %bb.12\n"
137+
"\n"
138+
" bb.11:\n"
139+
" %12:_(s8) = G_CONSTANT i8 2\n"
140+
" G_BR %bb.12\n"
141+
"\n"
142+
" bb.12:\n"
143+
" %13:_(s8) = PHI %10(s8), %bb.10, %12(s8), %bb.11, %14(s8), %bb.12\n"
144+
" %14:_(s8) = COPY %13\n"
145+
" G_BR %bb.12\n";
146+
setUp(MIRString);
147+
if (!TM)
148+
return;
149+
Register CopyReg = Copies[Copies.size() - 1];
150+
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
151+
Register SrcReg = FinalCopy->getOperand(1).getReg();
152+
Register DstReg = FinalCopy->getOperand(0).getReg();
153+
GISelKnownBits Info(*MF);
154+
KnownBits Res = Info.getKnownBits(SrcReg);
155+
EXPECT_EQ((uint64_t)0, Res.One.getZExtValue());
156+
EXPECT_EQ((uint64_t)0, Res.Zero.getZExtValue());
157+
158+
KnownBits Res2 = Info.getKnownBits(DstReg);
159+
EXPECT_EQ(Res.One.getZExtValue(), Res2.One.getZExtValue());
160+
EXPECT_EQ(Res.Zero.getZExtValue(), Res2.Zero.getZExtValue());
161+
}
162+
59163
TEST_F(GISelMITest, TestKnownBitsPtrToIntViceVersa) {
60164
StringRef MIRString = " %3:_(s16) = G_CONSTANT i16 256\n"
61165
" %4:_(p0) = G_INTTOPTR %3\n"

0 commit comments

Comments
 (0)