CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
101 lines
5.1 KiB
C++
101 lines
5.1 KiB
C++
// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu -fno-threadsafe-statics -fclangir -emit-cir %s -o %t.cir
|
|
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
|
|
// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu -fno-threadsafe-statics -fclangir -emit-llvm %s -o %t-cir.ll
|
|
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM,LLVM-CIR
|
|
// RUN: %clang_cc1 -std=c++17 -triple aarch64-unknown-linux-gnu -fno-threadsafe-statics -emit-llvm %s -o %t.ll
|
|
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM,LLVM-OGCG
|
|
|
|
// On ARM-style targets (here, AArch64), function-scope static locals use the
|
|
// ARM ABI rule that only bit 0 of the guard is checked. The guard size depends
|
|
// on classic codegen's `useInt8GuardVariable = !threadsafe && hasInternalLinkage`
|
|
// (see ItaniumCXXABI::EmitGuardedInit). Both branches below are NYI in the CIR
|
|
// LoweringPrepare pass and currently fail; fill in the expected output once
|
|
// support is added.
|
|
|
|
int bar();
|
|
|
|
// `useInt8GuardVariable == true`: thread-safe statics are disabled and the
|
|
// guard for a non-inline function's static has internal linkage, so an i8
|
|
// guard byte is used.
|
|
void byte_guard() {
|
|
static int a = bar();
|
|
}
|
|
|
|
// CIR: cir.func {{.*}} @_Z10byte_guardv()
|
|
// CIR: %[[A:.*]] = cir.get_global static_local @_ZZ10byte_guardvE1a : !cir.ptr<!s32i>
|
|
// CIR: %[[GUARD:.*]] = cir.get_global @_ZGVZ10byte_guardvE1a : !cir.ptr<!s8i>
|
|
// CIR: %[[GUARD_LOAD:.*]] = cir.load{{.*}} %[[GUARD]]
|
|
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0>
|
|
// CIR: %[[IS_UNINIT:.*]] = cir.cmp eq %[[GUARD_LOAD]], %[[ZERO]]
|
|
// CIR: cir.if %[[IS_UNINIT]] {
|
|
// CIR: %[[A:.*]] = cir.get_global static_local @_ZZ10byte_guardvE1a : !cir.ptr<!s32i>
|
|
// CIR: %[[BAR:.*]] = cir.call @_Z3barv()
|
|
// CIR: cir.store{{.*}} %[[BAR]], %[[A]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s8i
|
|
// CIR: cir.store %[[ONE]], %[[GUARD]] : !s8i, !cir.ptr<!s8i>
|
|
// CIR: }
|
|
|
|
// LLVM: define {{.*}} void @_Z10byte_guardv()
|
|
// LLVM: %[[GUARD:.*]] = load i8, ptr @_ZGVZ10byte_guardvE1a
|
|
// LLVM: %[[IS_UNINIT:.*]] = icmp eq i8 %[[GUARD]], 0
|
|
// LLVM: br i1 %[[IS_UNINIT]], label %[[DO_INIT:.*]], label %[[DONE:[^,]+]]
|
|
// LLVM: [[DO_INIT]]:
|
|
// LLVM: %[[BAR:.*]] = call {{.*}} i32 @_Z3barv()
|
|
// LLVM: store i32 %[[BAR]], ptr @_ZZ10byte_guardvE1a
|
|
// LLVM: store i8 1, ptr @_ZGVZ10byte_guardvE1a
|
|
// LLVM: br label %[[DONE]]
|
|
// LLVM: [[DONE]]:
|
|
// LLVM: ret void
|
|
|
|
// `useInt8GuardVariable == false`: the static inside an inline function has
|
|
// linkonce_odr linkage, so the full ARM size-typed guard (i64 on AArch64) is
|
|
// used even with -fno-threadsafe-statics.
|
|
inline int word_guard() {
|
|
static int b = bar();
|
|
return b;
|
|
}
|
|
|
|
// CIR: cir.func {{.*}} @_Z10word_guardv()
|
|
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
|
|
// CIR: %[[B:.*]] = cir.get_global static_local @_ZZ10word_guardvE1b : !cir.ptr<!s32i>
|
|
// CIR: %[[GUARD:.*]] = cir.get_global @_ZGVZ10word_guardvE1b : !cir.ptr<!s64i>
|
|
// CIR: %[[GUARD_BYTE_PTR:.*]] = cir.cast bitcast %[[GUARD]] : !cir.ptr<!s64i> -> !cir.ptr<!s8i>
|
|
// CIR: %[[GUARD_LOAD:.*]] = cir.load{{.*}} %[[GUARD_BYTE_PTR]] : !cir.ptr<!s8i>, !s8i
|
|
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s8i
|
|
// CIR: %[[GUARD_AND:.*]] = cir.and %[[GUARD_LOAD]], %[[ONE]] : !s8i
|
|
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s8i
|
|
// CIR: %[[IS_UNINIT:.*]] = cir.cmp eq %[[GUARD_AND]], %[[ZERO]] : !s8i
|
|
// CIR: cir.if %[[IS_UNINIT]] {
|
|
// CIR: %[[B_TOO:.*]] = cir.get_global static_local @_ZZ10word_guardvE1b : !cir.ptr<!s32i>
|
|
// CIR: %[[BAR:.*]] = cir.call @_Z3barv()
|
|
// CIR: cir.store{{.*}} %[[BAR]], %[[B_TOO]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
|
|
// CIR: cir.store %[[ONE]], %[[GUARD]] : !s64i, !cir.ptr<!s64i>
|
|
// CIR: }
|
|
// CIR: %[[LOAD_B:.*]] = cir.load{{.*}} %[[B]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR: cir.store %[[LOAD_B]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR: %[[LOAD_RETVAL:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR: cir.return %[[LOAD_RETVAL]] : !s32i
|
|
|
|
// Note: The guard variable is a 64-bit value, but the load and truncate of
|
|
// that value gets folded to an 8-byte-aligned i8 load on both LLVM via
|
|
// CIR and OGCG, while the store of the value only gets folded in OGCG.
|
|
|
|
// LLVM: define {{.*}} i32 @_Z10word_guardv()
|
|
// LLVM: %[[GUARD:.*]] = load i8, ptr @_ZGVZ10word_guardvE1b, align 8
|
|
// LLVM: %[[GUARD_AND:.*]] = and i8 %[[GUARD]], 1
|
|
// LLVM: %[[IS_UNINIT:.*]] = icmp eq i8 %[[GUARD_AND]], 0
|
|
// LLVM: br i1 %[[IS_UNINIT]], label %[[DO_INIT:.*]], label %[[DONE:[^,]+]]
|
|
// LLVM: [[DO_INIT]]:
|
|
// LLVM: %[[BAR:.*]] = call {{.*}} i32 @_Z3barv()
|
|
// LLVM: store i32 %[[BAR]], ptr @_ZZ10word_guardvE1b
|
|
// LLVM-CIR: store i64 1, ptr @_ZGVZ10word_guardvE1b, align 8
|
|
// LLVM-OGCG: store i8 1, ptr @_ZGVZ10word_guardvE1b, align 8
|
|
// LLVM: br label %[[DONE]]
|
|
// LLVM: [[DONE]]:
|
|
// LLVM: %[[LOAD_B:.*]] = load i32, ptr @_ZZ10word_guardvE1b
|
|
// LLVM: ret i32 %{{.*}}
|
|
|
|
// This is just here to trigger the emission of word_guard().
|
|
int call_word_guard() { return word_guard(); }
|