xref: /llvm-project/clang/test/CodeGen/RISCV/riscv-inline-asm.c (revision 33c44074714d1d2f3d5f65c3fb842cddb6b689ac)
1 // RUN: %clang_cc1 -triple riscv32 -O2 -emit-llvm %s -o - \
2 // RUN:     | FileCheck %s
3 // RUN: %clang_cc1 -triple riscv64 -O2 -emit-llvm %s -o - \
4 // RUN:     | FileCheck %s
5 
6 // Test RISC-V specific inline assembly constraints and modifiers.
7 
8 long test_r(long x) {
9 // CHECK-LABEL: define{{.*}} {{i64|i32}} @test_r(
10 // CHECK: call {{i64|i32}} asm sideeffect "", "=r,r"({{i64|i32}} %{{.*}})
11   long ret;
12   asm volatile ("" : "=r"(ret) : "r"(x));
13 // CHECK: call {{i64|i32}} asm sideeffect "", "=r,r"({{i64|i32}} %{{.*}})
14   asm volatile ("" : "=r"(ret) : "r"(x));
15   return ret;
16 }
17 
18 long test_cr(long x) {
19 // CHECK-LABEL: define{{.*}} {{i64|i32}} @test_cr(
20 // CHECK: call {{i64|i32}} asm sideeffect "", "=^cr,^cr"({{i64|i32}} %{{.*}})
21   long ret;
22   asm volatile ("" : "=cr"(ret) : "cr"(x));
23   return ret;
24 }
25 
26 float cf;
27 double cd;
28 void test_cf(float f, double d) {
29 // CHECK-LABEL: define{{.*}} void @test_cf(
30 // CHECK: call float asm sideeffect "", "=^cf,^cf"(float %{{.*}})
31   asm volatile("" : "=cf"(cf) : "cf"(f));
32 // CHECK: call double asm sideeffect "", "=^cf,^cf"(double %{{.*}})
33   asm volatile("" : "=cf"(cd) : "cf"(d));
34 }
35 
36 #if __riscv_xlen == 32
37 typedef long long double_xlen_t;
38 #elif __riscv_xlen == 64
39 typedef __int128_t double_xlen_t;
40 #endif
41 double_xlen_t test_R_wide_scalar(double_xlen_t p) {
42 // CHECK-LABEL: define{{.*}} {{i128|i64}} @test_R_wide_scalar(
43 // CHECK: call {{i128|i64}} asm sideeffect "", "=R,R"({{i128|i64}} %{{.*}})
44   double_xlen_t ret;
45   asm volatile("" : "=R"(ret) : "R"(p));
46   return ret;
47 }
48 
49 double_xlen_t test_cR_wide_scalar(double_xlen_t p) {
50 // CHECK-LABEL: define{{.*}} {{i128|i64}} @test_cR_wide_scalar(
51 // CHECK: call {{i128|i64}} asm sideeffect "", "=^cR,^cR"({{i128|i64}} %{{.*}})
52   double_xlen_t ret;
53   asm volatile("" : "=cR"(ret) : "cR"(p));
54   return ret;
55 }
56 
57 void test_I(void) {
58 // CHECK-LABEL: define{{.*}} void @test_I()
59 // CHECK: call void asm sideeffect "", "I"(i32 2047)
60   asm volatile ("" :: "I"(2047));
61 // CHECK: call void asm sideeffect "", "I"(i32 -2048)
62   asm volatile ("" :: "I"(-2048));
63 }
64 
65 void test_J(void) {
66 // CHECK-LABEL: define{{.*}} void @test_J()
67 // CHECK: call void asm sideeffect "", "J"(i32 0)
68   asm volatile ("" :: "J"(0));
69 }
70 
71 void test_K(void) {
72 // CHECK-LABEL: define{{.*}} void @test_K()
73 // CHECK: call void asm sideeffect "", "K"(i32 31)
74   asm volatile ("" :: "K"(31));
75 // CHECK: call void asm sideeffect "", "K"(i32 0)
76   asm volatile ("" :: "K"(0));
77 }
78 
79 float f;
80 double d;
81 void test_f(void) {
82 // CHECK-LABEL: define{{.*}} void @test_f()
83 // CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load float, ptr @f
84 // CHECK: call void asm sideeffect "", "f"(float [[FLT_ARG]])
85   asm volatile ("" :: "f"(f));
86 // CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load double, ptr @d
87 // CHECK: call void asm sideeffect "", "f"(double [[FLT_ARG]])
88   asm volatile ("" :: "f"(d));
89 }
90 
91 void test_A(int *p) {
92 // CHECK-LABEL: define{{.*}} void @test_A(ptr noundef %p)
93 // CHECK: call void asm sideeffect "", "*A"(ptr elementtype(i32) %p)
94   asm volatile("" :: "A"(*p));
95 }
96 
97 extern int var, arr[2][2];
98 struct Pair { int a, b; } pair;
99 
100 // CHECK-LABEL: test_s(
101 // 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)
102 // CHECK:         call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds nuw (i8, ptr @pair, {{.*}}))
103 // 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)
104 void test_s(void) {
105   asm("// %0 %1 %2" :: "s"(&var), "s"(&arr[1][1]), "s"(test_s));
106   asm("// %0" :: "s"(&pair.b));
107 
108   asm("// %0 %1 %2" :: "S"(&var), "S"(&arr[1][1]), "S"(test_s));
109 }
110 
111 // CHECK-LABEL: test_modifiers(
112 // CHECK: call void asm sideeffect "// ${0:i} ${1:i}", "r,r"({{i32|i64}} %val, i32 37)
113 // CHECK: call void asm sideeffect "// ${0:z} ${1:z}", "i,i"(i32 0, i32 1)
114 // CHECK: call void asm sideeffect "// ${0:N}", "r"({{i32|i64}} %val)
115 void test_modifiers(long val) {
116   asm volatile("// %i0 %i1" :: "r"(val), "r"(37));
117   asm volatile("// %z0 %z1" :: "i"(0), "i"(1));
118   asm volatile("// %N0" :: "r"(val));
119 }
120