1119 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=riscv64 -mattr=+m,+f,+d,+a,+c,+v \3; RUN: -target-abi=lp64d -verify-machineinstrs -O2 < %s | FileCheck %s4 5; The following tests check whether inserting VSETVLI avoids inserting6; unneeded vsetvlis across basic blocks.7 8define <vscale x 1 x double> @test1(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {9; CHECK-LABEL: test1:10; CHECK: # %bb.0: # %entry11; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma12; CHECK-NEXT: beqz a1, .LBB0_213; CHECK-NEXT: # %bb.1: # %if.then14; CHECK-NEXT: vfadd.vv v8, v8, v915; CHECK-NEXT: ret16; CHECK-NEXT: .LBB0_2: # %if.else17; CHECK-NEXT: vfsub.vv v8, v8, v918; CHECK-NEXT: ret19entry:20 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)21 %tobool = icmp eq i8 %cond, 022 br i1 %tobool, label %if.else, label %if.then23 24if.then: ; preds = %entry25 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)26 br label %if.end27 28if.else: ; preds = %entry29 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)30 br label %if.end31 32if.end: ; preds = %if.else, %if.then33 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %2, %if.else ]34 ret <vscale x 1 x double> %c.035}36 37@scratch = global i8 0, align 1638 39define <vscale x 1 x double> @test2(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {40; CHECK-LABEL: test2:41; CHECK: # %bb.0: # %entry42; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma43; CHECK-NEXT: beqz a1, .LBB1_244; CHECK-NEXT: # %bb.1: # %if.then45; CHECK-NEXT: vfadd.vv v9, v8, v946; CHECK-NEXT: vfmul.vv v8, v9, v847; CHECK-NEXT: ret48; CHECK-NEXT: .LBB1_2: # %if.else49; CHECK-NEXT: vfsub.vv v9, v8, v950; CHECK-NEXT: vfmul.vv v8, v9, v851; CHECK-NEXT: ret52entry:53 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)54 %tobool = icmp eq i8 %cond, 055 br i1 %tobool, label %if.else, label %if.then56 57if.then: ; preds = %entry58 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)59 br label %if.end60 61if.else: ; preds = %entry62 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)63 br label %if.end64 65if.end: ; preds = %if.else, %if.then66 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %2, %if.else ]67 %3 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %c.0, <vscale x 1 x double> %a, i64 7, i64 %0)68 ret <vscale x 1 x double> %369}70 71define <vscale x 1 x double> @test3(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {72; CHECK-LABEL: test3:73; CHECK: # %bb.0: # %entry74; CHECK-NEXT: beqz a1, .LBB2_275; CHECK-NEXT: # %bb.1: # %if.then76; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma77; CHECK-NEXT: vfadd.vv v9, v8, v978; CHECK-NEXT: vfmul.vv v8, v9, v879; CHECK-NEXT: ret80; CHECK-NEXT: .LBB2_2: # %if.else81; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma82; CHECK-NEXT: vfsub.vv v9, v8, v983; CHECK-NEXT: vfmul.vv v8, v9, v884; CHECK-NEXT: ret85entry:86 %tobool = icmp eq i8 %cond, 087 br i1 %tobool, label %if.else, label %if.then88 89if.then: ; preds = %entry90 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)91 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)92 br label %if.end93 94if.else: ; preds = %entry95 %2 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)96 %3 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %2)97 br label %if.end98 99if.end: ; preds = %if.else, %if.then100 %vl.0 = phi i64 [ %0, %if.then], [ %2, %if.else ]101 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %3, %if.else ]102 %4 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %c.0, <vscale x 1 x double> %a, i64 7, i64 %vl.0)103 ret <vscale x 1 x double> %4104}105 106define <vscale x 1 x double> @test4(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %l, <vscale x 1 x double> %r) nounwind {107; CHECK-LABEL: test4:108; CHECK: # %bb.0: # %entry109; CHECK-NEXT: beqz a1, .LBB3_2110; CHECK-NEXT: # %bb.1: # %if.then111; CHECK-NEXT: li a1, 1023112; CHECK-NEXT: slli a1, a1, 52113; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma114; CHECK-NEXT: vmv.v.x v10, a1115; CHECK-NEXT: li a1, 1116; CHECK-NEXT: slli a1, a1, 62117; CHECK-NEXT: vmv.v.x v11, a1118; CHECK-NEXT: vfadd.vv v10, v10, v11119; CHECK-NEXT: lui a1, %hi(scratch)120; CHECK-NEXT: addi a1, a1, %lo(scratch)121; CHECK-NEXT: vse64.v v10, (a1)122; CHECK-NEXT: j .LBB3_3123; CHECK-NEXT: .LBB3_2: # %if.else124; CHECK-NEXT: lui a1, 260096125; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma126; CHECK-NEXT: vmv.v.x v10, a1127; CHECK-NEXT: lui a1, 262144128; CHECK-NEXT: vmv.v.x v11, a1129; CHECK-NEXT: vfadd.vv v10, v10, v11130; CHECK-NEXT: lui a1, %hi(scratch)131; CHECK-NEXT: addi a1, a1, %lo(scratch)132; CHECK-NEXT: vse32.v v10, (a1)133; CHECK-NEXT: .LBB3_3: # %if.end134; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma135; CHECK-NEXT: vfmul.vv v8, v8, v9136; CHECK-NEXT: ret137entry:138 %tobool = icmp eq i8 %cond, 0139 br i1 %tobool, label %if.else, label %if.then140 141if.then: ; preds = %entry142 %0 = tail call <vscale x 1 x double> @llvm.riscv.vfmv.v.f.nxv1f64.f64(<vscale x 1 x double> poison, double 1.000000e+00, i64 %avl)143 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfmv.v.f.nxv1f64.f64(<vscale x 1 x double> poison, double 2.000000e+00, i64 %avl)144 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %0, <vscale x 1 x double> %1, i64 7, i64 %avl)145 %3 = bitcast ptr @scratch to ptr146 tail call void @llvm.riscv.vse.nxv1f64(<vscale x 1 x double> %2, ptr %3, i64 %avl)147 br label %if.end148 149if.else: ; preds = %entry150 %4 = tail call <vscale x 2 x float> @llvm.riscv.vfmv.v.f.nxv2f32.f32(<vscale x 2 x float> poison, float 1.000000e+00, i64 %avl)151 %5 = tail call <vscale x 2 x float> @llvm.riscv.vfmv.v.f.nxv2f32.f32(<vscale x 2 x float> poison, float 2.000000e+00, i64 %avl)152 %6 = tail call <vscale x 2 x float> @llvm.riscv.vfadd.nxv2f32.nxv2f32(<vscale x 2 x float> poison, <vscale x 2 x float> %4, <vscale x 2 x float> %5, i64 7, i64 %avl)153 %7 = bitcast ptr @scratch to ptr154 tail call void @llvm.riscv.vse.nxv2f32(<vscale x 2 x float> %6, ptr %7, i64 %avl)155 br label %if.end156 157if.end: ; preds = %if.else, %if.then158 %8 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %l, <vscale x 1 x double> %r, i64 7, i64 %avl)159 ret <vscale x 1 x double> %8160}161 162define <vscale x 1 x double> @test5(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {163; CHECK-LABEL: test5:164; CHECK: # %bb.0: # %entry165; CHECK-NEXT: andi a2, a1, 1166; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma167; CHECK-NEXT: bnez a2, .LBB4_3168; CHECK-NEXT: # %bb.1: # %if.else169; CHECK-NEXT: vfsub.vv v9, v8, v9170; CHECK-NEXT: andi a1, a1, 2171; CHECK-NEXT: beqz a1, .LBB4_4172; CHECK-NEXT: .LBB4_2: # %if.then4173; CHECK-NEXT: vfmul.vv v8, v9, v8174; CHECK-NEXT: ret175; CHECK-NEXT: .LBB4_3: # %if.then176; CHECK-NEXT: vfadd.vv v9, v8, v9177; CHECK-NEXT: andi a1, a1, 2178; CHECK-NEXT: bnez a1, .LBB4_2179; CHECK-NEXT: .LBB4_4: # %if.else5180; CHECK-NEXT: vfmul.vv v8, v8, v9181; CHECK-NEXT: ret182entry:183 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)184 %conv = zext i8 %cond to i32185 %and = and i32 %conv, 1186 %tobool = icmp eq i32 %and, 0187 br i1 %tobool, label %if.else, label %if.then188 189if.then: ; preds = %entry190 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)191 br label %if.end192 193if.else: ; preds = %entry194 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)195 br label %if.end196 197if.end: ; preds = %if.else, %if.then198 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %2, %if.else ]199 %and2 = and i32 %conv, 2200 %tobool3 = icmp eq i32 %and2, 0201 br i1 %tobool3, label %if.else5, label %if.then4202 203if.then4: ; preds = %if.end204 %3 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %c.0, <vscale x 1 x double> %a, i64 7, i64 %0)205 br label %if.end6206 207if.else5: ; preds = %if.end208 %4 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %c.0, i64 7, i64 %0)209 br label %if.end6210 211if.end6: ; preds = %if.else5, %if.then4212 %c.1 = phi <vscale x 1 x double> [ %3, %if.then4 ], [ %4, %if.else5 ]213 ret <vscale x 1 x double> %c.1214}215 216; FIXME: The explicit vsetvli in if.then4 could be removed as it is redundant217; with the one in the entry, but we lack the ability to remove explicit218; vsetvli instructions.219define <vscale x 1 x double> @test6(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {220; CHECK-LABEL: test6:221; CHECK: # %bb.0: # %entry222; CHECK-NEXT: andi a2, a1, 1223; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma224; CHECK-NEXT: bnez a2, .LBB5_3225; CHECK-NEXT: # %bb.1: # %if.else226; CHECK-NEXT: vfsub.vv v8, v8, v9227; CHECK-NEXT: andi a1, a1, 2228; CHECK-NEXT: beqz a1, .LBB5_4229; CHECK-NEXT: .LBB5_2: # %if.then4230; CHECK-NEXT: li a1, 1023231; CHECK-NEXT: slli a1, a1, 52232; CHECK-NEXT: vmv.v.x v9, a1233; CHECK-NEXT: li a1, 1234; CHECK-NEXT: slli a1, a1, 62235; CHECK-NEXT: vmv.v.x v10, a1236; CHECK-NEXT: vfadd.vv v9, v9, v10237; CHECK-NEXT: lui a1, %hi(scratch)238; CHECK-NEXT: addi a1, a1, %lo(scratch)239; CHECK-NEXT: vse64.v v9, (a1)240; CHECK-NEXT: j .LBB5_5241; CHECK-NEXT: .LBB5_3: # %if.then242; CHECK-NEXT: vfadd.vv v8, v8, v9243; CHECK-NEXT: andi a1, a1, 2244; CHECK-NEXT: bnez a1, .LBB5_2245; CHECK-NEXT: .LBB5_4: # %if.else5246; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma247; CHECK-NEXT: lui a1, 260096248; CHECK-NEXT: vmv.v.x v9, a1249; CHECK-NEXT: lui a1, 262144250; CHECK-NEXT: vmv.v.x v10, a1251; CHECK-NEXT: vfadd.vv v9, v9, v10252; CHECK-NEXT: lui a1, %hi(scratch)253; CHECK-NEXT: addi a1, a1, %lo(scratch)254; CHECK-NEXT: vse32.v v9, (a1)255; CHECK-NEXT: .LBB5_5: # %if.end10256; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma257; CHECK-NEXT: vfmul.vv v8, v8, v8258; CHECK-NEXT: ret259entry:260 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)261 %conv = zext i8 %cond to i32262 %and = and i32 %conv, 1263 %tobool = icmp eq i32 %and, 0264 br i1 %tobool, label %if.else, label %if.then265 266if.then: ; preds = %entry267 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)268 br label %if.end269 270if.else: ; preds = %entry271 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)272 br label %if.end273 274if.end: ; preds = %if.else, %if.then275 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %2, %if.else ]276 %and2 = and i32 %conv, 2277 %tobool3 = icmp eq i32 %and2, 0278 br i1 %tobool3, label %if.else5, label %if.then4279 280if.then4: ; preds = %if.end281 %3 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)282 %4 = tail call <vscale x 1 x double> @llvm.riscv.vfmv.v.f.nxv1f64.f64(<vscale x 1 x double> poison, double 1.000000e+00, i64 %3)283 %5 = tail call <vscale x 1 x double> @llvm.riscv.vfmv.v.f.nxv1f64.f64(<vscale x 1 x double> poison, double 2.000000e+00, i64 %3)284 %6 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %4, <vscale x 1 x double> %5, i64 7, i64 %3)285 %7 = bitcast ptr @scratch to ptr286 tail call void @llvm.riscv.vse.nxv1f64(<vscale x 1 x double> %6, ptr %7, i64 %3)287 br label %if.end10288 289if.else5: ; preds = %if.end290 %8 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 0)291 %9 = tail call <vscale x 2 x float> @llvm.riscv.vfmv.v.f.nxv2f32.f32(<vscale x 2 x float> poison, float 1.000000e+00, i64 %8)292 %10 = tail call <vscale x 2 x float> @llvm.riscv.vfmv.v.f.nxv2f32.f32( <vscale x 2 x float> poison, float 2.000000e+00, i64 %8)293 %11 = tail call <vscale x 2 x float> @llvm.riscv.vfadd.nxv2f32.nxv2f32(<vscale x 2 x float> poison, <vscale x 2 x float> %9, <vscale x 2 x float> %10, i64 7, i64 %8)294 %12 = bitcast ptr @scratch to ptr295 tail call void @llvm.riscv.vse.nxv2f32(<vscale x 2 x float> %11, ptr %12, i64 %8)296 br label %if.end10297 298if.end10: ; preds = %if.else5, %if.then4299 %13 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %c.0, <vscale x 1 x double> %c.0, i64 7, i64 %0)300 ret <vscale x 1 x double> %13301}302 303declare void @foo()304 305; Similar to test1, but contains a call to @foo to act as barrier to analyzing306; VL/VTYPE.307define <vscale x 1 x double> @test8(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {308; CHECK-LABEL: test8:309; CHECK: # %bb.0: # %entry310; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma311; CHECK-NEXT: beqz a1, .LBB6_2312; CHECK-NEXT: # %bb.1: # %if.then313; CHECK-NEXT: vfadd.vv v8, v8, v9314; CHECK-NEXT: ret315; CHECK-NEXT: .LBB6_2: # %if.else316; CHECK-NEXT: addi sp, sp, -32317; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill318; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill319; CHECK-NEXT: csrr a1, vlenb320; CHECK-NEXT: slli a1, a1, 1321; CHECK-NEXT: sub sp, sp, a1322; CHECK-NEXT: mv s0, a0323; CHECK-NEXT: csrr a0, vlenb324; CHECK-NEXT: add a0, a0, sp325; CHECK-NEXT: addi a0, a0, 16326; CHECK-NEXT: vs1r.v v9, (a0) # vscale x 8-byte Folded Spill327; CHECK-NEXT: addi a0, sp, 16328; CHECK-NEXT: vs1r.v v8, (a0) # vscale x 8-byte Folded Spill329; CHECK-NEXT: call foo330; CHECK-NEXT: csrr a0, vlenb331; CHECK-NEXT: add a0, a0, sp332; CHECK-NEXT: addi a0, a0, 16333; CHECK-NEXT: vl1r.v v8, (a0) # vscale x 8-byte Folded Reload334; CHECK-NEXT: addi a0, sp, 16335; CHECK-NEXT: vl1r.v v9, (a0) # vscale x 8-byte Folded Reload336; CHECK-NEXT: vsetvli zero, s0, e64, m1, ta, ma337; CHECK-NEXT: vfsub.vv v8, v9, v8338; CHECK-NEXT: csrr a0, vlenb339; CHECK-NEXT: slli a0, a0, 1340; CHECK-NEXT: add sp, sp, a0341; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload342; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload343; CHECK-NEXT: addi sp, sp, 32344; CHECK-NEXT: ret345entry:346 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)347 %tobool = icmp eq i8 %cond, 0348 br i1 %tobool, label %if.else, label %if.then349 350if.then: ; preds = %entry351 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)352 br label %if.end353 354if.else: ; preds = %entry355 call void @foo()356 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)357 br label %if.end358 359if.end: ; preds = %if.else, %if.then360 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %2, %if.else ]361 ret <vscale x 1 x double> %c.0362}363 364; Similar to test2, but contains a call to @foo to act as barrier to analyzing365; VL/VTYPE.366define <vscale x 1 x double> @test9(i64 %avl, i8 zeroext %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b) nounwind {367; CHECK-LABEL: test9:368; CHECK: # %bb.0: # %entry369; CHECK-NEXT: addi sp, sp, -32370; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill371; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill372; CHECK-NEXT: csrr a2, vlenb373; CHECK-NEXT: slli a2, a2, 1374; CHECK-NEXT: sub sp, sp, a2375; CHECK-NEXT: mv s0, a0376; CHECK-NEXT: vsetvli zero, a0, e64, m1, ta, ma377; CHECK-NEXT: beqz a1, .LBB7_2378; CHECK-NEXT: # %bb.1: # %if.then379; CHECK-NEXT: vfadd.vv v9, v8, v9380; CHECK-NEXT: addi a0, sp, 16381; CHECK-NEXT: vs1r.v v9, (a0) # vscale x 8-byte Folded Spill382; CHECK-NEXT: csrr a0, vlenb383; CHECK-NEXT: add a0, a0, sp384; CHECK-NEXT: addi a0, a0, 16385; CHECK-NEXT: vs1r.v v8, (a0) # vscale x 8-byte Folded Spill386; CHECK-NEXT: call foo387; CHECK-NEXT: addi a0, sp, 16388; CHECK-NEXT: vl1r.v v9, (a0) # vscale x 8-byte Folded Reload389; CHECK-NEXT: csrr a0, vlenb390; CHECK-NEXT: add a0, a0, sp391; CHECK-NEXT: addi a0, a0, 16392; CHECK-NEXT: vl1r.v v8, (a0) # vscale x 8-byte Folded Reload393; CHECK-NEXT: j .LBB7_3394; CHECK-NEXT: .LBB7_2: # %if.else395; CHECK-NEXT: vfsub.vv v9, v8, v9396; CHECK-NEXT: .LBB7_3: # %if.end397; CHECK-NEXT: vsetvli zero, s0, e64, m1, ta, ma398; CHECK-NEXT: vfmul.vv v8, v9, v8399; CHECK-NEXT: csrr a0, vlenb400; CHECK-NEXT: slli a0, a0, 1401; CHECK-NEXT: add sp, sp, a0402; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload403; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload404; CHECK-NEXT: addi sp, sp, 32405; CHECK-NEXT: ret406entry:407 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)408 %tobool = icmp eq i8 %cond, 0409 br i1 %tobool, label %if.else, label %if.then410 411if.then: ; preds = %entry412 %1 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)413 call void @foo()414 br label %if.end415 416if.else: ; preds = %entry417 %2 = tail call <vscale x 1 x double> @llvm.riscv.vfsub.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %a, <vscale x 1 x double> %b, i64 7, i64 %0)418 br label %if.end419 420if.end: ; preds = %if.else, %if.then421 %c.0 = phi <vscale x 1 x double> [ %1, %if.then ], [ %2, %if.else ]422 %3 = tail call <vscale x 1 x double> @llvm.riscv.vfmul.nxv1f64.nxv1f64(<vscale x 1 x double> poison, <vscale x 1 x double> %c.0, <vscale x 1 x double> %a, i64 7, i64 %0)423 ret <vscale x 1 x double> %3424}425 426define void @saxpy_vec(i64 %n, float %a, ptr nocapture readonly %x, ptr nocapture %y) {427; CHECK-LABEL: saxpy_vec:428; CHECK: # %bb.0: # %entry429; CHECK-NEXT: vsetvli a3, a0, e32, m8, ta, ma430; CHECK-NEXT: beqz a3, .LBB8_2431; CHECK-NEXT: .LBB8_1: # %for.body432; CHECK-NEXT: # =>This Inner Loop Header: Depth=1433; CHECK-NEXT: vle32.v v8, (a1)434; CHECK-NEXT: vle32.v v16, (a2)435; CHECK-NEXT: slli a4, a3, 2436; CHECK-NEXT: sub a0, a0, a3437; CHECK-NEXT: add a1, a1, a4438; CHECK-NEXT: vsetvli zero, zero, e32, m8, tu, ma439; CHECK-NEXT: vfmacc.vf v16, fa0, v8440; CHECK-NEXT: vse32.v v16, (a2)441; CHECK-NEXT: vsetvli a3, a0, e32, m8, ta, ma442; CHECK-NEXT: add a2, a2, a4443; CHECK-NEXT: bnez a3, .LBB8_1444; CHECK-NEXT: .LBB8_2: # %for.end445; CHECK-NEXT: ret446entry:447 %0 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 2, i64 3)448 %cmp.not13 = icmp eq i64 %0, 0449 br i1 %cmp.not13, label %for.end, label %for.body450 451for.body: ; preds = %for.body, %entry452 %1 = phi i64 [ %7, %for.body ], [ %0, %entry ]453 %n.addr.016 = phi i64 [ %sub, %for.body ], [ %n, %entry ]454 %x.addr.015 = phi ptr [ %add.ptr, %for.body ], [ %x, %entry ]455 %y.addr.014 = phi ptr [ %add.ptr1, %for.body ], [ %y, %entry ]456 %2 = bitcast ptr %x.addr.015 to ptr457 %3 = tail call <vscale x 16 x float> @llvm.riscv.vle.nxv16f32.i64(<vscale x 16 x float> poison, ptr %2, i64 %1)458 %add.ptr = getelementptr inbounds float, ptr %x.addr.015, i64 %1459 %4 = bitcast ptr %y.addr.014 to ptr460 %5 = tail call <vscale x 16 x float> @llvm.riscv.vle.nxv16f32.i64(<vscale x 16 x float> poison, ptr %4, i64 %1)461 %6 = tail call <vscale x 16 x float> @llvm.riscv.vfmacc.nxv16f32.f32.i64(<vscale x 16 x float> %5, float %a, <vscale x 16 x float> %3, i64 7, i64 %1, i64 0)462 tail call void @llvm.riscv.vse.nxv16f32.i64(<vscale x 16 x float> %6, ptr %4, i64 %1)463 %add.ptr1 = getelementptr inbounds float, ptr %y.addr.014, i64 %1464 %sub = sub i64 %n.addr.016, %1465 %7 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %sub, i64 2, i64 3)466 %cmp.not = icmp eq i64 %7, 0467 br i1 %cmp.not, label %for.end, label %for.body468 469for.end: ; preds = %for.body, %entry470 ret void471}472 473define void @saxpy_vec_demanded_fields(i64 %n, float %a, ptr nocapture readonly %x, ptr nocapture %y) {474; CHECK-LABEL: saxpy_vec_demanded_fields:475; CHECK: # %bb.0: # %entry476; CHECK-NEXT: vsetvli a3, a0, e32, m8, ta, ma477; CHECK-NEXT: beqz a3, .LBB9_2478; CHECK-NEXT: .LBB9_1: # %for.body479; CHECK-NEXT: # =>This Inner Loop Header: Depth=1480; CHECK-NEXT: vsetvli zero, a3, e32, m8, ta, ma481; CHECK-NEXT: vle32.v v8, (a1)482; CHECK-NEXT: vle32.v v16, (a2)483; CHECK-NEXT: slli a4, a3, 2484; CHECK-NEXT: sub a0, a0, a3485; CHECK-NEXT: add a1, a1, a4486; CHECK-NEXT: vsetvli zero, zero, e32, m8, tu, ma487; CHECK-NEXT: vfmacc.vf v16, fa0, v8488; CHECK-NEXT: vse32.v v16, (a2)489; CHECK-NEXT: vsetvli a3, a0, e16, m4, ta, ma490; CHECK-NEXT: add a2, a2, a4491; CHECK-NEXT: bnez a3, .LBB9_1492; CHECK-NEXT: .LBB9_2: # %for.end493; CHECK-NEXT: ret494entry:495 %0 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 2, i64 3)496 %cmp.not13 = icmp eq i64 %0, 0497 br i1 %cmp.not13, label %for.end, label %for.body498 499for.body: ; preds = %for.body, %entry500 %1 = phi i64 [ %7, %for.body ], [ %0, %entry ]501 %n.addr.016 = phi i64 [ %sub, %for.body ], [ %n, %entry ]502 %x.addr.015 = phi ptr [ %add.ptr, %for.body ], [ %x, %entry ]503 %y.addr.014 = phi ptr [ %add.ptr1, %for.body ], [ %y, %entry ]504 %2 = bitcast ptr %x.addr.015 to ptr505 %3 = tail call <vscale x 16 x float> @llvm.riscv.vle.nxv16f32.i64(<vscale x 16 x float> poison, ptr %2, i64 %1)506 %add.ptr = getelementptr inbounds float, ptr %x.addr.015, i64 %1507 %4 = bitcast ptr %y.addr.014 to ptr508 %5 = tail call <vscale x 16 x float> @llvm.riscv.vle.nxv16f32.i64(<vscale x 16 x float> poison, ptr %4, i64 %1)509 %6 = tail call <vscale x 16 x float> @llvm.riscv.vfmacc.nxv16f32.f32.i64(<vscale x 16 x float> %5, float %a, <vscale x 16 x float> %3, i64 7, i64 %1, i64 0)510 tail call void @llvm.riscv.vse.nxv16f32.i64(<vscale x 16 x float> %6, ptr %4, i64 %1)511 %add.ptr1 = getelementptr inbounds float, ptr %y.addr.014, i64 %1512 %sub = sub i64 %n.addr.016, %1513 %7 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %sub, i64 1, i64 2)514 %cmp.not = icmp eq i64 %7, 0515 br i1 %cmp.not, label %for.end, label %for.body516 517for.end: ; preds = %for.body, %entry518 ret void519}520 521; We need a vsetvli in the last block because the predecessors have different522; VTYPEs. The AVL is the same and the SEW/LMUL ratio implies the same VLMAX so523; we don't need to read AVL and can keep VL unchanged.524define <vscale x 2 x i32> @test_vsetvli_x0_x0(ptr %x, ptr %y, <vscale x 2 x i32> %z, i64 %vl, i1 %cond) nounwind {525; CHECK-LABEL: test_vsetvli_x0_x0:526; CHECK: # %bb.0: # %entry527; CHECK-NEXT: vsetvli zero, a2, e32, m1, ta, ma528; CHECK-NEXT: vle32.v v9, (a0)529; CHECK-NEXT: andi a3, a3, 1530; CHECK-NEXT: beqz a3, .LBB10_2531; CHECK-NEXT: # %bb.1: # %if532; CHECK-NEXT: vle16.v v10, (a1)533; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma534; CHECK-NEXT: vwcvt.x.x.v v8, v10535; CHECK-NEXT: .LBB10_2: # %if.end536; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma537; CHECK-NEXT: vadd.vv v8, v9, v8538; CHECK-NEXT: ret539entry:540 %a = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32(<vscale x 2 x i32> poison, ptr %x, i64 %vl)541 br i1 %cond, label %if, label %if.end542 543if:544 %b = call <vscale x 2 x i16> @llvm.riscv.vle.nxv2i16(<vscale x 2 x i16> poison, ptr %y, i64 %vl)545 %c = call <vscale x 2 x i32> @llvm.riscv.vwadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i16> %b, i16 0, i64 %vl)546 br label %if.end547 548if.end:549 %d = phi <vscale x 2 x i32> [ %z, %entry ], [ %c, %if ]550 %e = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %a, <vscale x 2 x i32> %d, i64 %vl)551 ret <vscale x 2 x i32> %e552}553 554; We can use X0, X0 vsetvli in if2 and if2.end. The merge point as if.end will555; see two different vtypes with the same SEW/LMUL ratio. At if2.end we will only556; know the SEW/LMUL ratio for the if.end predecessor and the full vtype for557; the if2 predecessor. This makes sure we can merge a SEW/LMUL predecessor with558; a predecessor we know the vtype for.559define <vscale x 2 x i32> @test_vsetvli_x0_x0_2(ptr %x, ptr %y, ptr %z, i64 %vl, i1 %cond, i1 %cond2, <vscale x 2 x i32> %w) nounwind {560; CHECK-LABEL: test_vsetvli_x0_x0_2:561; CHECK: # %bb.0: # %entry562; CHECK-NEXT: vsetvli zero, a3, e32, m1, ta, ma563; CHECK-NEXT: vle32.v v9, (a0)564; CHECK-NEXT: andi a4, a4, 1565; CHECK-NEXT: beqz a4, .LBB11_2566; CHECK-NEXT: # %bb.1: # %if567; CHECK-NEXT: vle16.v v10, (a1)568; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma569; CHECK-NEXT: vwadd.wv v9, v9, v10570; CHECK-NEXT: .LBB11_2: # %if.end571; CHECK-NEXT: andi a5, a5, 1572; CHECK-NEXT: beqz a5, .LBB11_4573; CHECK-NEXT: # %bb.3: # %if2574; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma575; CHECK-NEXT: vle16.v v10, (a2)576; CHECK-NEXT: vwadd.wv v9, v9, v10577; CHECK-NEXT: .LBB11_4: # %if2.end578; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma579; CHECK-NEXT: vadd.vv v8, v9, v8580; CHECK-NEXT: ret581entry:582 %a = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32(<vscale x 2 x i32> poison, ptr %x, i64 %vl)583 br i1 %cond, label %if, label %if.end584 585if:586 %b = call <vscale x 2 x i16> @llvm.riscv.vle.nxv2i16(<vscale x 2 x i16> poison, ptr %y, i64 %vl)587 %c = call <vscale x 2 x i32> @llvm.riscv.vwadd.w.nxv2i32.nxv2i16(<vscale x 2 x i32> poison, <vscale x 2 x i32> %a, <vscale x 2 x i16> %b, i64 %vl)588 br label %if.end589 590if.end:591 %d = phi <vscale x 2 x i32> [ %a, %entry ], [ %c, %if ]592 br i1 %cond2, label %if2, label %if2.end593 594if2:595 %e = call <vscale x 2 x i16> @llvm.riscv.vle.nxv2i16(<vscale x 2 x i16> poison, ptr %z, i64 %vl)596 %f = call <vscale x 2 x i32> @llvm.riscv.vwadd.w.nxv2i32.nxv2i16(<vscale x 2 x i32> poison, <vscale x 2 x i32> %d, <vscale x 2 x i16> %e, i64 %vl)597 br label %if2.end598 599if2.end:600 %g = phi <vscale x 2 x i32> [ %d, %if.end ], [ %f, %if2 ]601 %h = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %g, <vscale x 2 x i32> %w, i64 %vl)602 ret <vscale x 2 x i32> %h603}604 605; We should only need 1 vsetvli for this code.606define void @vlmax(i64 %N, ptr %c, ptr %a, ptr %b) {607; CHECK-LABEL: vlmax:608; CHECK: # %bb.0: # %entry609; CHECK-NEXT: blez a0, .LBB12_3610; CHECK-NEXT: # %bb.1: # %for.body.preheader611; CHECK-NEXT: li a4, 0612; CHECK-NEXT: vsetvli a6, zero, e64, m1, ta, ma613; CHECK-NEXT: slli a5, a6, 3614; CHECK-NEXT: .LBB12_2: # %for.body615; CHECK-NEXT: # =>This Inner Loop Header: Depth=1616; CHECK-NEXT: vle64.v v8, (a2)617; CHECK-NEXT: vle64.v v9, (a3)618; CHECK-NEXT: add a4, a4, a6619; CHECK-NEXT: add a3, a3, a5620; CHECK-NEXT: vfadd.vv v8, v8, v9621; CHECK-NEXT: vse64.v v8, (a1)622; CHECK-NEXT: add a1, a1, a5623; CHECK-NEXT: add a2, a2, a5624; CHECK-NEXT: blt a4, a0, .LBB12_2625; CHECK-NEXT: .LBB12_3: # %for.end626; CHECK-NEXT: ret627entry:628 %0 = tail call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 0)629 %cmp13 = icmp sgt i64 %N, 0630 br i1 %cmp13, label %for.body, label %for.end631 632for.body: ; preds = %entry, %for.body633 %i.014 = phi i64 [ %add, %for.body ], [ 0, %entry ]634 %arrayidx = getelementptr inbounds double, ptr %a, i64 %i.014635 %1 = bitcast ptr %arrayidx to ptr636 %2 = tail call <vscale x 1 x double> @llvm.riscv.vle.nxv1f64.i64(<vscale x 1 x double> poison, ptr %1, i64 %0)637 %arrayidx1 = getelementptr inbounds double, ptr %b, i64 %i.014638 %3 = bitcast ptr %arrayidx1 to ptr639 %4 = tail call <vscale x 1 x double> @llvm.riscv.vle.nxv1f64.i64(<vscale x 1 x double> poison, ptr %3, i64 %0)640 %5 = tail call <vscale x 1 x double> @llvm.riscv.vfadd.nxv1f64.nxv1f64.i64(<vscale x 1 x double> poison, <vscale x 1 x double> %2, <vscale x 1 x double> %4, i64 7, i64 %0)641 %arrayidx2 = getelementptr inbounds double, ptr %c, i64 %i.014642 %6 = bitcast ptr %arrayidx2 to ptr643 tail call void @llvm.riscv.vse.nxv1f64.i64(<vscale x 1 x double> %5, ptr %6, i64 %0)644 %add = add nuw nsw i64 %i.014, %0645 %cmp = icmp slt i64 %add, %N646 br i1 %cmp, label %for.body, label %for.end647 648for.end: ; preds = %for.body, %entry649 ret void650}651 652; A single vector store in the loop with VL controlled by VLMAX653define void @vector_init_vlmax(i64 %N, ptr %c) {654; CHECK-LABEL: vector_init_vlmax:655; CHECK: # %bb.0: # %entry656; CHECK-NEXT: blez a0, .LBB13_3657; CHECK-NEXT: # %bb.1: # %for.body.preheader658; CHECK-NEXT: li a2, 0659; CHECK-NEXT: vsetvli a3, zero, e64, m1, ta, ma660; CHECK-NEXT: slli a4, a3, 3661; CHECK-NEXT: vmv.v.i v8, 0662; CHECK-NEXT: .LBB13_2: # %for.body663; CHECK-NEXT: # =>This Inner Loop Header: Depth=1664; CHECK-NEXT: vse64.v v8, (a1)665; CHECK-NEXT: add a2, a2, a3666; CHECK-NEXT: add a1, a1, a4667; CHECK-NEXT: blt a2, a0, .LBB13_2668; CHECK-NEXT: .LBB13_3: # %for.end669; CHECK-NEXT: ret670entry:671 %0 = tail call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 0)672 %cmp13 = icmp sgt i64 %N, 0673 br i1 %cmp13, label %for.body, label %for.end674 675for.body: ; preds = %entry, %for.body676 %i.014 = phi i64 [ %add, %for.body ], [ 0, %entry ]677 %arrayidx2 = getelementptr inbounds double, ptr %c, i64 %i.014678 %addr = bitcast ptr %arrayidx2 to ptr679 tail call void @llvm.riscv.vse.nxv1f64.i64(<vscale x 1 x double> zeroinitializer, ptr %addr, i64 %0)680 %add = add nuw nsw i64 %i.014, %0681 %cmp = icmp slt i64 %add, %N682 br i1 %cmp, label %for.body, label %for.end683 684for.end: ; preds = %for.body, %entry685 ret void686}687 688; Same as above, but VL comes from user provided AVL value689define void @vector_init_vsetvli_N(i64 %N, ptr %c) {690; CHECK-LABEL: vector_init_vsetvli_N:691; CHECK: # %bb.0: # %entry692; CHECK-NEXT: blez a0, .LBB14_3693; CHECK-NEXT: # %bb.1: # %for.body.preheader694; CHECK-NEXT: li a2, 0695; CHECK-NEXT: vsetvli a3, a0, e64, m1, ta, ma696; CHECK-NEXT: slli a4, a3, 3697; CHECK-NEXT: vmv.v.i v8, 0698; CHECK-NEXT: .LBB14_2: # %for.body699; CHECK-NEXT: # =>This Inner Loop Header: Depth=1700; CHECK-NEXT: vse64.v v8, (a1)701; CHECK-NEXT: add a2, a2, a3702; CHECK-NEXT: add a1, a1, a4703; CHECK-NEXT: blt a2, a0, .LBB14_2704; CHECK-NEXT: .LBB14_3: # %for.end705; CHECK-NEXT: ret706entry:707 %0 = tail call i64 @llvm.riscv.vsetvli(i64 %N, i64 3, i64 0)708 %cmp13 = icmp sgt i64 %N, 0709 br i1 %cmp13, label %for.body, label %for.end710 711for.body: ; preds = %entry, %for.body712 %i.014 = phi i64 [ %add, %for.body ], [ 0, %entry ]713 %arrayidx2 = getelementptr inbounds double, ptr %c, i64 %i.014714 %addr = bitcast ptr %arrayidx2 to ptr715 tail call void @llvm.riscv.vse.nxv1f64.i64(<vscale x 1 x double> zeroinitializer, ptr %addr, i64 %0)716 %add = add nuw nsw i64 %i.014, %0717 %cmp = icmp slt i64 %add, %N718 br i1 %cmp, label %for.body, label %for.end719 720for.end: ; preds = %for.body, %entry721 ret void722}723 724; Same as above, but VL is a hard coded constant (in the preheader)725define void @vector_init_vsetvli_fv(i64 %N, ptr %c) {726; CHECK-LABEL: vector_init_vsetvli_fv:727; CHECK: # %bb.0: # %entry728; CHECK-NEXT: li a2, 0729; CHECK-NEXT: vsetivli a3, 4, e64, m1, ta, ma730; CHECK-NEXT: slli a4, a3, 3731; CHECK-NEXT: vmv.v.i v8, 0732; CHECK-NEXT: .LBB15_1: # %for.body733; CHECK-NEXT: # =>This Inner Loop Header: Depth=1734; CHECK-NEXT: vse64.v v8, (a1)735; CHECK-NEXT: add a2, a2, a3736; CHECK-NEXT: add a1, a1, a4737; CHECK-NEXT: blt a2, a0, .LBB15_1738; CHECK-NEXT: # %bb.2: # %for.end739; CHECK-NEXT: ret740entry:741 %0 = tail call i64 @llvm.riscv.vsetvli(i64 4, i64 3, i64 0)742 br label %for.body743 744for.body: ; preds = %entry, %for.body745 %i.014 = phi i64 [ %add, %for.body ], [ 0, %entry ]746 %arrayidx2 = getelementptr inbounds double, ptr %c, i64 %i.014747 %addr = bitcast ptr %arrayidx2 to ptr748 tail call void @llvm.riscv.vse.nxv1f64.i64(<vscale x 1 x double> zeroinitializer, ptr %addr, i64 %0)749 %add = add nuw nsw i64 %i.014, %0750 %cmp = icmp slt i64 %add, %N751 br i1 %cmp, label %for.body, label %for.end752 753for.end: ; preds = %for.body754 ret void755}756 757; Same as above, but result of vsetvli in preheader isn't used, and758; constant is repeated in loop759define void @vector_init_vsetvli_fv2(i64 %N, ptr %c) {760; CHECK-LABEL: vector_init_vsetvli_fv2:761; CHECK: # %bb.0: # %entry762; CHECK-NEXT: li a2, 0763; CHECK-NEXT: vsetivli zero, 4, e64, m1, ta, ma764; CHECK-NEXT: vmv.v.i v8, 0765; CHECK-NEXT: .LBB16_1: # %for.body766; CHECK-NEXT: # =>This Inner Loop Header: Depth=1767; CHECK-NEXT: vse64.v v8, (a1)768; CHECK-NEXT: addi a2, a2, 4769; CHECK-NEXT: addi a1, a1, 32770; CHECK-NEXT: blt a2, a0, .LBB16_1771; CHECK-NEXT: # %bb.2: # %for.end772; CHECK-NEXT: ret773entry:774 tail call i64 @llvm.riscv.vsetvli(i64 4, i64 3, i64 0)775 br label %for.body776 777for.body: ; preds = %entry, %for.body778 %i.014 = phi i64 [ %add, %for.body ], [ 0, %entry ]779 %arrayidx2 = getelementptr inbounds double, ptr %c, i64 %i.014780 %addr = bitcast ptr %arrayidx2 to ptr781 tail call void @llvm.riscv.vse.nxv1f64.i64(<vscale x 1 x double> zeroinitializer, ptr %addr, i64 4)782 %add = add nuw nsw i64 %i.014, 4783 %cmp = icmp slt i64 %add, %N784 br i1 %cmp, label %for.body, label %for.end785 786for.end: ; preds = %for.body787 ret void788}789 790; Same as above, but AVL is only specified on the store intrinsic791; This case will require some form of hoisting or PRE792define void @vector_init_vsetvli_fv3(i64 %N, ptr %c) {793; CHECK-LABEL: vector_init_vsetvli_fv3:794; CHECK: # %bb.0: # %entry795; CHECK-NEXT: li a2, 0796; CHECK-NEXT: vsetivli zero, 4, e64, m1, ta, ma797; CHECK-NEXT: vmv.v.i v8, 0798; CHECK-NEXT: .LBB17_1: # %for.body799; CHECK-NEXT: # =>This Inner Loop Header: Depth=1800; CHECK-NEXT: vse64.v v8, (a1)801; CHECK-NEXT: addi a2, a2, 4802; CHECK-NEXT: addi a1, a1, 32803; CHECK-NEXT: blt a2, a0, .LBB17_1804; CHECK-NEXT: # %bb.2: # %for.end805; CHECK-NEXT: ret806entry:807 br label %for.body808 809for.body: ; preds = %entry, %for.body810 %i.014 = phi i64 [ %add, %for.body ], [ 0, %entry ]811 %arrayidx2 = getelementptr inbounds double, ptr %c, i64 %i.014812 %addr = bitcast ptr %arrayidx2 to ptr813 tail call void @llvm.riscv.vse.nxv1f64.i64(<vscale x 1 x double> zeroinitializer, ptr %addr, i64 4)814 %add = add nuw nsw i64 %i.014, 4815 %cmp = icmp slt i64 %add, %N816 br i1 %cmp, label %for.body, label %for.end817 818for.end: ; preds = %for.body819 ret void820}821 822; Demonstrates a case where mutation in phase3 is problematic. We mutate the823; vsetvli without considering that it changes the compatibility result of the824; vadd in the second block.825define <vscale x 4 x i32> @cross_block_mutate(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b,826; CHECK-LABEL: cross_block_mutate:827; CHECK: # %bb.0: # %entry828; CHECK-NEXT: vsetivli a0, 6, e32, m2, tu, ma829; CHECK-NEXT: vmv.s.x v8, a0830; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma831; CHECK-NEXT: vadd.vv v8, v8, v10, v0.t832; CHECK-NEXT: ret833 <vscale x 4 x i1> %mask) {834entry:835 %vl = tail call i64 @llvm.riscv.vsetvli(i64 6, i64 1, i64 0)836 %vl.trunc = trunc i64 %vl to i32837 %a.mod = insertelement <vscale x 4 x i32> %a, i32 %vl.trunc, i32 0838 br label %fallthrough839 840fallthrough:841 %res = call <vscale x 4 x i32> @llvm.riscv.vadd.mask.nxv4i32.nxv4i32(842 <vscale x 4 x i32> poison, <vscale x 4 x i32> %a.mod,843 <vscale x 4 x i32> %b, <vscale x 4 x i1> %mask, i64 %vl, i64 0)844 ret <vscale x 4 x i32> %res845}846 847define <vscale x 2 x i32> @pre_lmul(<vscale x 2 x i32> %x, <vscale x 2 x i32> %y, i1 %cond) nounwind {848; CHECK-LABEL: pre_lmul:849; CHECK: # %bb.0: # %entry850; CHECK-NEXT: andi a0, a0, 1851; CHECK-NEXT: vsetvli a1, zero, e64, m1, ta, ma852; CHECK-NEXT: vsetvli zero, a1, e32, m1, ta, ma853; CHECK-NEXT: vadd.vv v8, v8, v9854; CHECK-NEXT: vadd.vv v8, v8, v9855; CHECK-NEXT: ret856entry:857 %vl = tail call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 0)858 %a = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %x, <vscale x 2 x i32> %y, i64 %vl)859 br i1 %cond, label %if, label %if.end860 861if:862 ; Deliberately change vtype - this could be an unknown call, but the broader863 ; code quality is distractingly bad864 tail call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 1)865 br label %if.end866 867if.end:868 %b = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %a, <vscale x 2 x i32> %y, i64 %vl)869 ret <vscale x 2 x i32> %b870}871 872define <vscale x 1 x double> @compat_store_consistency(i1 %cond, <vscale x 1 x double> %a, <vscale x 1 x double> %b, ptr %p1, <vscale x 1 x float> %c, ptr %p2) {873; CHECK-LABEL: compat_store_consistency:874; CHECK: # %bb.0: # %entry875; CHECK-NEXT: andi a0, a0, 1876; CHECK-NEXT: vsetvli a3, zero, e64, m1, ta, ma877; CHECK-NEXT: vfadd.vv v8, v8, v9878; CHECK-NEXT: vs1r.v v8, (a1)879; CHECK-NEXT: beqz a0, .LBB20_2880; CHECK-NEXT: # %bb.1: # %if.then881; CHECK-NEXT: vse32.v v10, (a2)882; CHECK-NEXT: .LBB20_2: # %if.end883; CHECK-NEXT: ret884entry:885 %res = fadd <vscale x 1 x double> %a, %b886 store <vscale x 1 x double> %res, ptr %p1887 br i1 %cond, label %if.then, label %if.end888 889if.then: ; preds = %entry890 store <vscale x 1 x float> %c, ptr %p2891 br label %if.end892 893if.end: ; preds = %if.else, %if.then894 ret <vscale x 1 x double> %res895}896 897; Next two tests (which are the same except for swapped block order), make sure that the898; demanded reasoning around vmv.s.x correctly handles a forward state with only a valid899; SEWLMULRatio. We previously had a crash bug in this case.900define <vscale x 2 x i32> @test_ratio_only_vmv_s_x(ptr %x, ptr %y, i1 %cond) nounwind {901; CHECK-LABEL: test_ratio_only_vmv_s_x:902; CHECK: # %bb.0: # %entry903; CHECK-NEXT: andi a2, a2, 1904; CHECK-NEXT: beqz a2, .LBB21_2905; CHECK-NEXT: # %bb.1: # %if906; CHECK-NEXT: vsetivli zero, 2, e16, mf2, ta, ma907; CHECK-NEXT: vle16.v v9, (a1)908; CHECK-NEXT: vwcvt.x.x.v v8, v9909; CHECK-NEXT: j .LBB21_3910; CHECK-NEXT: .LBB21_2:911; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma912; CHECK-NEXT: vle32.v v8, (a0)913; CHECK-NEXT: .LBB21_3: # %if.end914; CHECK-NEXT: vsetvli zero, zero, e32, m1, tu, ma915; CHECK-NEXT: vmv.s.x v8, zero916; CHECK-NEXT: ret917entry:918 %a = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32(<vscale x 2 x i32> poison, ptr %x, i64 2)919 br i1 %cond, label %if, label %if.end920 921if:922 %b = call <vscale x 2 x i16> @llvm.riscv.vle.nxv2i16(<vscale x 2 x i16> poison, ptr %y, i64 2)923 %c = call <vscale x 2 x i32> @llvm.riscv.vwadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i16> %b, i16 0, i64 2)924 br label %if.end925 926if.end:927 %d = phi <vscale x 2 x i32> [ %a, %entry ], [ %c, %if ]928 %e = insertelement <vscale x 2 x i32> %d, i32 0, i32 0929 ret <vscale x 2 x i32> %e930}931 932define <vscale x 2 x i32> @test_ratio_only_vmv_s_x2(ptr %x, ptr %y, i1 %cond) nounwind {933; CHECK-LABEL: test_ratio_only_vmv_s_x2:934; CHECK: # %bb.0: # %entry935; CHECK-NEXT: andi a2, a2, 1936; CHECK-NEXT: beqz a2, .LBB22_2937; CHECK-NEXT: # %bb.1: # %if938; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma939; CHECK-NEXT: vle32.v v8, (a0)940; CHECK-NEXT: j .LBB22_3941; CHECK-NEXT: .LBB22_2:942; CHECK-NEXT: vsetivli zero, 2, e16, mf2, ta, ma943; CHECK-NEXT: vle16.v v9, (a1)944; CHECK-NEXT: vwcvt.x.x.v v8, v9945; CHECK-NEXT: .LBB22_3: # %if.end946; CHECK-NEXT: vsetvli zero, zero, e32, m1, tu, ma947; CHECK-NEXT: vmv.s.x v8, zero948; CHECK-NEXT: ret949entry:950 %b = call <vscale x 2 x i16> @llvm.riscv.vle.nxv2i16(<vscale x 2 x i16> poison, ptr %y, i64 2)951 %c = call <vscale x 2 x i32> @llvm.riscv.vwadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i16> %b, i16 0, i64 2)952 br i1 %cond, label %if, label %if.end953 954if:955 %a = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32(<vscale x 2 x i32> poison, ptr %x, i64 2)956 br label %if.end957 958if.end:959 %d = phi <vscale x 2 x i32> [ %a, %if ], [ %c, %entry ]960 %e = insertelement <vscale x 2 x i32> %d, i32 0, i32 0961 ret <vscale x 2 x i32> %e962}963 964; This case demonstrates a PRE case where the first instruction in the block965; doesn't require a state transition.966define void @pre_over_vle(ptr %A) {967; CHECK-LABEL: pre_over_vle:968; CHECK: # %bb.0: # %entry969; CHECK-NEXT: addi a1, a0, 800970; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma971; CHECK-NEXT: .LBB23_1: # %vector.body972; CHECK-NEXT: # =>This Inner Loop Header: Depth=1973; CHECK-NEXT: vle8.v v8, (a0)974; CHECK-NEXT: vsext.vf4 v9, v8975; CHECK-NEXT: vse32.v v9, (a0)976; CHECK-NEXT: addi a0, a0, 8977; CHECK-NEXT: bne a0, a1, .LBB23_1978; CHECK-NEXT: # %bb.2: # %exit979; CHECK-NEXT: ret980entry:981 br label %vector.body982 983vector.body:984 %iv = phi i64 [ 0, %entry], [%iv.next, %vector.body]985 %addr = getelementptr inbounds <2 x i32>, ptr %A, i64 %iv986 %v = load <2 x i8>, ptr %addr987 %v2 = sext <2 x i8> %v to <2 x i32>988 store <2 x i32> %v2, ptr %addr989 %iv.next = add i64 %iv, 1990 %cmp = icmp ne i64 %iv.next, 100991 br i1 %cmp, label %vector.body, label %exit992exit:993 ret void994}995 996; Normally a pseudo's AVL is already live in its block, so it will already be997; live where we're inserting the vsetvli, before the pseudo. In some cases the998; AVL can be from a predecessor block, so make sure we extend its live range999; across blocks.1000define <vscale x 2 x i32> @cross_block_avl_extend(i64 %avl, <vscale x 2 x i32> %a, <vscale x 2 x i32> %b) {1001; CHECK-LABEL: cross_block_avl_extend:1002; CHECK: # %bb.0: # %entry1003; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma1004; CHECK-NEXT: vadd.vv v9, v8, v91005; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma1006; CHECK-NEXT: vadd.vv v8, v8, v91007; CHECK-NEXT: ret1008entry:1009 ; Get the output vl from a vsetvli1010 %vl = call i64 @llvm.riscv.vsetvli.i64(i64 %avl, i64 2, i64 0)1011 ; Force a vsetvli toggle so we need to insert a new vsetvli in exit1012 %d = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %a, <vscale x 2 x i32> %b, i64 1)1013 br label %exit1014exit:1015 ; The use of the vl from the vsetvli will be replaced with its %avl because1016 ; VLMAX is the same. So %avl, which was previously only live in %entry, will1017 ; need to be extended down toe %exit.1018 %c = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %a, <vscale x 2 x i32> %d, i64 %vl)1019 ret <vscale x 2 x i32> %c1020}1021 1022define void @cross_block_avl_extend_backwards(i1 %cond, <vscale x 8 x i8> %v, ptr %p, i64 %avl) {1023; CHECK-LABEL: cross_block_avl_extend_backwards:1024; CHECK: # %bb.0: # %entry1025; CHECK-NEXT: andi a0, a0, 11026; CHECK-NEXT: beqz a0, .LBB25_21027; CHECK-NEXT: # %bb.1: # %exit1028; CHECK-NEXT: ret1029; CHECK-NEXT: .LBB25_2: # %bar1030; CHECK-NEXT: addi a2, a2, 11031; CHECK-NEXT: .LBB25_3: # %foo1032; CHECK-NEXT: # =>This Inner Loop Header: Depth=11033; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma1034; CHECK-NEXT: vse8.v v8, (a1)1035; CHECK-NEXT: vsetvli zero, a2, e8, m1, ta, ma1036; CHECK-NEXT: vse8.v v8, (a1)1037; CHECK-NEXT: j .LBB25_31038entry:1039 br i1 %cond, label %exit, label %bar1040foo:1041 ; Force a vl toggle1042 call void @llvm.riscv.vse.nxv8i8.i64(<vscale x 8 x i8> %v, ptr %p, i64 1)1043 ; %add's LiveRange needs to be extended backwards to here.1044 call void @llvm.riscv.vse.nxv8i8.i64(<vscale x 8 x i8> %v, ptr %p, i64 %add)1045 br label %foo1046exit:1047 ret void1048bar:1049 %add = add i64 %avl, 11050 br label %foo1051}1052 1053define void @vlmax_avl_phi(i1 %cmp, ptr %p, i64 %a, i64 %b) {1054; CHECK-LABEL: vlmax_avl_phi:1055; CHECK: # %bb.0: # %entry1056; CHECK-NEXT: andi a0, a0, 11057; CHECK-NEXT: beqz a0, .LBB26_21058; CHECK-NEXT: # %bb.1: # %foo1059; CHECK-NEXT: vsetvli zero, a2, e8, m1, ta, ma1060; CHECK-NEXT: j .LBB26_31061; CHECK-NEXT: .LBB26_2: # %bar1062; CHECK-NEXT: vsetvli zero, a3, e8, m1, ta, ma1063; CHECK-NEXT: .LBB26_3: # %exit1064; CHECK-NEXT: vmv.v.i v8, 01065; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma1066; CHECK-NEXT: vse8.v v8, (a1)1067; CHECK-NEXT: ret1068entry:1069 br i1 %cmp, label %foo, label %bar1070 1071foo:1072 %vl.foo = tail call i64 @llvm.riscv.vsetvli.i64(i64 %a, i64 0, i64 0)1073 br label %exit1074 1075bar:1076 %vl.bar = tail call i64 @llvm.riscv.vsetvli.i64(i64 %b, i64 0, i64 0)1077 br label %exit1078 1079exit:1080 %phivl = phi i64 [ %vl.foo, %foo ], [ %vl.bar, %bar ]1081 %1 = tail call <vscale x 8 x i8> @llvm.riscv.vmv.v.x.nxv8i8.i64(<vscale x 8 x i8> poison, i8 0, i64 %phivl)1082 call void @llvm.riscv.vse.nxv8i8(<vscale x 8 x i8> %1, ptr %p, i64 1)1083 ret void1084}1085 1086; Check that if we forward an AVL whose value is clobbered in its LiveInterval1087; we emit a copy instead.1088define <vscale x 4 x i32> @clobbered_forwarded_avl(i64 %n, <vscale x 4 x i32> %v, i1 %cmp) {1089; CHECK-LABEL: clobbered_forwarded_avl:1090; CHECK: # %bb.0: # %entry1091; CHECK-NEXT: vsetvli zero, a0, e32, m2, ta, ma1092; CHECK-NEXT: andi a1, a1, 11093; CHECK-NEXT: .LBB27_1: # %for.body1094; CHECK-NEXT: # =>This Inner Loop Header: Depth=11095; CHECK-NEXT: addi a0, a0, 11096; CHECK-NEXT: bnez a1, .LBB27_11097; CHECK-NEXT: # %bb.2: # %for.cond.cleanup1098; CHECK-NEXT: vadd.vv v10, v8, v81099; CHECK-NEXT: vadd.vv v8, v10, v81100; CHECK-NEXT: ret1101entry:1102 %0 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %n, i64 2, i64 1)1103 br label %for.body1104 1105for.body:1106 ; Use %n in a PHI here so its virtual register is assigned to a second time here.1107 %1 = phi i64 [ %3, %for.body ], [ %n, %entry ]1108 %2 = tail call i64 @llvm.riscv.vsetvli.i64(i64 %1, i64 0, i64 0)1109 %3 = add i64 %1, 11110 br i1 %cmp, label %for.body, label %for.cond.cleanup1111 1112for.cond.cleanup:1113 %4 = tail call <vscale x 4 x i32> @llvm.riscv.vadd.nxv2f32.nxv2f32.i64(<vscale x 4 x i32> poison, <vscale x 4 x i32> %v, <vscale x 4 x i32> %v, i64 -1)1114 ; VL toggle needed here: If the %n AVL was forwarded here we wouldn't be able1115 ; to extend it's LiveInterval because it would clobber the assignment at %1.1116 %5 = tail call <vscale x 4 x i32> @llvm.riscv.vadd.nxv2f32.nxv2f32.i64(<vscale x 4 x i32> poison, <vscale x 4 x i32> %4, <vscale x 4 x i32> %v, i64 %0)1117 ret <vscale x 4 x i32> %51118}1119