[clang] [Serialization] Read the initializer for interesting static variables before consuming it (PR #92218)

2024-05-15 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 closed 
https://github.com/llvm/llvm-project/pull/92218
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Serialization] Read the initializer for interesting static variables before consuming it (PR #92218)

2024-05-15 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 edited 
https://github.com/llvm/llvm-project/pull/92218
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Serialization] Read the initializer for interesting static variables before consuming it (PR #92218)

2024-05-14 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-modules

Author: Chuanqi Xu (ChuanqiXu9)


Changes

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.

---

Patch is 28.54 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/92218.diff


3 Files Affected:

- (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+26-3) 
- (added) clang/test/Modules/pr91418.cppm (+67) 
- (modified) clang/test/OpenMP/nvptx_lambda_capturing.cpp (+123-123) 


``diff
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 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(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 ) {
diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm
new file mode 100644
index 0..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{{.*}}@_Z6MakeVR(
+// CHECK: store{{.*}}[[A_CALL]], ptr @_ZN21VectorSinConstantsSSE1AE
+
+// CHECK: define{{.*}}@__cxx_global_var_init.2(
+// CHECK: [[B_CALL:%[a-zA-Z0-9]+]] = call{{.*}}@_Z6MakeVR(
+// 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
+// 

[clang] [Serialization] Read the initializer for interesting static variables before consuming it (PR #92218)

2024-05-14 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 created 
https://github.com/llvm/llvm-project/pull/92218

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.

>From 699da64855f147708f153c30177a1d02a4e014f7 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Wed, 15 May 2024 12:37:16 +0800
Subject: [PATCH] [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.
---
 clang/lib/Serialization/ASTReaderDecl.cpp|  29 ++-
 clang/test/Modules/pr91418.cppm  |  67 +
 clang/test/OpenMP/nvptx_lambda_capturing.cpp | 246 +--
 3 files changed, 216 insertions(+), 126 deletions(-)
 create mode 100644 clang/test/Modules/pr91418.cppm

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 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(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 ) {
diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm
new file mode 100644
index 0..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