Skip to content

Commit d199bf9

Browse files
committed
[RISCV][InsertVSETVLI] Handle partially transparent instructions in PRE
The PRE implementation was being overly strict when checking to see if a vsetvli was removed in the current block. For instructions which don't use all the fields of VTYPE or VL, we can propagate a changed state past the first instruction with an SEW operand and remove a vsetvli later in the block. We do need to be careful now to ensure that the state convergences before the end of the block or we'd invalidate the cached data flow results. Taking a step back, we're modeling the effect of the emitVSETVLIs pass which runs just after PRE. This is unfortunate, and makes me think we should probably reevaluate doing the PRE as a post-pass instead of as surgery in the data flow phases. Doing that requires us to get more aggressive about mutating user written vsetvlis which we've tried not to do up to now, but well, maybe it's time? Anyways, that's a thought for the future, not something I'm proposing doing now. Differential Revision: https://reviews.llvm.org/D142409
1 parent 73dba2f commit d199bf9

File tree

2 files changed

+31
-19
lines changed

2 files changed

+31
-19
lines changed

llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,27 +1188,40 @@ void RISCVInsertVSETVLI::doPRE(MachineBasicBlock &MBB) {
11881188
if (!hasFixedResult(AvailableInfo, ST))
11891189
return;
11901190

1191-
// Does it actually let us remove an implicit transition in MBB?
1192-
bool Found = false;
1193-
for (auto &MI : MBB) {
1194-
if (isVectorConfigInstr(MI))
1195-
return;
1196-
1197-
const uint64_t TSFlags = MI.getDesc().TSFlags;
1198-
if (RISCVII::hasSEWOp(TSFlags)) {
1199-
if (AvailableInfo != computeInfoForInstr(MI, TSFlags, MRI))
1200-
return;
1201-
Found = true;
1191+
// Model the effect of changing the input state of the block MBB to
1192+
// AvailableInfo. We're looking for two issues here; one legality,
1193+
// one profitability.
1194+
// 1) If the block doesn't use some of the fields from VL or VTYPE, we
1195+
// may hit the end of the block with a different end state. We can
1196+
// not make this change without reflowing later blocks as well.
1197+
// 2) If we don't actually remove a transition, inserting a vsetvli
1198+
// into the predecessor block would be correct, but unprofitable.
1199+
VSETVLIInfo OldInfo = BlockInfo[MBB.getNumber()].Pred;
1200+
VSETVLIInfo CurInfo = AvailableInfo;
1201+
int TransitionsRemoved = 0;
1202+
for (const MachineInstr &MI : MBB) {
1203+
const VSETVLIInfo LastInfo = CurInfo;
1204+
const VSETVLIInfo LastOldInfo = OldInfo;
1205+
transferBefore(CurInfo, MI);
1206+
transferBefore(OldInfo, MI);
1207+
if (CurInfo == LastInfo)
1208+
TransitionsRemoved++;
1209+
if (LastOldInfo == OldInfo)
1210+
TransitionsRemoved--;
1211+
transferAfter(CurInfo, MI);
1212+
transferAfter(OldInfo, MI);
1213+
if (CurInfo == OldInfo)
1214+
// Convergence. All transitions after this must match by construction.
12021215
break;
1203-
}
12041216
}
1205-
if (!Found)
1217+
if (CurInfo != OldInfo || TransitionsRemoved <= 0)
1218+
// Issues 1 and 2 above
12061219
return;
12071220

12081221
// Finally, update both data flow state and insert the actual vsetvli.
12091222
// Doing both keeps the code in sync with the dataflow results, which
12101223
// is critical for correctness of phase 3.
1211-
auto OldInfo = BlockInfo[UnavailablePred->getNumber()].Exit;
1224+
auto OldExit = BlockInfo[UnavailablePred->getNumber()].Exit;
12121225
LLVM_DEBUG(dbgs() << "PRE VSETVLI from " << MBB.getName() << " to "
12131226
<< UnavailablePred->getName() << " with state "
12141227
<< AvailableInfo << "\n");
@@ -1220,7 +1233,7 @@ void RISCVInsertVSETVLI::doPRE(MachineBasicBlock &MBB) {
12201233
auto InsertPt = UnavailablePred->getFirstInstrTerminator();
12211234
insertVSETVLI(*UnavailablePred, InsertPt,
12221235
UnavailablePred->findDebugLoc(InsertPt),
1223-
AvailableInfo, OldInfo);
1236+
AvailableInfo, OldExit);
12241237
}
12251238

12261239
static void doUnion(DemandedFields &A, DemandedFields B) {

llvm/test/CodeGen/RISCV/rvv/vsetvli-insert-crossbb.ll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -954,16 +954,15 @@ if.end:
954954
ret <vscale x 2 x i32> %e
955955
}
956956

957-
; This case demonstrates a PRE oppurtunity where the first instruction
958-
; in the block doesn't require a state transition. Essentially, we need
959-
; to FRE the transition to the start of the block, and *then* PRE it.
957+
; This case demonstrates a PRE case where the first instruction in the block
958+
; doesn't require a state transition.
960959
define void @pre_over_vle(ptr %A) {
961960
; CHECK-LABEL: pre_over_vle:
962961
; CHECK: # %bb.0: # %entry
963962
; CHECK-NEXT: li a1, 100
963+
; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma
964964
; CHECK-NEXT: .LBB22_1: # %vector.body
965965
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
966-
; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma
967966
; CHECK-NEXT: vle8.v v8, (a0)
968967
; CHECK-NEXT: vsext.vf4 v9, v8
969968
; CHECK-NEXT: vse32.v v9, (a0)

0 commit comments

Comments
 (0)