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 186a3cbdcfe11f98e64f64636a6c6eafadc18937 Mon Sep 17 00:00:00 2001
From: Pincheng Wang <[email protected]>
Date: Thu, 4 Jun 2026 22:51:04 +0800
Subject: [PATCH 3/4] [Clang][OpenMP] Fix formatting and tighten declare-simd
 test checks

- CGOpenMPRuntime.cpp: align the continuation of the BuiltinID lib-function
  check and drop trailing whitespace flagged by `git diff --check`.
- declare_simd_preserve_builtin.cpp: terminate the file with a newline.
- declare_simd_inaccessiblemem.c: make the sincos CHECK-NOT match the
  specific `memory(inaccessiblemem...)` effect we are guarding against, so
  the test does not start failing once an unrelated `memory(...)` attribute
  is added on sincos in the future.
---
 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 f8b910166186fad640b51720ca06b6fdd5c109ee Mon Sep 17 00:00:00 2001
From: Pincheng Wang <[email protected]>
Date: Thu, 4 Jun 2026 23:02:45 +0800
Subject: [PATCH 4/4] [Clang][OpenMP] Apply clang-format to declare-simd
 codegen changes

- Reorder the llvm/IR/{VFABIDemangler,Value}.h includes alphabetically.
- Reflow getOrInsertFunction call and shouldEmitDeclareSimdVariantMetadata
  call to match what `git clang-format` produces on the touched lines.
---
 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