llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-risc-v Author: Hank Chang (HankChang736) <details> <summary>Changes</summary> This patch use the hook getClobbers() in RISCV target and mark {vl, type} as clobber to prevent Post-RA scheduler moving vsetvl across inline assembly. Fixing [#<!-- -->97794](https://github.com/llvm/llvm-project/pull/97794). --- Full diff: https://github.com/llvm/llvm-project/pull/128636.diff 6 Files Affected: - (modified) clang/lib/Basic/Targets/RISCV.h (+1-1) - (modified) clang/test/CodeGen/RISCV/riscv-inline-asm-clobber.c (+36-12) - (modified) clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c (+4-4) - (modified) clang/test/CodeGen/RISCV/riscv-inline-asm.c (+21-21) - (added) llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm-clobber.ll (+37) - (added) llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm.ll (+37) ``````````diff diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index c26aa19080162..5590aa9d03c75 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -68,7 +68,7 @@ class RISCVTargetInfo : public TargetInfo { return TargetInfo::VoidPtrBuiltinVaList; } - std::string_view getClobbers() const override { return ""; } + std::string_view getClobbers() const override { return "~{vl},~{vtype}"; } StringRef getConstraintRegister(StringRef Constraint, StringRef Expression) const override { diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm-clobber.c b/clang/test/CodeGen/RISCV/riscv-inline-asm-clobber.c index 8aa80386f205f..65cfc081fe26d 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm-clobber.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm-clobber.c @@ -7,38 +7,62 @@ // Test RISC-V specific clobbered registers in inline assembly. -// CHECK-LABEL: define {{.*}} void @test_fflags -// CHECK: tail call void asm sideeffect "", "~{fflags}"() +// CHECK-LABEL: define dso_local void @test_fflags( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "", "~{fflags},~{vl},~{vtype}"() #[[ATTR1:[0-9]+]], !srcloc [[META6:![0-9]+]] +// CHECK-NEXT: ret void +// void test_fflags(void) { asm volatile ("" :::"fflags"); } -// CHECK-LABEL: define {{.*}} void @test_frm -// CHECK: tail call void asm sideeffect "", "~{frm}"() +// CHECK-LABEL: define dso_local void @test_frm( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "", "~{frm},~{vl},~{vtype}"() #[[ATTR1]], !srcloc [[META7:![0-9]+]] +// CHECK-NEXT: ret void +// void test_frm(void) { asm volatile ("" :::"frm"); } -// CHECK-LABEL: define {{.*}} void @test_vtype -// CHECK: tail call void asm sideeffect "", "~{vtype}"() +// CHECK-LABEL: define dso_local void @test_vtype( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "", "~{vtype},~{vl},~{vtype}"() #[[ATTR1]], !srcloc [[META8:![0-9]+]] +// CHECK-NEXT: ret void +// void test_vtype(void) { asm volatile ("" :::"vtype"); } -// CHECK-LABEL: define {{.*}} void @test_vl -// CHECK: tail call void asm sideeffect "", "~{vl}"() +// CHECK-LABEL: define dso_local void @test_vl( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "", "~{vl},~{vl},~{vtype}"() #[[ATTR1]], !srcloc [[META9:![0-9]+]] +// CHECK-NEXT: ret void +// void test_vl(void) { asm volatile ("" :::"vl"); } -// CHECK-LABEL: define {{.*}} void @test_vxsat -// CHECK: tail call void asm sideeffect "", "~{vxsat}"() +// CHECK-LABEL: define dso_local void @test_vxsat( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "", "~{vxsat},~{vl},~{vtype}"() #[[ATTR1]], !srcloc [[META10:![0-9]+]] +// CHECK-NEXT: ret void +// void test_vxsat(void) { asm volatile ("" :::"vxsat"); } -// CHECK-LABEL: define {{.*}} void @test_vxrm -// CHECK: tail call void asm sideeffect "", "~{vxrm}"() +// CHECK-LABEL: define dso_local void @test_vxrm( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void asm sideeffect "", "~{vxrm},~{vl},~{vtype}"() #[[ATTR1]], !srcloc [[META11:![0-9]+]] +// CHECK-NEXT: ret void +// void test_vxrm(void) { asm volatile ("" :::"vxrm"); } diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c b/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c index 879fb1238d83a..e9444c6a76d87 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c @@ -18,12 +18,12 @@ void test_v_reg() { : : "v1", "x1"); // CHECK-LABEL: define{{.*}} @test_v_reg -// CHECK: "~{v1},~{x1}" +// CHECK: "~{v1},~{x1},~{vl},~{vtype}" } vint32m1_t test_vr(vint32m1_t a, vint32m1_t b) { // CHECK-LABEL: define{{.*}} @test_vr -// CHECK: %0 = tail call <vscale x 2 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr"(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) +// CHECK: %0 = tail call <vscale x 2 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vr,^vr,^vr,~{vl},~{vtype}"(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) vint32m1_t ret; asm volatile ("vadd.vv %0, %1, %2" : "=vr"(ret) : "vr"(a), "vr"(b)); return ret; @@ -31,7 +31,7 @@ vint32m1_t test_vr(vint32m1_t a, vint32m1_t b) { vint32m1_t test_vd(vint32m1_t a, vint32m1_t b) { // CHECK-LABEL: define{{.*}} @test_vd -// CHECK: %0 = tail call <vscale x 2 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vd,^vd"(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) +// CHECK: %0 = tail call <vscale x 2 x i32> asm sideeffect "vadd.vv $0, $1, $2", "=^vd,^vd,^vd,~{vl},~{vtype}"(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) vint32m1_t ret; asm volatile ("vadd.vv %0, %1, %2" : "=vd"(ret) : "vd"(a), "vd"(b)); return ret; @@ -39,7 +39,7 @@ vint32m1_t test_vd(vint32m1_t a, vint32m1_t b) { vbool1_t test_vm(vbool1_t a, vbool1_t b) { // CHECK-LABEL: define{{.*}} @test_vm -// CHECK: %0 = tail call <vscale x 64 x i1> asm sideeffect "vmand.mm $0, $1, $2", "=^vm,^vm,^vm"(<vscale x 64 x i1> %a, <vscale x 64 x i1> %b) +// CHECK: %0 = tail call <vscale x 64 x i1> asm sideeffect "vmand.mm $0, $1, $2", "=^vm,^vm,^vm,~{vl},~{vtype}"(<vscale x 64 x i1> %a, <vscale x 64 x i1> %b) vbool1_t ret; asm volatile ("vmand.mm %0, %1, %2" : "=vm"(ret) : "vm"(a), "vm"(b)); return ret; diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index f2031e0adcbcb..1a8ccb7ea5a68 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -7,17 +7,17 @@ long test_r(long x) { // CHECK-LABEL: define{{.*}} {{i64|i32}} @test_r( -// CHECK: call {{i64|i32}} asm sideeffect "", "=r,r"({{i64|i32}} %{{.*}}) +// CHECK: call {{i64|i32}} asm sideeffect "", "=r,r,~{vl},~{vtype}"({{i64|i32}} %{{.*}}) long ret; asm volatile ("" : "=r"(ret) : "r"(x)); -// CHECK: call {{i64|i32}} asm sideeffect "", "=r,r"({{i64|i32}} %{{.*}}) +// CHECK: call {{i64|i32}} asm sideeffect "", "=r,r,~{vl},~{vtype}"({{i64|i32}} %{{.*}}) asm volatile ("" : "=r"(ret) : "r"(x)); return ret; } long test_cr(long x) { // CHECK-LABEL: define{{.*}} {{i64|i32}} @test_cr( -// CHECK: call {{i64|i32}} asm sideeffect "", "=^cr,^cr"({{i64|i32}} %{{.*}}) +// CHECK: call {{i64|i32}} asm sideeffect "", "=^cr,^cr,~{vl},~{vtype}"({{i64|i32}} %{{.*}}) long ret; asm volatile ("" : "=cr"(ret) : "cr"(x)); return ret; @@ -27,9 +27,9 @@ float cf; double cd; void test_cf(float f, double d) { // CHECK-LABEL: define{{.*}} void @test_cf( -// CHECK: call float asm sideeffect "", "=^cf,^cf"(float %{{.*}}) +// CHECK: call float asm sideeffect "", "=^cf,^cf,~{vl},~{vtype}"(float %{{.*}}) asm volatile("" : "=cf"(cf) : "cf"(f)); -// CHECK: call double asm sideeffect "", "=^cf,^cf"(double %{{.*}}) +// CHECK: call double asm sideeffect "", "=^cf,^cf,~{vl},~{vtype}"(double %{{.*}}) asm volatile("" : "=cf"(cd) : "cf"(d)); } @@ -40,7 +40,7 @@ typedef __int128_t double_xlen_t; #endif double_xlen_t test_R_wide_scalar(double_xlen_t p) { // CHECK-LABEL: define{{.*}} {{i128|i64}} @test_R_wide_scalar( -// CHECK: call {{i128|i64}} asm sideeffect "", "=R,R"({{i128|i64}} %{{.*}}) +// CHECK: call {{i128|i64}} asm sideeffect "", "=R,R,~{vl},~{vtype}"({{i128|i64}} %{{.*}}) double_xlen_t ret; asm volatile("" : "=R"(ret) : "R"(p)); return ret; @@ -48,7 +48,7 @@ double_xlen_t test_R_wide_scalar(double_xlen_t p) { double_xlen_t test_cR_wide_scalar(double_xlen_t p) { // CHECK-LABEL: define{{.*}} {{i128|i64}} @test_cR_wide_scalar( -// CHECK: call {{i128|i64}} asm sideeffect "", "=^cR,^cR"({{i128|i64}} %{{.*}}) +// CHECK: call {{i128|i64}} asm sideeffect "", "=^cR,^cR,~{vl},~{vtype}"({{i128|i64}} %{{.*}}) double_xlen_t ret; asm volatile("" : "=cR"(ret) : "cR"(p)); return ret; @@ -56,23 +56,23 @@ double_xlen_t test_cR_wide_scalar(double_xlen_t p) { void test_I(void) { // CHECK-LABEL: define{{.*}} void @test_I() -// CHECK: call void asm sideeffect "", "I"(i32 2047) +// CHECK: call void asm sideeffect "", "I,~{vl},~{vtype}"(i32 2047) asm volatile ("" :: "I"(2047)); -// CHECK: call void asm sideeffect "", "I"(i32 -2048) +// CHECK: call void asm sideeffect "", "I,~{vl},~{vtype}"(i32 -2048) asm volatile ("" :: "I"(-2048)); } void test_J(void) { // CHECK-LABEL: define{{.*}} void @test_J() -// CHECK: call void asm sideeffect "", "J"(i32 0) +// CHECK: call void asm sideeffect "", "J,~{vl},~{vtype}"(i32 0) asm volatile ("" :: "J"(0)); } void test_K(void) { // CHECK-LABEL: define{{.*}} void @test_K() -// CHECK: call void asm sideeffect "", "K"(i32 31) +// CHECK: call void asm sideeffect "", "K,~{vl},~{vtype}"(i32 31) asm volatile ("" :: "K"(31)); -// CHECK: call void asm sideeffect "", "K"(i32 0) +// CHECK: call void asm sideeffect "", "K,~{vl},~{vtype}"(i32 0) asm volatile ("" :: "K"(0)); } @@ -81,16 +81,16 @@ double d; void test_f(void) { // CHECK-LABEL: define{{.*}} void @test_f() // CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load float, ptr @f -// CHECK: call void asm sideeffect "", "f"(float [[FLT_ARG]]) +// CHECK: call void asm sideeffect "", "f,~{vl},~{vtype}"(float [[FLT_ARG]]) asm volatile ("" :: "f"(f)); // CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load double, ptr @d -// CHECK: call void asm sideeffect "", "f"(double [[FLT_ARG]]) +// CHECK: call void asm sideeffect "", "f,~{vl},~{vtype}"(double [[FLT_ARG]]) asm volatile ("" :: "f"(d)); } void test_A(int *p) { // CHECK-LABEL: define{{.*}} void @test_A(ptr noundef %p) -// CHECK: call void asm sideeffect "", "*A"(ptr elementtype(i32) %p) +// CHECK: call void asm sideeffect "", "*A,~{vl},~{vtype}"(ptr elementtype(i32) %p) asm volatile("" :: "A"(*p)); } @@ -98,9 +98,9 @@ extern int var, arr[2][2]; struct Pair { int a, b; } pair; // CHECK-LABEL: test_s( -// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds nuw (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) -// CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds nuw (i8, ptr @pair, {{.*}})) -// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds nuw (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s,~{vl},~{vtype}"(ptr nonnull @var, ptr nonnull getelementptr inbounds nuw (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0", "s,~{vl},~{vtype}"(ptr nonnull getelementptr inbounds nuw (i8, ptr @pair, {{.*}})) +// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S,~{vl},~{vtype}"(ptr nonnull @var, ptr nonnull getelementptr inbounds nuw (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) void test_s(void) { asm("// %0 %1 %2" :: "s"(&var), "s"(&arr[1][1]), "s"(test_s)); asm("// %0" :: "s"(&pair.b)); @@ -109,9 +109,9 @@ void test_s(void) { } // CHECK-LABEL: test_modifiers( -// CHECK: call void asm sideeffect "// ${0:i} ${1:i}", "r,r"({{i32|i64}} %val, i32 37) -// CHECK: call void asm sideeffect "// ${0:z} ${1:z}", "i,i"(i32 0, i32 1) -// CHECK: call void asm sideeffect "// ${0:N}", "r"({{i32|i64}} %val) +// CHECK: call void asm sideeffect "// ${0:i} ${1:i}", "r,r,~{vl},~{vtype}"({{i32|i64}} %val, i32 37) +// CHECK: call void asm sideeffect "// ${0:z} ${1:z}", "i,i,~{vl},~{vtype}"(i32 0, i32 1) +// CHECK: call void asm sideeffect "// ${0:N}", "r,~{vl},~{vtype}"({{i32|i64}} %val) void test_modifiers(long val) { asm volatile("// %i0 %i1" :: "r"(val), "r"(37)); asm volatile("// %z0 %z1" :: "i"(0), "i"(1)); diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm-clobber.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm-clobber.ll new file mode 100644 index 0000000000000..75d8b4c5437b1 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm-clobber.ll @@ -0,0 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -verify-machineinstrs < %s | FileCheck %s + +define void @foo(<vscale x 8 x half> %0, <vscale x 8 x half> %1) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vmv.v.i v12, 0 +; CHECK-NEXT: lui a0, 1 +; CHECK-NEXT: addiw a0, a0, -1096 +; CHECK-NEXT: vmv.v.i v16, 0 +; CHECK-NEXT: vsetvli zero, a0, e8, m1, ta, ma +; CHECK-NEXT: #APP +; CHECK-NEXT: vfmadd.vv v16, v12, v12 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: vfmadd.vv v16, v12, v12 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vsetvli zero, a0, e16, m2, ta, ma +; CHECK-NEXT: vse16.v v8, (zero) +; CHECK-NEXT: ret +entry: + %2 = tail call i64 @llvm.riscv.vsetvli.i64(i64 3000, i64 0, i64 0) + %3 = tail call <vscale x 8 x float> asm sideeffect "vfmadd.vv $0, $1, $2", "=^vr,^vr,^vr,0,~{vl},~{vtype}"(<vscale x 8 x float> zeroinitializer, <vscale x 8 x float> zeroinitializer, <vscale x 8 x float> zeroinitializer) + %4 = tail call <vscale x 8 x float> asm sideeffect "vfmadd.vv $0, $1, $2", "=^vr,^vr,^vr,0,~{vl},~{vtype}"(<vscale x 8 x float> zeroinitializer, <vscale x 8 x float> zeroinitializer, <vscale x 8 x float> %3) + tail call void @llvm.riscv.vse.nxv8f16.i64(<vscale x 8 x half> %0, ptr null, i64 %2) + ret void +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare i64 @llvm.riscv.vsetvli.i64(i64, i64 immarg, i64 immarg) #0 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: write) +declare void @llvm.riscv.vse.nxv8f16.i64(<vscale x 8 x half>, ptr nocapture, i64) #1 + +attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) } +attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) } diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm.ll b/llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm.ll new file mode 100644 index 0000000000000..e60ce90d5ed8b --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm.ll @@ -0,0 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -verify-machineinstrs < %s | FileCheck %s + +define void @foo(<vscale x 8 x half> %0, <vscale x 8 x half> %1) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vmv.v.i v12, 0 +; CHECK-NEXT: lui a0, 1 +; CHECK-NEXT: addiw a0, a0, -1096 +; CHECK-NEXT: vmv.v.i v16, 0 +; CHECK-NEXT: vsetvli zero, a0, e8, m1, ta, ma +; CHECK-NEXT: #APP +; CHECK-NEXT: vfmadd.vv v16, v12, v12 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vsetvli zero, a0, e16, m2, ta, ma +; CHECK-NEXT: #APP +; CHECK-NEXT: vfmadd.vv v16, v12, v12 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vse16.v v8, (zero) +; CHECK-NEXT: ret +entry: + %2 = tail call i64 @llvm.riscv.vsetvli.i64(i64 3000, i64 0, i64 0) + %3 = tail call <vscale x 8 x float> asm sideeffect "vfmadd.vv $0, $1, $2", "=^vr,^vr,^vr,0"(<vscale x 8 x float> zeroinitializer, <vscale x 8 x float> zeroinitializer, <vscale x 8 x float> zeroinitializer) + %4 = tail call <vscale x 8 x float> asm sideeffect "vfmadd.vv $0, $1, $2", "=^vr,^vr,^vr,0"(<vscale x 8 x float> zeroinitializer, <vscale x 8 x float> zeroinitializer, <vscale x 8 x float> %3) + tail call void @llvm.riscv.vse.nxv8f16.i64(<vscale x 8 x half> %0, ptr null, i64 %2) + ret void +} + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none) +declare i64 @llvm.riscv.vsetvli.i64(i64, i64 immarg, i64 immarg) #0 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: write) +declare void @llvm.riscv.vse.nxv8f16.i64(<vscale x 8 x half>, ptr nocapture, i64) #1 + +attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) } +attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: write) } `````````` </details> https://github.com/llvm/llvm-project/pull/128636 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits