diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp index bf9de0a4b5604..e5819d90526d9 100644 --- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp +++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp @@ -1755,6 +1755,14 @@ bool RISCVInsertVSETVLI::canMutatePriorConfig( if (!VNI || !PrevVNI || VNI != PrevVNI) return false; } + + // If we define VL and need to move the definition up, check we can extend + // the live interval upwards from MI to PrevMI. + Register VL = MI.getOperand(0).getReg(); + if (VL.isVirtual() && LIS && + LIS->getInterval(VL).overlaps(LIS->getInstructionIndex(PrevMI), + LIS->getInstructionIndex(MI))) + return false; } assert(PrevMI.getOperand(2).isImm() && MI.getOperand(2).isImm()); diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll index b6e29cf76cd48..e8d89d4066e43 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.ll @@ -879,3 +879,46 @@ entry: %3 = tail call { , i64 } @llvm.riscv.vleff( poison, ptr %p, i64 %2) ret void } + +; This will create a live interval in such a way we can't coalesce two vsetvlis, +; see the corresponding .mir test for more details. Make sure we check for this +; and don't crash. +define void @coalesce_vl_clobber(ptr %p) { +; CHECK-LABEL: coalesce_vl_clobber: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li a2, 0 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: vsetivli zero, 0, e8, mf2, ta, ma +; CHECK-NEXT: vmclr.m v8 +; CHECK-NEXT: vmv.v.i v9, 0 +; CHECK-NEXT: vmv1r.v v0, v8 +; CHECK-NEXT: vmerge.vim v9, v9, 1, v0 +; CHECK-NEXT: .LBB43_1: # %vector.body +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v0, v8 +; CHECK-NEXT: slli a3, a1, 32 +; CHECK-NEXT: vsetvli a1, a2, e8, mf8, ta, ma +; CHECK-NEXT: vsetivli zero, 0, e8, mf2, ta, mu +; CHECK-NEXT: vmv.v.i v10, 0 +; CHECK-NEXT: srli a3, a3, 32 +; CHECK-NEXT: vmerge.vim v10, v10, 1, v0 +; CHECK-NEXT: vslideup.vx v10, v9, a3, v0.t +; CHECK-NEXT: vsetvli zero, zero, e8, mf2, ta, ma +; CHECK-NEXT: vmsne.vi v0, v10, 0, v0.t +; CHECK-NEXT: vsetvli zero, a1, e32, m2, ta, ma +; CHECK-NEXT: vmv.v.i v10, 0 +; CHECK-NEXT: vse32.v v10, (a0), v0.t +; CHECK-NEXT: li a2, 1 +; CHECK-NEXT: j .LBB43_1 +entry: + br label %vector.body + +vector.body: + %avl = phi i64 [ 0, %entry ], [ 1, %vector.body ] + %prev.evl = phi i32 [ 0, %entry ], [ %0, %vector.body ] + %0 = tail call i32 @llvm.experimental.get.vector.length(i64 %avl, i32 1, i1 true) + %1 = tail call @llvm.experimental.vp.splice( zeroinitializer, zeroinitializer, i32 0, zeroinitializer, i32 %prev.evl, i32 0) + tail call void @llvm.vp.store( zeroinitializer, ptr %p, %1, i32 %0) + br label %vector.body +} diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir index f9929c9caf712..396ca517e4017 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-insert.mir @@ -100,6 +100,10 @@ ret void } + define void @coalesce_vl_clobber() { + ret void + } + define void @vsetvli_vleff() { ret void } @@ -624,10 +628,33 @@ body: | ; CHECK: liveins: $x8, $v8 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %x:gprnox0 = COPY $x8 + ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 1, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + ; CHECK-NEXT: dead %v:vr = COPY $v8, implicit $vtype ; CHECK-NEXT: dead %x:gprnox0 = PseudoVSETVLI %x, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + %x:gprnox0 = COPY $x8 + dead $x0 = PseudoVSETIVLI 1, 208, implicit-def $vl, implicit-def $vtype + %v:vr = COPY $v8, implicit $vtype + %x = PseudoVSETVLI %x, 208, implicit-def $vl, implicit-def $vtype +... +--- +# Because of the %y:gprnox0 = COPY %x, we can't extend the live range of %x from +# the second vsetvli to the first vsetvli when coalescing. +name: coalesce_vl_clobber +tracksRegLiveness: true +body: | + bb.0: + liveins: $x8, $v8 + ; CHECK-LABEL: name: coalesce_vl_clobber + ; CHECK: liveins: $x8, $v8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %x:gprnox0 = COPY $x8 + ; CHECK-NEXT: dead $x0 = PseudoVSETIVLI 1, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype + ; CHECK-NEXT: dead %y:gprnox0 = COPY %x ; CHECK-NEXT: dead %v:vr = COPY $v8, implicit $vtype + ; CHECK-NEXT: dead %x:gprnox0 = PseudoVSETVLI %x, 208 /* e32, m1, ta, ma */, implicit-def $vl, implicit-def $vtype %x:gprnox0 = COPY $x8 dead $x0 = PseudoVSETIVLI 1, 208, implicit-def $vl, implicit-def $vtype + %y:gprnox0 = COPY %x %v:vr = COPY $v8, implicit $vtype %x = PseudoVSETVLI %x, 208, implicit-def $vl, implicit-def $vtype ...