diff --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h --- a/clang/lib/Headers/larchintrin.h +++ b/clang/lib/Headers/larchintrin.h @@ -14,6 +14,46 @@ extern "C" { #endif +typedef struct rdtime { + unsigned int value; + unsigned int timeid; +} __rdtime_t; + +#if __loongarch_grlen == 64 +typedef struct drdtime { + unsigned long dvalue; + unsigned long dtimeid; +} __drdtime_t; + +extern __inline __drdtime_t + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __rdtime_d(void) { + __drdtime_t __drdtime; + __asm__ volatile( + "rdtime.d %[val], %[tid]\n\t" + : [val] "=&r"(__drdtime.dvalue), [tid] "=&r"(__drdtime.dtimeid)); + return __drdtime; +} +#endif + +extern __inline __rdtime_t + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __rdtimeh_w(void) { + __rdtime_t __rdtime; + __asm__ volatile("rdtimeh.w %[val], %[tid]\n\t" + : [val] "=&r"(__rdtime.value), [tid] "=&r"(__rdtime.timeid)); + return __rdtime; +} + +extern __inline __rdtime_t + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __rdtimel_w(void) { + __rdtime_t __rdtime; + __asm__ volatile("rdtimel.w %[val], %[tid]\n\t" + : [val] "=&r"(__rdtime.value), [tid] "=&r"(__rdtime.timeid)); + return __rdtime; +} + #if __loongarch_grlen == 64 extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c --- a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c +++ b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c @@ -111,3 +111,7 @@ void ldpte_d(long int a, int b) { __builtin_loongarch_ldpte_d(a, 1); // expected-error {{this builtin requires target: loongarch64}} } + +void rdtime_d() { + __rdtime_d(); // expected-error {{call to undeclared function '__rdtime_d'}} +} diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la32.c b/clang/test/CodeGen/LoongArch/intrinsic-la32.c --- a/clang/test/CodeGen/LoongArch/intrinsic-la32.c +++ b/clang/test/CodeGen/LoongArch/intrinsic-la32.c @@ -166,3 +166,14 @@ unsigned int c = __builtin_loongarch_cpucfg(a); return 0; } + +// LA32-LABEL: @rdtime( +// LA32-NEXT: entry: +// LA32-NEXT: [[TMP0:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimeh.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1:[0-9]+]], !srcloc !2 +// LA32-NEXT: [[TMP1:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimel.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc !3 +// LA32-NEXT: ret void +// +void rdtime() { + __rdtimeh_w(); + __rdtimel_w(); +} diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la64.c b/clang/test/CodeGen/LoongArch/intrinsic-la64.c --- a/clang/test/CodeGen/LoongArch/intrinsic-la64.c +++ b/clang/test/CodeGen/LoongArch/intrinsic-la64.c @@ -373,3 +373,23 @@ unsigned int c = __builtin_loongarch_cpucfg(a); return 0; } + +// CHECK-LABEL: @rdtime_d( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { i64, i64 } asm sideeffect "rdtime.d $0, $1\0A\09", "=&r,=&r"() #[[ATTR1:[0-9]+]], !srcloc !2 +// CHECK-NEXT: ret void +// +void rdtime_d() { + __rdtime_d(); +} + +// CHECK-LABEL: @rdtime( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimeh.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc !3 +// CHECK-NEXT: [[TMP1:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimel.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc !4 +// CHECK-NEXT: ret void +// +void rdtime() { + __rdtimeh_w(); + __rdtimel_w(); +}