Skip to content

[RISCV] Mark {vl, vtype} as clobber in inline assembly #128636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -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}"; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::string_view getClobbers() const override { return "~{vl},~{vtype}"; }
std::string_view getClobbers() const override {
if (ISAInfo->hasExtension("zve32x"))
return "~{vl},~{vtype}";
return "";
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this implementation is better, just update it with your implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't work with the target attribute.


StringRef getConstraintRegister(StringRef Constraint,
StringRef Expression) const override {
Expand Down
48 changes: 36 additions & 12 deletions clang/test/CodeGen/RISCV/riscv-inline-asm-clobber.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
8 changes: 4 additions & 4 deletions clang/test/CodeGen/RISCV/riscv-inline-asm-rvv.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,28 @@ 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;
}

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;
}

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;
Expand Down
42 changes: 21 additions & 21 deletions clang/test/CodeGen/RISCV/riscv-inline-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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));
}

Expand All @@ -40,39 +40,39 @@ 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;
}

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;
}

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));
}

Expand All @@ -81,26 +81,26 @@ 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));
}

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));
Expand All @@ -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));
Expand Down
37 changes: 37 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm-clobber.ll
Original file line number Diff line number Diff line change
@@ -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) }
37 changes: 37 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv/vsetvl-cross-inline-asm.ll
Original file line number Diff line number Diff line change
@@ -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) }