Author: Chuanqi Xu Date: 2024-05-15T10:29:49+08:00 New Revision: 11b059145d177ee287c7ada9864addf8d083c160
URL: https://github.com/llvm/llvm-project/commit/11b059145d177ee287c7ada9864addf8d083c160 DIFF: https://github.com/llvm/llvm-project/commit/11b059145d177ee287c7ada9864addf8d083c160.diff LOG: [Serialization] Read the initializer for interesting static variables before consuming it Close https://github.com/llvm/llvm-project/issues/91418 Since we load the variable's initializers lazily, it'd be problematic if the initializers dependent on each other. So here we try to load the initializers of static variables to make sure they are passed to code generator by order. If we read any thing interesting, we would consume that before emitting the current declaration. Added: clang/test/Modules/pr91418.cppm Modified: clang/lib/Serialization/ASTReaderDecl.cpp Removed: ################################################################################ diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0c647086e304a..a6254b70560c3 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4186,12 +4186,35 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - Decl *D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque<Decl *> MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast<VarDecl>(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); if (isConsumerInterestedIn(D)) PassInterestingDeclToConsumer(D); } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm new file mode 100644 index 0000000000000..33fec992439d6 --- /dev/null +++ b/clang/test/Modules/pr91418.cppm @@ -0,0 +1,67 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -x c++-header %t/foo.h \ +// RUN: -emit-pch -o %t/foo.pch +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/use.cpp -include-pch \ +// RUN: %t/foo.pch -emit-llvm -o - | FileCheck %t/use.cpp + +//--- foo.h +#ifndef FOO_H +#define FOO_H +typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); + +static __inline__ __m128 __attribute__((__always_inline__, __min_vector_width__(128))) +_mm_setr_ps(float __z, float __y, float __x, float __w) +{ + return __extension__ (__m128){ __z, __y, __x, __w }; +} + +typedef __m128 VR; + +inline VR MakeVR( float X, float Y, float Z, float W ) +{ + return _mm_setr_ps( X, Y, Z, W ); +} + +extern "C" float sqrtf(float); + +namespace VectorSinConstantsSSE +{ + float a = (16 * sqrtf(0.225f)); + VR A = MakeVR(a, a, a, a); + static const float b = (16 * sqrtf(0.225f)); + static const VR B = MakeVR(b, b, b, b); +} + +#endif // FOO_H + +//--- use.cpp +#include "foo.h" +float use() { + return VectorSinConstantsSSE::A[0] + VectorSinConstantsSSE::A[1] + + VectorSinConstantsSSE::A[2] + VectorSinConstantsSSE::A[3] + + VectorSinConstantsSSE::B[0] + VectorSinConstantsSSE::B[1] + + VectorSinConstantsSSE::B[2] + VectorSinConstantsSSE::B[3]; +} + +// CHECK: define{{.*}}@__cxx_global_var_init( +// CHECK: store{{.*}}[[a_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSE1aE + +// CHECK: define{{.*}}@__cxx_global_var_init.1( +// CHECK: [[A_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( +// CHECK: store{{.*}}[[A_CALL]], ptr @_ZN21VectorSinConstantsSSE1AE + +// CHECK: define{{.*}}@__cxx_global_var_init.2( +// CHECK: [[B_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVRffff( +// CHECK: store{{.*}}[[B_CALL]], ptr @_ZN21VectorSinConstantsSSEL1BE + +// CHECK: define{{.*}}@__cxx_global_var_init.3( +// CHECK: store{{.*}}[[b_RESULT:%[a-zA-Z0-9]+]], ptr @_ZN21VectorSinConstantsSSEL1bE + +// CHECK: @_GLOBAL__sub_I_use.cpp +// CHECK: call{{.*}}@__cxx_global_var_init( +// CHECK: call{{.*}}@__cxx_global_var_init.1( +// CHECK: call{{.*}}@__cxx_global_var_init.3( +// CHECK: call{{.*}}@__cxx_global_var_init.2( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits