Skip to content

Commit a029ece

Browse files
authored
[RISCV] Fix coalescing vsetvlis when AVL and vl registers are the same (#141941)
With EVL tail folding we can end up with vsetvlis where the output vl and the input AVL are the same register. When we try to coalesce it we crashed because we tried to move the def's live interval before the kill's live interval, e.g. in this example: (vn0 def) dead $x0 = PseudoVSETIVLI 1, 192, implicit-def $vl, implicit-def $vtype renamable $v9 = COPY killed renamable $v8 (vn1 def) %23:gprnox0 = PseudoVSETVLI killed (vn0) %23:gprnox0, 197, implicit-def $vl, implicit-def $vtype We would try to move the vn1 def VNInfo up to the previous VSETVLI, in the middle of vn0's segment. However separately, we were also assuming that the vl would only have one definition and thus were just taking the VNInfo from beginIndex(), so we ended up with a backwards segment and got the error "Cannot create empty or backwards segment". This fixes these two issues, the first one by moving the AVL operand + live interval up first, and the second by taking the VNInfo from NextMI's slot index. Fixes #141907
1 parent 835497a commit a029ece

File tree

3 files changed

+91
-10
lines changed

3 files changed

+91
-10
lines changed

llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,13 +1698,24 @@ void RISCVInsertVSETVLI::coalesceVSETVLIs(MachineBasicBlock &MBB) const {
16981698
MI.getOperand(0).setReg(DefReg);
16991699
MI.getOperand(0).setIsDead(false);
17001700

1701+
// Move the AVL from NextMI to MI
1702+
dropAVLUse(MI.getOperand(1));
1703+
if (NextMI->getOperand(1).isImm())
1704+
MI.getOperand(1).ChangeToImmediate(NextMI->getOperand(1).getImm());
1705+
else
1706+
MI.getOperand(1).ChangeToRegister(NextMI->getOperand(1).getReg(),
1707+
false);
1708+
dropAVLUse(NextMI->getOperand(1));
1709+
17011710
// The def of DefReg moved to MI, so extend the LiveInterval up to
17021711
// it.
17031712
if (DefReg.isVirtual() && LIS) {
17041713
LiveInterval &DefLI = LIS->getInterval(DefReg);
17051714
SlotIndex MISlot = LIS->getInstructionIndex(MI).getRegSlot();
1706-
VNInfo *DefVNI = DefLI.getVNInfoAt(DefLI.beginIndex());
1707-
LiveInterval::Segment S(MISlot, DefLI.beginIndex(), DefVNI);
1715+
SlotIndex NextMISlot =
1716+
LIS->getInstructionIndex(*NextMI).getRegSlot();
1717+
VNInfo *DefVNI = DefLI.getVNInfoAt(NextMISlot);
1718+
LiveInterval::Segment S(MISlot, NextMISlot, DefVNI);
17081719
DefLI.addSegment(S);
17091720
DefVNI->def = MISlot;
17101721
// Mark DefLI as spillable if it was previously unspillable
@@ -1715,13 +1726,6 @@ void RISCVInsertVSETVLI::coalesceVSETVLIs(MachineBasicBlock &MBB) const {
17151726
LIS->shrinkToUses(&DefLI);
17161727
}
17171728

1718-
dropAVLUse(MI.getOperand(1));
1719-
if (NextMI->getOperand(1).isImm())
1720-
MI.getOperand(1).ChangeToImmediate(NextMI->getOperand(1).getImm());
1721-
else
1722-
MI.getOperand(1).ChangeToRegister(NextMI->getOperand(1).getReg(),
1723-
false);
1724-
17251729
MI.setDesc(NextMI->getDesc());
17261730
}
17271731
MI.getOperand(2).setImm(NextMI->getOperand(2).getImm());
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=riscv64 -mcpu=sifive-p670 | FileCheck %s
3+
4+
define void @pr141907(ptr %0) nounwind {
5+
; CHECK-LABEL: pr141907:
6+
; CHECK: # %bb.0: # %entry
7+
; CHECK-NEXT: addi sp, sp, -16
8+
; CHECK-NEXT: csrr a1, vlenb
9+
; CHECK-NEXT: slli a1, a1, 2
10+
; CHECK-NEXT: sub sp, sp, a1
11+
; CHECK-NEXT: vsetivli zero, 0, e32, m1, ta, ma
12+
; CHECK-NEXT: vmv.v.i v9, 0
13+
; CHECK-NEXT: vmclr.m v0
14+
; CHECK-NEXT: li a1, 0
15+
; CHECK-NEXT: vsetvli a3, zero, e16, mf2, ta, ma
16+
; CHECK-NEXT: vmv.v.i v12, 0
17+
; CHECK-NEXT: addi a2, sp, 16
18+
; CHECK-NEXT: .LBB0_1: # %vector.body
19+
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
20+
; CHECK-NEXT: vs4r.v v8, (a2)
21+
; CHECK-NEXT: vsetvli a1, a1, e8, mf8, ta, ma
22+
; CHECK-NEXT: vsetivli zero, 0, e16, mf2, ta, ma
23+
; CHECK-NEXT: vnsrl.wi v11, v9, 0, v0.t
24+
; CHECK-NEXT: vsetvli a3, zero, e32, m1, ta, ma
25+
; CHECK-NEXT: vlseg3e32.v v8, (a2)
26+
; CHECK-NEXT: vsetivli zero, 0, e16, mf2, ta, ma
27+
; CHECK-NEXT: vsseg2e16.v v11, (zero)
28+
; CHECK-NEXT: bnez a1, .LBB0_1
29+
; CHECK-NEXT: .LBB0_2: # %while.body5
30+
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
31+
; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma
32+
; CHECK-NEXT: vse16.v v9, (a0)
33+
; CHECK-NEXT: j .LBB0_2
34+
entry:
35+
br label %vector.body
36+
37+
vector.body: ; preds = %vector.body, %entry
38+
%evl.based.iv = phi i64 [ 0, %entry ], [ %2, %vector.body ]
39+
%vector.recur = phi <vscale x 2 x i32> [ zeroinitializer, %entry ], [ %3, %vector.body ]
40+
%1 = call i32 @llvm.experimental.get.vector.length.i64(i64 %evl.based.iv, i32 1, i1 true)
41+
%2 = zext i32 %1 to i64
42+
%wide.masked.load = call <vscale x 6 x i32> @llvm.vp.load.nxv6i32.p0(ptr null, <vscale x 6 x i1> zeroinitializer, i32 0)
43+
%deinterleaved.results = call { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } @llvm.vector.deinterleave3.nxv6i32(<vscale x 6 x i32> %wide.masked.load)
44+
%3 = extractvalue { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } %deinterleaved.results, 1
45+
%vp.cast65 = call <vscale x 2 x i16> @llvm.vp.trunc.nxv2i16.nxv2i32(<vscale x 2 x i32> %vector.recur, <vscale x 2 x i1> zeroinitializer, i32 0)
46+
%interleaved.vec = call <vscale x 4 x i16> @llvm.vector.interleave2.nxv4i16(<vscale x 2 x i16> %vp.cast65, <vscale x 2 x i16> zeroinitializer)
47+
call void @llvm.vp.store.nxv4i16.p0(<vscale x 4 x i16> %interleaved.vec, ptr null, <vscale x 4 x i1> splat (i1 true), i32 0)
48+
%4 = icmp eq i32 %1, 0
49+
br i1 %4, label %while.body5, label %vector.body
50+
51+
while.body5: ; preds = %while.body5, %vector.body
52+
%5 = bitcast <vscale x 2 x i32> %3 to <vscale x 4 x i16>
53+
%cond52 = extractelement <vscale x 4 x i16> %5, i64 0
54+
store i16 %cond52, ptr %0, align 2
55+
br label %while.body5
56+
}

llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@
9696
ret void
9797
}
9898

99+
define void @coalesce_vl_avl_same_reg() {
100+
ret void
101+
}
102+
99103
declare <vscale x 1 x i64> @llvm.riscv.vadd.nxv1i64.nxv1i64.i64(<vscale x 1 x i64>, <vscale x 1 x i64>, <vscale x 1 x i64>, i64) #1
100104

101105
declare <vscale x 1 x i64> @llvm.riscv.vle.nxv1i64.i64(<vscale x 1 x i64>, ptr nocapture, i64) #4
@@ -408,7 +412,7 @@ body: |
408412
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x10
409413
; CHECK-NEXT: dead $x0 = PseudoVSETVLI [[COPY]], 216 /* e64, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
410414
; CHECK-NEXT: [[PseudoVLE64_V_M1_:%[0-9]+]]:vr = PseudoVLE64_V_M1 undef $noreg, [[COPY2]], $noreg, 6 /* e64 */, 0 /* tu, mu */, implicit $vl, implicit $vtype
411-
; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */
415+
; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, implicit-def $vl, implicit-def $vtype
412416
; CHECK-NEXT: dead $x0 = PseudoVSETVLI [[COPY]], 216 /* e64, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
413417
; CHECK-NEXT: [[PseudoVADD_VV_M1_:%[0-9]+]]:vr = PseudoVADD_VV_M1 undef $noreg, [[PseudoVLE64_V_M1_]], [[COPY1]], $noreg, 6 /* e64 */, 0 /* tu, mu */, implicit $vl, implicit $vtype
414418
; CHECK-NEXT: $v8 = COPY [[PseudoVADD_VV_M1_]], implicit $vtype
@@ -601,3 +605,20 @@ body: |
601605
%x:gpr = COPY $x10
602606
renamable $v8 = PseudoVMV_S_X undef renamable $v8, killed renamable %x, 1, 5
603607
PseudoRET implicit $v8
608+
...
609+
---
610+
name: coalesce_vl_avl_same_reg
611+
tracksRegLiveness: true
612+
body: |
613+
bb.0:
614+
liveins: $x8, $v8
615+
; CHECK-LABEL: name: coalesce_vl_avl_same_reg
616+
; CHECK: liveins: $x8, $v8
617+
; CHECK-NEXT: {{ $}}
618+
; CHECK-NEXT: %x:gprnox0 = COPY $x8
619+
; CHECK-NEXT: dead %x:gprnox0 = PseudoVSETVLI %x, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
620+
; CHECK-NEXT: dead %v:vr = COPY $v8, implicit $vtype
621+
%x:gprnox0 = COPY $x8
622+
dead $x0 = PseudoVSETIVLI 1, 208, implicit-def $vl, implicit-def $vtype
623+
%v:vr = COPY $v8, implicit $vtype
624+
%x = PseudoVSETVLI %x, 208, implicit-def $vl, implicit-def $vtype

0 commit comments

Comments
 (0)