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