Skip to content

Commit d04d645

Browse files
[RISCV] Add SchedRead for merge operand
Prior to this patch, SchedReads were not modeled for instructions that did not have a MASK suffix. This patch adds a SchedRead for all instructions that have a merge operand. @reames is doing work to fold TA and TU instructions into a single instruction. This means that a single instruction may or may not actually read the merge operand (TU must read merge operand). It is possible that a TA instruction needs to read the merge operand, for instance if TA is implemented as TU. Therefore, it makes sense to represent the read of the merge operand for both TA and TU instructions. In the case that a subtarget wants to model TA read different from TU read, the subtarget should use a SchedVariant, which has access to the MachineInstr. Without this patch, the current SchedReads are off by one for instructions that have a merge operand. I am concerned is that `forceMergeOpRead` is passed to `SchedXXX`, but the `SchedXXX` is not defined next to the ins and outs. This leads us to walk the class hierarchy to determine whether `forceMergeOpRead` needs to be be true. I worry that this will make this change harder to review, and it may not be clear that `forceMergeOpRead` needs to be updated if any future changes add or remove merge operands. I thought about moving the SchedXXX definitions to where the ins and outs occur (as a seperate patch), but the drawback of this is that we have to pass around lots of new arguments through class heirarchies. One improvement on this is to use a single custom data structure to pass through the heirarchies the eventually gets used by the SchedXXX. If any reviewers care to share their own opinion on this concern, or suggest a different solution to this concern, it would be greatly appreciated. In any case, this concern is NFC. Differential Revision: https://reviews.llvm.org/D157650
1 parent 1800038 commit d04d645

File tree

2 files changed

+293
-174
lines changed

2 files changed

+293
-174
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfoV.td

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -106,70 +106,77 @@ def simm5_plus1_nonzero : ImmLeaf<XLenVT,
106106
// in order.
107107
// `reads` SchedReads that are listed for each explicit use operand.
108108
// `forceMasked` Forced to be masked (e.g. Add-with-Carry Instructions).
109+
// `forceMergeOpRead` Force to have read for merge operand.
109110
class SchedCommon<list<SchedWrite> writes, list<SchedRead> reads,
110-
string mx = "WorstCase", int sew = 0, bit forceMasked = 0>
111-
: Sched<[]> {
111+
string mx = "WorstCase", int sew = 0, bit forceMasked = 0,
112+
bit forceMergeOpRead = 0> : Sched<[]> {
112113
defvar isMasked = !ne(!find(NAME, "_MASK"), -1);
113114
defvar isMaskedOrForceMasked = !or(forceMasked, isMasked);
114-
defvar mergeOp = !if(!or(!eq(mx, "WorstCase"), !eq(sew, 0)),
115+
defvar mergeRead = !if(!or(!eq(mx, "WorstCase"), !eq(sew, 0)),
115116
!cast<SchedRead>("ReadVMergeOp_" # mx),
116117
!cast<SchedRead>("ReadVMergeOp_" # mx # "_E" #sew));
117-
defvar allReads = !if(isMaskedOrForceMasked,
118-
!listconcat([mergeOp], reads, [ReadVMask]),
119-
reads);
118+
defvar needsMergeRead = !or(isMaskedOrForceMasked, forceMergeOpRead);
119+
defvar readsWithMask =
120+
!if(isMaskedOrForceMasked, !listconcat(reads, [ReadVMask]), reads);
121+
defvar allReads =
122+
!if(needsMergeRead, !listconcat([mergeRead], readsWithMask), reads);
120123
let SchedRW = !listconcat(writes, allReads);
121124
}
122125

123126
// Common class of scheduling definitions for n-ary instructions.
124127
// The scheudling resources are relevant to LMUL and may be relevant to SEW.
125-
class SchedNary<string write, list<string> reads,
126-
string mx, int sew = 0, bit forceMasked = 0>:
127-
SchedCommon<[!cast<SchedWrite>(
128-
!if(sew, write # "_" # mx # "_E" # sew,
128+
class SchedNary<string write, list<string> reads, string mx, int sew = 0,
129+
bit forceMasked = 0, bit forceMergeOpRead = 0>
130+
: SchedCommon<[!cast<SchedWrite>(
131+
!if(sew,
132+
write # "_" # mx # "_E" # sew,
129133
write # "_" # mx))],
130-
!foreach(read, reads,
131-
!cast<SchedRead>(
132-
!if(sew, read # "_" # mx # "_E" # sew,
133-
read # "_" # mx))),
134-
mx, sew, forceMasked>;
134+
!foreach(read, reads,
135+
!cast<SchedRead>(!if(sew, read #"_" #mx #"_E" #sew,
136+
read #"_" #mx))),
137+
mx, sew, forceMasked, forceMergeOpRead>;
135138

136139
// Classes with postfix "MC" are only used in MC layer.
137140
// For these classes, we assume that they are with the worst case costs and
138141
// `ReadVMask` is always needed (with some exceptions).
139142

140143
// For instructions with no operand.
141-
class SchedNullary<string write, string mx, int sew = 0, bit forceMasked = 0>:
142-
SchedNary<write, [], mx, sew, forceMasked>;
144+
class SchedNullary<string write, string mx, int sew = 0, bit forceMasked = 0,
145+
bit forceMergeOpRead = 0>:
146+
SchedNary<write, [], mx, sew, forceMasked, forceMergeOpRead>;
143147
class SchedNullaryMC<string write, bit forceMasked = 1>:
144148
SchedNullary<write, "WorstCase", forceMasked=forceMasked>;
145149

146150
// For instructions with one operand.
147151
class SchedUnary<string write, string read0, string mx, int sew = 0,
148-
bit forceMasked = 0>:
149-
SchedNary<write, [read0], mx, sew, forceMasked>;
152+
bit forceMasked = 0, bit forceMergeOpRead = 0>:
153+
SchedNary<write, [read0], mx, sew, forceMasked, forceMergeOpRead>;
150154
class SchedUnaryMC<string write, string read0, bit forceMasked = 1>:
151155
SchedUnary<write, read0, "WorstCase", forceMasked=forceMasked>;
152156

153157
// For instructions with two operands.
154-
class SchedBinary<string write, string read0, string read1,
155-
string mx, int sew = 0, bit forceMasked = 0>:
156-
SchedNary<write, [read0, read1], mx, sew, forceMasked>;
158+
class SchedBinary<string write, string read0, string read1, string mx,
159+
int sew = 0, bit forceMasked = 0, bit forceMergeOpRead = 0>
160+
: SchedNary<write, [read0, read1], mx, sew, forceMasked, forceMergeOpRead>;
157161
class SchedBinaryMC<string write, string read0, string read1,
158162
bit forceMasked = 1>:
159163
SchedBinary<write, read0, read1, "WorstCase", forceMasked=forceMasked>;
160164

161165
// For instructions with three operands.
162166
class SchedTernary<string write, string read0, string read1, string read2,
163-
string mx, int sew = 0, bit forceMasked = 0>:
164-
SchedNary<write, [read0, read1, read2], mx, sew, forceMasked>;
167+
string mx, int sew = 0, bit forceMasked = 0,
168+
bit forceMergeOpRead = 0>
169+
: SchedNary<write, [read0, read1, read2], mx, sew, forceMasked,
170+
forceMergeOpRead>;
165171
class SchedTernaryMC<string write, string read0, string read1, string read2,
166172
int sew = 0, bit forceMasked = 1>:
167173
SchedNary<write, [read0, read1, read2], "WorstCase", sew, forceMasked>;
168174

169175
// For reduction instructions.
170-
class SchedReduction<string write, string read, string mx, int sew>:
171-
SchedCommon<[!cast<SchedWrite>(write # "_" # mx # "_E" # sew)],
172-
!listsplat(!cast<SchedRead>(read), 3), mx, sew>;
176+
class SchedReduction<string write, string read, string mx, int sew,
177+
bit forceMergeOpRead = 0>
178+
: SchedCommon<[!cast<SchedWrite>(write #"_" #mx #"_E" #sew)],
179+
!listsplat(!cast<SchedRead>(read), 3), mx, sew, forceMergeOpRead>;
173180
class SchedReductionMC<string write, string readV, string readV0>:
174181
SchedCommon<[!cast<SchedWrite>(write # "_WorstCase")],
175182
[!cast<SchedRead>(readV), !cast<SchedRead>(readV0)],

0 commit comments

Comments
 (0)