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