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