https://github.com/wpcwzy updated 
https://github.com/llvm/llvm-project/pull/193881

From a9fcb2faa6168d6259f1a29c9ec482823b36dee2 Mon Sep 17 00:00:00 2001
From: Pincheng Wang <[email protected]>
Date: Wed, 22 Apr 2026 22:30:19 +0800
Subject: [PATCH 1/4] clang: preserve declare-simd libcalls

---
 clang/lib/CodeGen/CGBuiltin.cpp               | 15 ++++
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 72 +++++++++++++++++++
 .../OpenMP/declare_simd_preserve_builtin.cpp  | 14 ++++
 3 files changed, 101 insertions(+)
 create mode 100644 clang/test/OpenMP/declare_simd_preserve_builtin.cpp

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da72a43643a54..b0abe0de56c19 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -28,6 +28,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Intrinsics.h"
@@ -69,6 +70,16 @@ static bool shouldEmitBuiltinAsIR(unsigned BuiltinID,
   return false;
 }
 
+static bool shouldPreserveLibCallForDeclareSimd(const FunctionDecl *FD,
+                                                const LangOptions &LangOpts) {
+  if (!FD || !LangOpts.OpenMP)
+    return false;
+
+  return llvm::any_of(FD->redecls(), [](const FunctionDecl *Redecl) {
+    return Redecl->hasAttr<OMPDeclareSimdDeclAttr>();
+  });
+}
+
 static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
                                         unsigned BuiltinID, const CallExpr *E,
                                         ReturnValueSlot ReturnValue,
@@ -2647,6 +2658,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
           BuiltinID, CGM.getTriple(), ErrnoOverriden, getLangOpts().MathErrno,
           OptNone, IsOptimizationEnabled);
 
+  if (GenerateFPMathIntrinsics &&
+      shouldPreserveLibCallForDeclareSimd(FD, getLangOpts()))
+    GenerateFPMathIntrinsics = false;
+
   if (GenerateFPMathIntrinsics) {
     switch (BuiltinIDIfNoAsmLabel) {
     case Builtin::BIacos:
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp 
b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index a8255ac74cfcf..5626836669761 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -36,6 +36,7 @@
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Value.h"
+#include "llvm/IR/VFABIDemangler.h"
 #include "llvm/Support/AtomicOrdering.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
@@ -11311,6 +11312,72 @@ emitX86DeclareSimdFunction(const FunctionDecl *FD, 
llvm::Function *Fn,
   }
 }
 
+static void emitDeclareSimdVariantMetadata(CodeGenModule &CGM,
+                                           llvm::Function *Fn) {
+  llvm::SmallVector<std::string, 8> VariantMappings;
+  for (llvm::Attribute Attr : Fn->getAttributes().getFnAttrs()) {
+    if (!Attr.isStringAttribute())
+      continue;
+
+    StringRef VariantName = Attr.getKindAsString();
+    if (!VariantName.starts_with("_ZGV"))
+      continue;
+
+    std::optional<llvm::VFInfo> Info =
+        llvm::VFABI::tryDemangleForVFABI(VariantName, Fn->getFunctionType());
+    if (!Info)
+      continue;
+
+    llvm::FunctionType *VectorTy =
+        llvm::VFABI::createFunctionType(*Info, Fn->getFunctionType());
+    llvm::Function *VecFn = llvm::cast<llvm::Function>(
+        Fn->getParent()->getOrInsertFunction(Info->VectorName, VectorTy)
+            .getCallee());
+    CGM.addCompilerUsedGlobal(VecFn);
+    VariantMappings.push_back(std::string(VariantName));
+  }
+
+  if (VariantMappings.empty())
+    return;
+
+  SmallString<256> Buffer;
+  llvm::raw_svector_ostream Out(Buffer);
+  for (const std::string &VariantName : VariantMappings)
+    Out << VariantName << ',';
+  Buffer.pop_back();
+
+  Fn->removeFnAttr(llvm::VFABI::MappingsAttrName);
+  Fn->addFnAttr(llvm::VFABI::MappingsAttrName, Buffer.str());
+}
+
+static bool shouldEmitDeclareSimdVariantMetadata(const FunctionDecl *FD,
+                                                 const SourceManager &SM) {
+  if (!FD)
+    return false;
+
+  for (const FunctionDecl *Redecl : FD->redecls()) {
+    if (!Redecl->hasAttr<OMPDeclareSimdDeclAttr>())
+      continue;
+
+    unsigned BuiltinID = Redecl->getBuiltinID();
+    if (BuiltinID &&
+      Redecl->getASTContext().BuiltinInfo.isLibFunction(BuiltinID))
+      return true;
+
+    SourceLocation Loc = SM.getExpansionLoc(Redecl->getLocation());
+    if (!Loc.isValid())
+      continue;
+      
+    // Keep support for library-style declarations coming from headers that are
+    // not marked as system headers (e.g. staged glibc build directories), but
+    // avoid enabling this for every non-main-file declaration.
+    if (!SM.isWrittenInMainFile(Loc) && Redecl->hasExternalFormalLinkage())
+      return true;
+  }
+
+  return false;
+}
+
 // This are the Functions that are needed to mangle the name of the
 // vector functions generated by the compiler, according to the rules
 // defined in the "Vector Function ABI specifications for AArch64",
@@ -11577,6 +11644,7 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const 
FunctionDecl *FD,
                                               llvm::Function *Fn) {
   ASTContext &C = CGM.getContext();
   FD = FD->getMostRecentDecl();
+  const FunctionDecl *MostRecentFD = FD;
   while (FD) {
     // Map params to their positions in function decl.
     llvm::DenseMap<const Decl *, unsigned> ParamPositions;
@@ -11724,6 +11792,10 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const 
FunctionDecl *FD,
     }
     FD = FD->getPreviousDecl();
   }
+
+  if (shouldEmitDeclareSimdVariantMetadata(
+          MostRecentFD, CGM.getContext().getSourceManager()))
+    emitDeclareSimdVariantMetadata(CGM, Fn);
 }
 
 namespace {
diff --git a/clang/test/OpenMP/declare_simd_preserve_builtin.cpp 
b/clang/test/OpenMP/declare_simd_preserve_builtin.cpp
new file mode 100644
index 0000000000000..e4452257a2537
--- /dev/null
+++ b/clang/test/OpenMP/declare_simd_preserve_builtin.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -ffast-math -fopenmp 
-emit-llvm %s -o - | FileCheck %s
+
+double sqrt(double);
+
+#pragma omp declare simd notinbranch
+double sqrt(double);
+
+double test(double x) {
+  return sqrt(x);
+}
+
+// CHECK-LABEL: define{{.*}}@_Z4testd(
+// CHECK: call{{.*}}@_Z4sqrtd(
+// CHECK-NOT: llvm.sqrt
\ No newline at end of file

From 9b1eed70c1225e95753e9bf1501e6d0fad293b86 Mon Sep 17 00:00:00 2001
From: Pincheng Wang <[email protected]>
Date: Thu, 4 Jun 2026 19:44:25 +0800
Subject: [PATCH 2/4] [Clang][OpenMP] Mark math declare-simd libcalls as
 InaccessibleMemOnly

When clang emits a libm math function declaration that carries a #pragma
omp declare simd, conservatively tighten its memory effects to
inaccessiblemem-only. These functions only touch the floating-point
environment (rounding mode, exceptions, errno reporting); they do not
read or write user-visible memory through their arguments.

Functions whose result is written back through a pointer (sincos, modf,
frexp, remquo, ...) are excluded so that their effect on user memory is
preserved. The set is identified by the existing builtin attribute
ConstIgnoringErrnoAndExceptions, with an additional guard that rejects
any builtin taking a pointer parameter.

This complements the loop-vectorizer changes for issue #120868 by
removing the false dependence edges that previously prevented OpenMP
SIMD loops containing standard math calls from being vectorized via
their VFABI mappings under -fmath-errno.
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 34 +++++++++++++++++++
 .../OpenMP/declare_simd_inaccessiblemem.c     | 21 ++++++++++++
 2 files changed, 55 insertions(+)
 create mode 100644 clang/test/OpenMP/declare_simd_inaccessiblemem.c

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp 
b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 5626836669761..653d146d3059b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -38,6 +38,7 @@
 #include "llvm/IR/Value.h"
 #include "llvm/IR/VFABIDemangler.h"
 #include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Support/ModRef.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdint>
@@ -11640,6 +11641,31 @@ static void emitAArch64DeclareSimdFunction(
   }
 }
 
+// Returns true if FD names a standard libm math builtin whose only side
+// effects are the floating-point environment (rounding mode, exceptions, and
+// any implementation-defined errno reporting). Functions that write results
+// back through pointer parameters (sincos, modf, frexp, remquo, ...) are
+// explicitly excluded so that we never weaken their memory effects.
+static bool shouldMarkInaccessibleMemOnlyForDeclareSimd(const FunctionDecl *FD,
+                                                        ASTContext &Ctx) {
+  if (!FD)
+    return false;
+  unsigned BuiltinID = FD->getBuiltinID();
+  if (!BuiltinID)
+    return false;
+  // ConstWithoutErrnoAndExceptions is set on the standard libm math builtins
+  // whose only side effects come from the floating-point environment
+  // (rounding mode, exceptions, errno reporting).
+  if (!Ctx.BuiltinInfo.isConstWithoutErrnoAndExceptions(BuiltinID))
+    return false;
+  // sincos-style functions take output pointers; their effects on user-visible
+  // memory cannot be modeled as inaccessible-memory-only.
+  for (const ParmVarDecl *P : FD->parameters())
+    if (P->getType()->isAnyPointerType())
+      return false;
+  return true;
+}
+
 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
                                               llvm::Function *Fn) {
   ASTContext &C = CGM.getContext();
@@ -11796,6 +11822,14 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const 
FunctionDecl *FD,
   if (shouldEmitDeclareSimdVariantMetadata(
           MostRecentFD, CGM.getContext().getSourceManager()))
     emitDeclareSimdVariantMetadata(CGM, Fn);
+
+  // Tighten memory effects for libm math functions that are otherwise modelled
+  // as may-access-any-memory. The vectorizer relies on this to avoid treating
+  // these calls as dependence-blocking memory accesses in OpenMP SIMD loops.
+  if (shouldMarkInaccessibleMemOnlyForDeclareSimd(MostRecentFD,
+                                                  CGM.getContext()))
+    Fn->setMemoryEffects(Fn->getMemoryEffects() &
+                         llvm::MemoryEffects::inaccessibleMemOnly());
 }
 
 namespace {
diff --git a/clang/test/OpenMP/declare_simd_inaccessiblemem.c 
b/clang/test/OpenMP/declare_simd_inaccessiblemem.c
new file mode 100644
index 0000000000000..eb9163183708b
--- /dev/null
+++ b/clang/test/OpenMP/declare_simd_inaccessiblemem.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -fopenmp -fmath-errno \
+// RUN:   -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
+
+// Verify that libm math builtins declared with #pragma omp declare simd get
+// memory(inaccessiblemem: readwrite). Functions that take output pointers
+// (e.g. sincos) must NOT be tightened, because they write through user memory.
+
+#pragma omp declare simd notinbranch
+double acosh(double);
+
+#pragma omp declare simd notinbranch linear(s) linear(c)
+void sincos(double, double *s, double *c);
+
+double test_acosh(double x) { return acosh(x); }
+void test_sincos(double x, double *s, double *c) { sincos(x, s, c); }
+
+// CHECK: declare double @acosh(double {{[^)]*}}) [[ACOSH_ATTR:#[0-9]+]]
+// CHECK: declare void @sincos(double {{[^)]*}}, ptr {{[^)]*}}, ptr {{[^)]*}}) 
[[SINCOS_ATTR:#[0-9]+]]
+
+// CHECK: attributes [[ACOSH_ATTR]] = { {{.*}}memory(inaccessiblemem: 
readwrite){{.*}} }
+// CHECK-NOT: attributes [[SINCOS_ATTR]] = { {{.*}}memory({{.*}} }

From b9d14a7a53732480836fbd7c99de8f0639c71cbf Mon Sep 17 00:00:00 2001
From: Pincheng Wang <[email protected]>
Date: Thu, 4 Jun 2026 23:16:17 +0800
Subject: [PATCH 3/4] [Clang][OpenMP] Tidy up declare-simd codegen and test
 nits

Realign the BuiltinID lib-function continuation in CGOpenMPRuntime.cpp and
drop the trailing whitespace git diff --check complained about.

Add the missing final newline to declare_simd_preserve_builtin.cpp.

The sincos CHECK-NOT in declare_simd_inaccessiblemem.c was matching any
memory(...) attribute, which would start firing if an unrelated memory
effect ever lands on the declaration. Narrow it to memory(inaccessiblemem
...) so the test only enforces what we actually care about.
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp               | 4 ++--
 clang/test/OpenMP/declare_simd_inaccessiblemem.c    | 2 +-
 clang/test/OpenMP/declare_simd_preserve_builtin.cpp | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp 
b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 653d146d3059b..6fd487caeaea2 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -11362,13 +11362,13 @@ static bool 
shouldEmitDeclareSimdVariantMetadata(const FunctionDecl *FD,
 
     unsigned BuiltinID = Redecl->getBuiltinID();
     if (BuiltinID &&
-      Redecl->getASTContext().BuiltinInfo.isLibFunction(BuiltinID))
+        Redecl->getASTContext().BuiltinInfo.isLibFunction(BuiltinID))
       return true;
 
     SourceLocation Loc = SM.getExpansionLoc(Redecl->getLocation());
     if (!Loc.isValid())
       continue;
-      
+
     // Keep support for library-style declarations coming from headers that are
     // not marked as system headers (e.g. staged glibc build directories), but
     // avoid enabling this for every non-main-file declaration.
diff --git a/clang/test/OpenMP/declare_simd_inaccessiblemem.c 
b/clang/test/OpenMP/declare_simd_inaccessiblemem.c
index eb9163183708b..da357e7bacddb 100644
--- a/clang/test/OpenMP/declare_simd_inaccessiblemem.c
+++ b/clang/test/OpenMP/declare_simd_inaccessiblemem.c
@@ -18,4 +18,4 @@ void test_sincos(double x, double *s, double *c) { sincos(x, 
s, c); }
 // CHECK: declare void @sincos(double {{[^)]*}}, ptr {{[^)]*}}, ptr {{[^)]*}}) 
[[SINCOS_ATTR:#[0-9]+]]
 
 // CHECK: attributes [[ACOSH_ATTR]] = { {{.*}}memory(inaccessiblemem: 
readwrite){{.*}} }
-// CHECK-NOT: attributes [[SINCOS_ATTR]] = { {{.*}}memory({{.*}} }
+// CHECK-NOT: attributes [[SINCOS_ATTR]] = { 
{{.*}}memory(inaccessiblemem{{.*}} }
diff --git a/clang/test/OpenMP/declare_simd_preserve_builtin.cpp 
b/clang/test/OpenMP/declare_simd_preserve_builtin.cpp
index e4452257a2537..7b6a808de13da 100644
--- a/clang/test/OpenMP/declare_simd_preserve_builtin.cpp
+++ b/clang/test/OpenMP/declare_simd_preserve_builtin.cpp
@@ -11,4 +11,4 @@ double test(double x) {
 
 // CHECK-LABEL: define{{.*}}@_Z4testd(
 // CHECK: call{{.*}}@_Z4sqrtd(
-// CHECK-NOT: llvm.sqrt
\ No newline at end of file
+// CHECK-NOT: llvm.sqrt

From a0eb3f97987fc3c8d271987841de53bad5d65894 Mon Sep 17 00:00:00 2001
From: Pincheng Wang <[email protected]>
Date: Thu, 4 Jun 2026 23:16:29 +0800
Subject: [PATCH 4/4] [Clang][OpenMP] clang-format declare-simd codegen

Sort llvm/IR/VFABIDemangler.h before llvm/IR/Value.h and reflow the
getOrInsertFunction call and the shouldEmitDeclareSimdVariantMetadata
call so the touched lines match git clang-format.
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp 
b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 6fd487caeaea2..ed5ccc5620e3d 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -35,8 +35,8 @@
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/InstrTypes.h"
-#include "llvm/IR/Value.h"
 #include "llvm/IR/VFABIDemangler.h"
+#include "llvm/IR/Value.h"
 #include "llvm/Support/AtomicOrdering.h"
 #include "llvm/Support/ModRef.h"
 #include "llvm/Support/raw_ostream.h"
@@ -11332,7 +11332,8 @@ static void 
emitDeclareSimdVariantMetadata(CodeGenModule &CGM,
     llvm::FunctionType *VectorTy =
         llvm::VFABI::createFunctionType(*Info, Fn->getFunctionType());
     llvm::Function *VecFn = llvm::cast<llvm::Function>(
-        Fn->getParent()->getOrInsertFunction(Info->VectorName, VectorTy)
+        Fn->getParent()
+            ->getOrInsertFunction(Info->VectorName, VectorTy)
             .getCallee());
     CGM.addCompilerUsedGlobal(VecFn);
     VariantMappings.push_back(std::string(VariantName));
@@ -11819,8 +11820,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const 
FunctionDecl *FD,
     FD = FD->getPreviousDecl();
   }
 
-  if (shouldEmitDeclareSimdVariantMetadata(
-          MostRecentFD, CGM.getContext().getSourceManager()))
+  if (shouldEmitDeclareSimdVariantMetadata(MostRecentFD,
+                                           
CGM.getContext().getSourceManager()))
     emitDeclareSimdVariantMetadata(CGM, Fn);
 
   // Tighten memory effects for libm math functions that are otherwise modelled

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to