https://github.com/AlexVlx created 
https://github.com/llvm/llvm-project/pull/234291

Creating constants at the point of observation / use can lead, in complex 
control-flow, to their referencing by previous instructions, which yields 
broken MIR. This change uses the dedicated interface to ensure that constants 
are always created in the entry block and thus dominate all uses. It is mostly 
NFC asides from tweaking tests that were order dependent. 

>From 3e0abe10c53e08cc1ebf16662d8d58cd7245f70f Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Thu, 15 May 2025 23:27:42 +0100
Subject: [PATCH 01/16] Add pass which forwards unimplemented math builtins /
 libcalls to the HIPSTDPAR runtime component.

---
 .../llvm/Transforms/HipStdPar/HipStdPar.h     |   7 +
 llvm/lib/Passes/PassRegistry.def              |   1 +
 .../lib/Target/AMDGPU/AMDGPUTargetMachine.cpp |   8 +-
 llvm/lib/Transforms/HipStdPar/HipStdPar.cpp   | 117 +++++++++
 llvm/test/Transforms/HipStdPar/math-fixup.ll  | 240 ++++++++++++++++++
 5 files changed, 371 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/Transforms/HipStdPar/math-fixup.ll

diff --git a/llvm/include/llvm/Transforms/HipStdPar/HipStdPar.h 
b/llvm/include/llvm/Transforms/HipStdPar/HipStdPar.h
index 5ff38bdf04812b..27195051ed7eb9 100644
--- a/llvm/include/llvm/Transforms/HipStdPar/HipStdPar.h
+++ b/llvm/include/llvm/Transforms/HipStdPar/HipStdPar.h
@@ -40,6 +40,13 @@ class HipStdParAllocationInterpositionPass
   static bool isRequired() { return true; }
 };
 
+class HipStdParMathFixupPass : public PassInfoMixin<HipStdParMathFixupPass> {
+public:
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+
+  static bool isRequired() { return true; }
+};
+
 } // namespace llvm
 
 #endif // LLVM_TRANSFORMS_HIPSTDPAR_HIPSTDPAR_H
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 94dabe290213dc..3acdbf4d49fdec 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -80,6 +80,7 @@ MODULE_PASS("global-merge-func", GlobalMergeFuncPass())
 MODULE_PASS("globalopt", GlobalOptPass())
 MODULE_PASS("globalsplit", GlobalSplitPass())
 MODULE_PASS("hipstdpar-interpose-alloc", 
HipStdParAllocationInterpositionPass())
+MODULE_PASS("hipstdpar-math-fixup", HipStdParMathFixupPass())
 MODULE_PASS("hipstdpar-select-accelerator-code",
             HipStdParAcceleratorCodeSelectionPass())
 MODULE_PASS("hotcoldsplit", HotColdSplittingPass())
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp 
b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
index ccb251b730f169..c3f8cee1e17832 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
@@ -819,8 +819,10 @@ void 
AMDGPUTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
           // When we are not using -fgpu-rdc, we can run accelerator code
           // selection relatively early, but still after linking to prevent
           // eager removal of potentially reachable symbols.
-          if (EnableHipStdPar)
+          if (EnableHipStdPar) {
+            PM.addPass(HipStdParMathFixupPass());
             PM.addPass(HipStdParAcceleratorCodeSelectionPass());
+          }
           PM.addPass(AMDGPUPrintfRuntimeBindingPass());
         }
 
@@ -899,8 +901,10 @@ void 
AMDGPUTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
         // selection after linking to prevent, otherwise we end up removing
         // potentially reachable symbols that were exported as external in 
other
         // modules.
-        if (EnableHipStdPar)
+        if (EnableHipStdPar) {
+          PM.addPass(HipStdParMathFixupPass());
           PM.addPass(HipStdParAcceleratorCodeSelectionPass());
+        }
         // We want to support the -lto-partitions=N option as "best effort".
         // For that, we need to lower LDS earlier in the pipeline before the
         // module is partitioned for codegen.
diff --git a/llvm/lib/Transforms/HipStdPar/HipStdPar.cpp 
b/llvm/lib/Transforms/HipStdPar/HipStdPar.cpp
index 5a87cf8c83d790..815878089c69ec 100644
--- a/llvm/lib/Transforms/HipStdPar/HipStdPar.cpp
+++ b/llvm/lib/Transforms/HipStdPar/HipStdPar.cpp
@@ -37,6 +37,16 @@
 //    memory that ends up in one of the runtime equivalents, since this can
 //    happen if e.g. a library that was compiled without interposition returns
 //    an allocation that can be validly passed to `free`.
+//
+// 3. MathFixup (required): Some accelerators might have an incomplete
+//    implementation for the intrinsics used to implement some of the math
+//    functions in <cmath> / their corresponding libcall lowerings. Since this
+//    can vary quite significantly between accelerators, we replace calls to a
+//    set of intrinsics / lib functions known to be problematic with calls to a
+//    HIPSTDPAR specific forwarding layer, which gives an uniform interface for
+//    accelerators to implement in their own runtime components. This pass
+//    should run before AcceleratorCodeSelection so as to prevent the spurious
+//    removal of the HIPSTDPAR specific forwarding functions.
 
//===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/HipStdPar/HipStdPar.h"
@@ -48,6 +58,7 @@
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 
@@ -321,3 +332,109 @@ HipStdParAllocationInterpositionPass::run(Module &M, 
ModuleAnalysisManager&) {
 
   return PreservedAnalyses::none();
 }
+
+static constexpr std::pair<StringLiteral, StringLiteral> MathLibToHipStdPar[]{
+    {"acosh", "__hipstdpar_acosh_f64"},
+    {"acoshf", "__hipstdpar_acosh_f32"},
+    {"asinh", "__hipstdpar_asinh_f64"},
+    {"asinhf", "__hipstdpar_asinh_f32"},
+    {"atanh", "__hipstdpar_atanh_f64"},
+    {"atanhf", "__hipstdpar_atanh_f32"},
+    {"cbrt", "__hipstdpar_cbrt_f64"},
+    {"cbrtf", "__hipstdpar_cbrt_f32"},
+    {"erf", "__hipstdpar_erf_f64"},
+    {"erff", "__hipstdpar_erf_f32"},
+    {"erfc", "__hipstdpar_erfc_f64"},
+    {"erfcf", "__hipstdpar_erfc_f32"},
+    {"fdim", "__hipstdpar_fdim_f64"},
+    {"fdimf", "__hipstdpar_fdim_f32"},
+    {"expm1", "__hipstdpar_expm1_f64"},
+    {"expm1f", "__hipstdpar_expm1_f32"},
+    {"hypot", "__hipstdpar_hypot_f64"},
+    {"hypotf", "__hipstdpar_hypot_f32"},
+    {"ilogb", "__hipstdpar_ilogb_f64"},
+    {"ilogbf", "__hipstdpar_ilogb_f32"},
+    {"lgamma", "__hipstdpar_lgamma_f64"},
+    {"lgammaf", "__hipstdpar_lgamma_f32"},
+    {"log1p", "__hipstdpar_log1p_f64"},
+    {"log1pf", "__hipstdpar_log1p_f32"},
+    {"logb", "__hipstdpar_logb_f64"},
+    {"logbf", "__hipstdpar_logb_f32"},
+    {"nextafter", "__hipstdpar_nextafter_f64"},
+    {"nextafterf", "__hipstdpar_nextafter_f32"},
+    {"nexttoward", "__hipstdpar_nexttoward_f64"},
+    {"nexttowardf", "__hipstdpar_nexttoward_f32"},
+    {"remainder", "__hipstdpar_remainder_f64"},
+    {"remainderf", "__hipstdpar_remainder_f32"},
+    {"remquo", "__hipstdpar_remquo_f64"},
+    {"remquof", "__hipstdpar_remquo_f32"},
+    {"scalbln", "__hipstdpar_scalbln_f64"},
+    {"scalblnf", "__hipstdpar_scalbln_f32"},
+    {"scalbn", "__hipstdpar_scalbn_f64"},
+    {"scalbnf", "__hipstdpar_scalbn_f32"},
+    {"tgamma", "__hipstdpar_tgamma_f64"},
+    {"tgammaf", "__hipstdpar_tgamma_f32"}};
+
+PreservedAnalyses HipStdParMathFixupPass::run(Module &M,
+                                              ModuleAnalysisManager &) {
+  if (M.empty())
+    return PreservedAnalyses::all();
+
+  SmallVector<std::pair<Function *, std::string>> ToReplace;
+  for (auto &&F : M) {
+    if (!F.hasName())
+      continue;
+
+    auto N = F.getName().str();
+    auto ID = F.getIntrinsicID();
+
+    switch (ID) {
+    case Intrinsic::not_intrinsic: {
+      auto It = find_if(MathLibToHipStdPar,
+                        [&](auto &&M) { return M.first == N; });
+      if (It == std::cend(MathLibToHipStdPar))
+        continue;
+      ToReplace.emplace_back(&F, It->second);
+      break;
+    }
+    case Intrinsic::acos:
+    case Intrinsic::asin:
+    case Intrinsic::atan:
+    case Intrinsic::atan2:
+    case Intrinsic::cosh:
+    case Intrinsic::modf:
+    case Intrinsic::sinh:
+    case Intrinsic::tan:
+    case Intrinsic::tanh:
+      break;
+    default: {
+      if (F.getReturnType()->isDoubleTy()) {
+        switch (ID) {
+        case Intrinsic::cos:
+        case Intrinsic::exp:
+        case Intrinsic::exp2:
+        case Intrinsic::log:
+        case Intrinsic::log10:
+        case Intrinsic::log2:
+        case Intrinsic::pow:
+        case Intrinsic::sin:
+          break;
+        default:
+          continue;
+        }
+        break;
+      }
+      continue;
+    }
+    }
+
+    llvm::replace(N, '.', '_');
+    N.replace(0, sizeof("llvm"), "__hipstdpar_");
+    ToReplace.emplace_back(&F, std::move(N));
+  }
+  for (auto &&F : ToReplace)
+    F.first->replaceAllUsesWith(M.getOrInsertFunction(
+        F.second, F.first->getFunctionType()).getCallee());
+
+  return PreservedAnalyses::none();
+}
\ No newline at end of file
diff --git a/llvm/test/Transforms/HipStdPar/math-fixup.ll 
b/llvm/test/Transforms/HipStdPar/math-fixup.ll
new file mode 100644
index 00000000000000..e0e2ca79c08435
--- /dev/null
+++ b/llvm/test/Transforms/HipStdPar/math-fixup.ll
@@ -0,0 +1,240 @@
+; RUN: opt -S -passes=hipstdpar-math-fixup %s | FileCheck %s
+
+define void @foo(double noundef %dbl, float noundef %flt, i32 noundef %quo) #0 
{
+; CHECK-LABEL: define void @foo(
+; CHECK-SAME: double noundef [[DBL:%.*]], float noundef [[FLT:%.*]], i32 
noundef [[QUO:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[QUO_ADDR:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    store i32 [[QUO]], ptr [[QUO_ADDR]], align 4
+entry:
+  %quo.addr = alloca i32, align 4
+  store i32 %quo, ptr %quo.addr, align 4
+  ; CHECK-NEXT:    [[TMP0:%.*]] = tail call contract double 
@llvm.fabs.f64(double [[DBL]])
+  %0 = tail call contract double @llvm.fabs.f64(double %dbl)
+  ; CHECK-NEXT:    [[TMP1:%.*]] = tail call contract float 
@llvm.fabs.f32(float [[FLT]])
+  %1 = tail call contract float @llvm.fabs.f32(float %flt)
+  ; CHECK-NEXT:    [[CALL:%.*]] = tail call contract double 
@__hipstdpar_remainder_f64(double noundef [[TMP0]], double noundef [[TMP0]]) 
#[[ATTR4:[0-9]+]]
+  %call = tail call contract double @remainder(double noundef %0, double 
noundef %0) #4
+  ; CHECK-NEXT:    [[CALL1:%.*]] = tail call contract float 
@__hipstdpar_remainder_f32(float noundef [[TMP1]], float noundef [[TMP1]]) 
#[[ATTR4]]
+  %call1 = tail call contract float @remainderf(float noundef %1, float 
noundef %1) #4
+  ; CHECK-NEXT:    [[CALL2:%.*]] = call contract double 
@__hipstdpar_remquo_f64(double noundef [[CALL]], double noundef [[CALL]], ptr 
noundef nonnull [[QUO_ADDR]]) #[[ATTR3:[0-9]+]]
+  %call2 = call contract double @remquo(double noundef %call, double noundef 
%call, ptr noundef nonnull %quo.addr) #5
+  ; CHECK-NEXT:    [[CALL3:%.*]] = call contract float 
@__hipstdpar_remquo_f32(float noundef [[CALL1]], float noundef [[CALL1]], ptr 
noundef nonnull [[QUO_ADDR]]) #[[ATTR3]]
+  %call3 = call contract float @remquof(float noundef %call1, float noundef 
%call1, ptr noundef nonnull %quo.addr) #5
+  ; CHECK-NEXT:    [[TMP2:%.*]] = call contract double @llvm.fma.f64(double 
[[CALL2]], double [[CALL2]], double [[CALL2]])
+  %2 = call contract double @llvm.fma.f64(double %call2, double %call2, double 
%call2)
+  ; CHECK-NEXT:    [[TMP3:%.*]] = call contract float @llvm.fma.f32(float 
[[CALL3]], float [[CALL3]], float [[CALL3]])
+  %3 = call contract float @llvm.fma.f32(float %call3, float %call3, float 
%call3)
+  ; CHECK-NEXT:    [[CALL4:%.*]] = call contract double 
@__hipstdpar_fdim_f64(double noundef [[TMP2]], double noundef [[TMP2]]) 
#[[ATTR4]]
+  %call4 = call contract double @fdim(double noundef %2, double noundef %2) #4
+  ; CHECK-NEXT:    [[CALL5:%.*]] = call contract float 
@__hipstdpar_fdim_f32(float noundef [[TMP3]], float noundef [[TMP3]]) #[[ATTR4]]
+  %call5 = call contract float @fdimf(float noundef %3, float noundef %3) #4
+  ; CHECK-NEXT:    [[TMP4:%.*]] = call contract double 
@__hipstdpar_exp_f64(double [[CALL4]])
+  %4 = call contract double @llvm.exp.f64(double %call4)
+  ; CHECK-NEXT:    [[TMP5:%.*]] = call contract float @llvm.exp.f32(float 
[[CALL5]])
+  %5 = call contract float @llvm.exp.f32(float %call5)
+  ; CHECK-NEXT:    [[TMP6:%.*]] = call contract double 
@__hipstdpar_exp2_f64(double [[TMP4]])
+  %6 = call contract double @llvm.exp2.f64(double %4)
+  ; CHECK-NEXT:    [[TMP7:%.*]] = call contract float @llvm.exp2.f32(float 
[[TMP5]])
+  %7 = call contract float @llvm.exp2.f32(float %5)
+  ; CHECK-NEXT:    [[CALL6:%.*]] = call contract double 
@__hipstdpar_expm1_f64(double noundef [[TMP6]]) #[[ATTR4]]
+  %call6 = call contract double @expm1(double noundef %6) #4
+  ; CHECK-NEXT:    [[CALL7:%.*]] = call contract float 
@__hipstdpar_expm1_f32(float noundef [[TMP7]]) #[[ATTR4]]
+  %call7 = call contract float @expm1f(float noundef %7) #4
+  ; CHECK-NEXT:    [[TMP8:%.*]] = call contract double 
@__hipstdpar_log_f64(double [[CALL6]])
+  %8 = call contract double @llvm.log.f64(double %call6)
+  ; CHECK-NEXT:    [[TMP9:%.*]] = call contract float @llvm.log.f32(float 
[[CALL7]])
+  %9 = call contract float @llvm.log.f32(float %call7)
+  ; CHECK-NEXT:    [[TMP10:%.*]] = call contract double 
@__hipstdpar_log10_f64(double [[TMP8]])
+  %10 = call contract double @llvm.log10.f64(double %8)
+  ; CHECK-NEXT:    [[TMP11:%.*]] = call contract float @llvm.log10.f32(float 
[[TMP9]])
+  %11 = call contract float @llvm.log10.f32(float %9)
+  ; CHECK-NEXT:    [[TMP12:%.*]] = call contract double 
@__hipstdpar_log2_f64(double [[TMP10]])
+  %12 = call contract double @llvm.log2.f64(double %10)
+  ; CHECK-NEXT:    [[TMP13:%.*]] = call contract float @llvm.log2.f32(float 
[[TMP11]])
+  %13 = call contract float @llvm.log2.f32(float %11)
+  ; CHECK-NEXT:    [[CALL8:%.*]] = call contract double 
@__hipstdpar_log1p_f64(double noundef [[TMP12]]) #[[ATTR4]]
+  %call8 = call contract double @log1p(double noundef %12) #4
+  ; CHECK-NEXT:    [[CALL9:%.*]] = call contract float 
@__hipstdpar_log1p_f32(float noundef [[TMP13]]) #[[ATTR4]]
+  %call9 = call contract float @log1pf(float noundef %13) #4
+  ; CHECK-NEXT:    [[TMP14:%.*]] = call contract float @llvm.pow.f32(float 
[[CALL9]], float [[CALL9]])
+  %14 = call contract float @llvm.pow.f32(float %call9, float %call9)
+  ; CHECK-NEXT:    [[TMP15:%.*]] = call contract double @llvm.sqrt.f64(double 
[[CALL8]])
+  %15 = call contract double @llvm.sqrt.f64(double %call8)
+  ; CHECK-NEXT:    [[TMP16:%.*]] = call contract float @llvm.sqrt.f32(float 
[[TMP14]])
+  %16 = call contract float @llvm.sqrt.f32(float %14)
+  ; CHECK-NEXT:    [[CALL10:%.*]] = call contract double 
@__hipstdpar_cbrt_f64(double noundef [[TMP15]]) #[[ATTR4]]
+  %call10 = call contract double @cbrt(double noundef %15) #4
+  ; CHECK-NEXT:    [[CALL11:%.*]] = call contract float 
@__hipstdpar_cbrt_f32(float noundef [[TMP16]]) #[[ATTR4]]
+  %call11 = call contract float @cbrtf(float noundef %16) #4
+  ; CHECK-NEXT:    [[CALL12:%.*]] = call contract double 
@__hipstdpar_hypot_f64(double noundef [[CALL10]], double noundef [[CALL10]]) 
#[[ATTR4]]
+  %call12 = call contract double @hypot(double noundef %call10, double noundef 
%call10) #4
+  ; CHECK-NEXT:    [[CALL13:%.*]] = call contract float 
@__hipstdpar_hypot_f32(float noundef [[CALL11]], float noundef [[CALL11]]) 
#[[ATTR4]]
+  %call13 = call contract float @hypotf(float noundef %call11, float noundef 
%call11) #4
+  ; CHECK-NEXT:    [[TMP17:%.*]] = call contract float @llvm.sin.f32(float 
[[CALL13]])
+  %17 = call contract float @llvm.sin.f32(float %call13)
+  ; CHECK-NEXT:    [[TMP18:%.*]] = call contract float @llvm.cos.f32(float 
[[TMP17]])
+  %18 = call contract float @llvm.cos.f32(float %17)
+  ; CHECK-NEXT:    [[TMP19:%.*]] = call contract double 
@__hipstdpar_tan_f64(double [[CALL12]])
+  %19 = call contract double @llvm.tan.f64(double %call12)
+  ; CHECK-NEXT:    [[TMP20:%.*]] = call contract double 
@__hipstdpar_asin_f64(double [[TMP19]])
+  %20 = call contract double @llvm.asin.f64(double %19)
+  ; CHECK-NEXT:    [[TMP21:%.*]] = call contract double 
@__hipstdpar_acos_f64(double [[TMP20]])
+  %21 = call contract double @llvm.acos.f64(double %20)
+  ; CHECK-NEXT:    [[TMP22:%.*]] = call contract double 
@__hipstdpar_atan_f64(double [[TMP21]])
+  %22 = call contract double @llvm.atan.f64(double %21)
+  ; CHECK-NEXT:    [[TMP23:%.*]] = call contract double 
@__hipstdpar_atan2_f64(double [[TMP22]], double [[TMP22]])
+  %23 = call contract double @llvm.atan2.f64(double %22, double %22)
+  ; CHECK-NEXT:    [[TMP24:%.*]] = call contract double 
@__hipstdpar_sinh_f64(double [[TMP23]])
+  %24 = call contract double @llvm.sinh.f64(double %23)
+  ; CHECK-NEXT:    [[TMP25:%.*]] = call contract double 
@__hipstdpar_cosh_f64(double [[TMP24]])
+  %25 = call contract double @llvm.cosh.f64(double %24)
+  ; CHECK-NEXT:    [[TMP26:%.*]] = call contract double 
@__hipstdpar_tanh_f64(double [[TMP25]])
+  %26 = call contract double @llvm.tanh.f64(double %25)
+  ; CHECK-NEXT:    [[CALL14:%.*]] = call contract double 
@__hipstdpar_asinh_f64(double noundef [[TMP26]]) #[[ATTR4]]
+  %call14 = call contract double @asinh(double noundef %26) #4
+  ; CHECK-NEXT:    [[CALL15:%.*]] = call contract float 
@__hipstdpar_asinh_f32(float noundef [[TMP18]]) #[[ATTR4]]
+  %call15 = call contract float @asinhf(float noundef %18) #4
+  ; CHECK-NEXT:    [[CALL16:%.*]] = call contract double 
@__hipstdpar_acosh_f64(double noundef [[CALL14]]) #[[ATTR4]]
+  %call16 = call contract double @acosh(double noundef %call14) #4
+  ; CHECK-NEXT:    [[CALL17:%.*]] = call contract float 
@__hipstdpar_acosh_f32(float noundef [[CALL15]]) #[[ATTR4]]
+  %call17 = call contract float @acoshf(float noundef %call15) #4
+  ; CHECK-NEXT:    [[CALL18:%.*]] = call contract double 
@__hipstdpar_atanh_f64(double noundef [[CALL16]]) #[[ATTR4]]
+  %call18 = call contract double @atanh(double noundef %call16) #4
+  ; CHECK-NEXT:    [[CALL19:%.*]] = call contract float 
@__hipstdpar_atanh_f32(float noundef [[CALL17]]) #[[ATTR4]]
+  %call19 = call contract float @atanhf(float noundef %call17) #4
+  ; CHECK-NEXT:    [[CALL20:%.*]] = call contract double 
@__hipstdpar_erf_f64(double noundef [[CALL18]]) #[[ATTR4]]
+  %call20 = call contract double @erf(double noundef %call18) #4
+  ; CHECK-NEXT:    [[CALL21:%.*]] = call contract float 
@__hipstdpar_erf_f32(float noundef [[CALL19]]) #[[ATTR4]]
+  %call21 = call contract float @erff(float noundef %call19) #4
+  ; CHECK-NEXT:    [[CALL22:%.*]] = call contract double 
@__hipstdpar_erfc_f64(double noundef [[CALL20]]) #[[ATTR4]]
+  %call22 = call contract double @erfc(double noundef %call20) #4
+  ; CHECK-NEXT:    [[CALL23:%.*]] = call contract float 
@__hipstdpar_erfc_f32(float noundef [[CALL21]]) #[[ATTR4]]
+  %call23 = call contract float @erfcf(float noundef %call21) #4
+  ; CHECK-NEXT:    [[CALL24:%.*]] = call contract double 
@__hipstdpar_tgamma_f64(double noundef [[CALL22]]) #[[ATTR4]]
+  %call24 = call contract double @tgamma(double noundef %call22) #4
+  ; CHECK-NEXT:    [[CALL25:%.*]] = call contract float 
@__hipstdpar_tgamma_f32(float noundef [[CALL23]]) #[[ATTR4]]
+  %call25 = call contract float @tgammaf(float noundef %call23) #4
+  ; CHECK-NEXT:    [[CALL26:%.*]] = call contract double 
@__hipstdpar_lgamma_f64(double noundef [[CALL24]]) #[[ATTR3]]
+  %call26 = call contract double @lgamma(double noundef %call24) #5
+  ; CHECK-NEXT:    [[CALL27:%.*]] = call contract float 
@__hipstdpar_lgamma_f32(float noundef [[CALL25]]) #[[ATTR3]]
+  %call27 = call contract float @lgammaf(float noundef %call25) #5
+  ret void
+}
+
+declare double @llvm.fabs.f64(double) #1
+
+declare float @llvm.fabs.f32(float) #1
+
+declare hidden double @remainder(double noundef, double noundef) 
local_unnamed_addr #2
+
+declare hidden float @remainderf(float noundef, float noundef) 
local_unnamed_addr #2
+
+declare hidden double @remquo(double noundef, double noundef, ptr noundef) 
local_unnamed_addr #3
+
+declare hidden float @remquof(float noundef, float noundef, ptr noundef) 
local_unnamed_addr #3
+
+declare double @llvm.fma.f64(double, double, double) #1
+
+declare float @llvm.fma.f32(float, float, float) #1
+
+declare hidden double @fdim(double noundef, double noundef) local_unnamed_addr 
#2
+
+declare hidden float @fdimf(float noundef, float noundef) local_unnamed_addr #2
+
+declare double @llvm.exp.f64(double) #1
+
+declare float @llvm.exp.f32(float) #1
+
+declare double @llvm.exp2.f64(double) #1
+
+declare float @llvm.exp2.f32(float) #1
+
+declare hidden double @expm1(double noundef) local_unnamed_addr #2
+
+declare hidden float @expm1f(float noundef) local_unnamed_addr #2
+
+declare double @llvm.log.f64(double) #1
+
+declare float @llvm.log.f32(float) #1
+
+declare double @llvm.log10.f64(double) #1
+
+declare float @llvm.log10.f32(float) #1
+
+declare double @llvm.log2.f64(double) #1
+
+declare float @llvm.log2.f32(float) #1
+
+declare hidden double @log1p(double noundef) local_unnamed_addr #2
+
+declare hidden float @log1pf(float noundef) local_unnamed_addr #2
+
+declare float @llvm.pow.f32(float, float) #1
+
+declare double @llvm.sqrt.f64(double) #1
+
+declare float @llvm.sqrt.f32(float) #1
+
+declare hidden double @cbrt(double noundef) local_unnamed_addr #2
+
+declare hidden float @cbrtf(float noundef) local_unnamed_addr #2
+
+declare hidden double @hypot(double noundef, double noundef) 
local_unnamed_addr #2
+
+declare hidden float @hypotf(float noundef, float noundef) local_unnamed_addr 
#2
+
+declare float @llvm.sin.f32(float) #1
+
+declare float @llvm.cos.f32(float) #1
+
+declare double @llvm.tan.f64(double) #1
+
+declare double @llvm.asin.f64(double) #1
+
+declare double @llvm.acos.f64(double) #1
+
+declare double @llvm.atan.f64(double) #1
+
+declare double @llvm.atan2.f64(double, double) #1
+
+declare double @llvm.sinh.f64(double) #1
+
+declare double @llvm.cosh.f64(double) #1
+
+declare double @llvm.tanh.f64(double) #1
+
+declare hidden double @asinh(double noundef) local_unnamed_addr #2
+
+declare hidden float @asinhf(float noundef) local_unnamed_addr #2
+
+declare hidden double @acosh(double noundef) local_unnamed_addr #2
+
+declare hidden float @acoshf(float noundef) local_unnamed_addr #2
+
+declare hidden double @atanh(double noundef) local_unnamed_addr #2
+
+declare hidden float @atanhf(float noundef) local_unnamed_addr #2
+
+declare hidden double @erf(double noundef) local_unnamed_addr #2
+
+declare hidden float @erff(float noundef) local_unnamed_addr #2
+
+declare hidden double @erfc(double noundef) local_unnamed_addr #2
+
+declare hidden float @erfcf(float noundef) local_unnamed_addr #2
+
+declare hidden double @tgamma(double noundef) local_unnamed_addr #2
+
+declare hidden float @tgammaf(float noundef) local_unnamed_addr #2
+
+declare hidden double @lgamma(double noundef) local_unnamed_addr #3
+
+declare hidden float @lgammaf(float noundef) local_unnamed_addr #3
+
+attributes #0 = { convergent mustprogress norecurse nounwind }
+attributes #1 = { mustprogress nocallback nofree nosync nounwind speculatable 
willreturn memory(none) }
+attributes #2 = { convergent mustprogress nofree nounwind willreturn 
memory(none) }
+attributes #3 = { convergent nounwind }
+attributes #4 = { convergent nounwind willreturn memory(none) }
+attributes #5 = { convergent nounwind }

>From d2998eac9f2a7a26edf69b54e850d6c81a5998d7 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Thu, 1 Oct 2026 19:05:14 +0100
Subject: [PATCH 02/16] Add safe-ish size optimization for AMDGCN flavoured
 SPIR-V.

---
 clang/lib/CodeGen/BackendUtil.cpp             | 45 +++++++++++++++++++
 .../CodeGen/amdgcnspirv-size-optimization.c   | 45 +++++++++++++++++++
 2 files changed, 90 insertions(+)
 create mode 100644 clang/test/CodeGen/amdgcnspirv-size-optimization.c

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index c754c75aa59de5..6f7e5c76965441 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -66,9 +66,14 @@
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/HipStdPar/HipStdPar.h"
+#include "llvm/Transforms/IPO/DeadArgumentElimination.h"
 #include "llvm/Transforms/IPO/EmbedBitcodePass.h"
+#include "llvm/Transforms/IPO/FunctionAttrs.h"
+#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
+#include "llvm/Transforms/IPO/GlobalOpt.h"
 #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
 #include "llvm/Transforms/IPO/LowerTypeTests.h"
+#include "llvm/Transforms/IPO/SCCP.h"
 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
 #include "llvm/Transforms/InstCombine/InstCombine.h"
 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
@@ -95,9 +100,13 @@
 #include "llvm/Transforms/Scalar/EarlyCSE.h"
 #include "llvm/Transforms/Scalar/GVN.h"
 #include "llvm/Transforms/Scalar/JumpThreading.h"
+#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
+#include "llvm/Transforms/Scalar/SimplifyCFG.h"
+#include "llvm/Transforms/Scalar/SROA.h"
 #include "llvm/Transforms/Utils/AssignGUID.h"
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/Transforms/Utils/DynamicDebugging.h"
+#include "llvm/Transforms/Utils/Mem2Reg.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <limits>
 #include <memory>
@@ -800,6 +809,38 @@ void addLowerAllowCheckPass(const CodeGenOptions 
&CodeGenOpts,
   }
 }
 
+static void addAMDGCNSPIRVSizeOptimizationPasses(ModulePassManager &MPM) {
+  // For AMDGCN flavoured SPIR-V we want to preserve the pristine Clang input
+  // by default, to minimise the risk of SPIR-V target specific transforms
+  // being disruptive for the AMDGPU BE. However, this can yield very large
+  // binaries. Thus, for higher optimisation levels we turn on a minimal set
+  // of size reducing passes. The pass collection here is derived from that
+  // proposed in Jain et al. "An analysis of executable size reduction by LLVM
+  // passes" (https://doi.org/10.1007/s40012-019-00248-5), more specifically
+  // the GF and G0 groups.
+
+  // GF: -lower-expect -simplifycfg -sroa -early-cse
+  MPM.addPass(createModuleToFunctionPassAdaptor(LowerExpectIntrinsicPass()));
+  MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass()));
+  MPM.addPass(createModuleToFunctionPassAdaptor(
+      SROAPass(SROAOptions::PreserveCFG)));
+  MPM.addPass(createModuleToFunctionPassAdaptor(EarlyCSEPass()));
+
+  // G0: -forceattrs -inferattrs -ipsccp -globalopt -mem2reg -deadargelim
+  //     -instcombine -simplifycfg -prune-eh (PostOrderFunctionAttrs in NewPM)
+  //     -inline(disabled) -functionattrs (disabled)
+  MPM.addPass(ForceFunctionAttrsPass());
+  MPM.addPass(InferFunctionAttrsPass());
+  MPM.addPass(IPSCCPPass());
+  MPM.addPass(GlobalOptPass());
+  MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass()));
+  MPM.addPass(DeadArgumentEliminationPass());
+  MPM.addPass(createModuleToFunctionPassAdaptor(InstCombinePass()));
+  MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass()));
+  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
+      PostOrderFunctionAttrsPass()));
+}
+
 void EmitAssemblyHelper::RunOptimizationPipeline(
     BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,
     std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS, BackendConsumer *BC) {
@@ -1116,6 +1157,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
     } else {
       MPM.addPass(PB.buildPerModuleDefaultPipeline(Level));
     }
+  } else if (TargetTriple.isSPIRV() &&
+             TargetTriple.getVendor() == llvm::Triple::VendorType::AMD &&
+             mapToLevel(CodeGenOpts) > OptimizationLevel::O1) {
+    addAMDGCNSPIRVSizeOptimizationPasses(MPM);
   }
 
   // Link against bitcodes supplied via the -mlink-builtin-bitcode option
diff --git a/clang/test/CodeGen/amdgcnspirv-size-optimization.c 
b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
new file mode 100644
index 00000000000000..93385ec800e0fe
--- /dev/null
+++ b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
@@ -0,0 +1,45 @@
+
+// RUN: %clang_cc1 -O0 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -O1 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O1
+// RUN: %clang_cc1 -O2 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O2
+
+// O0-NOT: Running pass: LowerExpectIntrinsic
+// O0-NOT: Running pass: SimplifyCFG
+// O0-NOT: Running pass: SROA
+// O0-NOT: Running pass: EarlyCSE
+// O0-NOT: Running pass: ForceFunctionAttrs
+// O0-NOT: Running pass: InferFunctionAttrs
+// O0-NOT: Running pass: IPSCCP
+// O0-NOT: Running pass: GlobalOpt
+// O0-NOT: Running pass: Promote
+// O0-NOT: Running pass: DeadArgumentElimination
+// O0-NOT: Running pass: InstCombine
+// O0-NOT: Running pass: PostOrderFunctionAttrs
+
+// O1-NOT: Running pass: LowerExpectIntrinsic
+// O1-NOT: Running pass: SimplifyCFG
+// O1-NOT: Running pass: SROA
+// O1-NOT: Running pass: EarlyCSE
+// O1-NOT: Running pass: ForceFunctionAttrs
+// O1-NOT: Running pass: InferFunctionAttrs
+// O1-NOT: Running pass: IPSCCP
+// O1-NOT: Running pass: GlobalOpt
+// O1-NOT: Running pass: Promote
+// O1-NOT: Running pass: DeadArgumentElimination
+// O1-NOT: Running pass: InstCombine
+// O1-NOT: Running pass: PostOrderFunctionAttrs
+
+// O2-DAG: Running pass: LowerExpectIntrinsic
+// O2-DAG: Running pass: SimplifyCFG
+// O2-DAG: Running pass: SROA
+// O2-DAG: Running pass: EarlyCSE
+// O2-DAG: Running pass: ForceFunctionAttrs
+// O2-DAG: Running pass: InferFunctionAttrs
+// O2-DAG: Running pass: IPSCCP
+// O2-DAG: Running pass: GlobalOpt
+// O2-DAG: Running pass: Promote
+// O2-DAG: Running pass: DeadArgumentElimination
+// O2-DAG: Running pass: InstCombine
+// O2-DAG: Running pass: PostOrderFunctionAttrs
+
+void foo() {}

>From 86fc7fa0632f0487be03b82affd51875fdadd66b Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Fri, 2 Oct 2026 12:52:51 +0100
Subject: [PATCH 03/16] Fix formatting.

---
 clang/lib/CodeGen/BackendUtil.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 6f7e5c76965441..ee4e4be696de9b 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -68,8 +68,8 @@
 #include "llvm/Transforms/HipStdPar/HipStdPar.h"
 #include "llvm/Transforms/IPO/DeadArgumentElimination.h"
 #include "llvm/Transforms/IPO/EmbedBitcodePass.h"
-#include "llvm/Transforms/IPO/FunctionAttrs.h"
 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
+#include "llvm/Transforms/IPO/FunctionAttrs.h"
 #include "llvm/Transforms/IPO/GlobalOpt.h"
 #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
 #include "llvm/Transforms/IPO/LowerTypeTests.h"
@@ -101,8 +101,8 @@
 #include "llvm/Transforms/Scalar/GVN.h"
 #include "llvm/Transforms/Scalar/JumpThreading.h"
 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
-#include "llvm/Transforms/Scalar/SimplifyCFG.h"
 #include "llvm/Transforms/Scalar/SROA.h"
+#include "llvm/Transforms/Scalar/SimplifyCFG.h"
 #include "llvm/Transforms/Utils/AssignGUID.h"
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/Transforms/Utils/DynamicDebugging.h"
@@ -822,8 +822,8 @@ static void 
addAMDGCNSPIRVSizeOptimizationPasses(ModulePassManager &MPM) {
   // GF: -lower-expect -simplifycfg -sroa -early-cse
   MPM.addPass(createModuleToFunctionPassAdaptor(LowerExpectIntrinsicPass()));
   MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass()));
-  MPM.addPass(createModuleToFunctionPassAdaptor(
-      SROAPass(SROAOptions::PreserveCFG)));
+  MPM.addPass(
+      createModuleToFunctionPassAdaptor(SROAPass(SROAOptions::PreserveCFG)));
   MPM.addPass(createModuleToFunctionPassAdaptor(EarlyCSEPass()));
 
   // G0: -forceattrs -inferattrs -ipsccp -globalopt -mem2reg -deadargelim
@@ -837,8 +837,8 @@ static void 
addAMDGCNSPIRVSizeOptimizationPasses(ModulePassManager &MPM) {
   MPM.addPass(DeadArgumentEliminationPass());
   MPM.addPass(createModuleToFunctionPassAdaptor(InstCombinePass()));
   MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass()));
-  MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
-      PostOrderFunctionAttrsPass()));
+  MPM.addPass(
+      createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass()));
 }
 
 void EmitAssemblyHelper::RunOptimizationPipeline(

>From 15d5013fa6a6012ed4f318ec2b8ac6628a2282a8 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Sun, 4 Oct 2026 12:22:55 +0100
Subject: [PATCH 04/16] Update test.

---
 .../CodeGen/amdgcnspirv-size-optimization.c   | 44 +++++++------------
 1 file changed, 17 insertions(+), 27 deletions(-)

diff --git a/clang/test/CodeGen/amdgcnspirv-size-optimization.c 
b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
index 93385ec800e0fe..cf512d3a4d7af9 100644
--- a/clang/test/CodeGen/amdgcnspirv-size-optimization.c
+++ b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
@@ -1,7 +1,10 @@
 
 // RUN: %clang_cc1 -O0 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
-// RUN: %clang_cc1 -O1 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O1
-// RUN: %clang_cc1 -O2 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O2
+// RUN: %clang_cc1 -O1 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -Og -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -O2 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O
+// RUN: %clang_cc1 -Os -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O
+// RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O
 
 // O0-NOT: Running pass: LowerExpectIntrinsic
 // O0-NOT: Running pass: SimplifyCFG
@@ -16,30 +19,17 @@
 // O0-NOT: Running pass: InstCombine
 // O0-NOT: Running pass: PostOrderFunctionAttrs
 
-// O1-NOT: Running pass: LowerExpectIntrinsic
-// O1-NOT: Running pass: SimplifyCFG
-// O1-NOT: Running pass: SROA
-// O1-NOT: Running pass: EarlyCSE
-// O1-NOT: Running pass: ForceFunctionAttrs
-// O1-NOT: Running pass: InferFunctionAttrs
-// O1-NOT: Running pass: IPSCCP
-// O1-NOT: Running pass: GlobalOpt
-// O1-NOT: Running pass: Promote
-// O1-NOT: Running pass: DeadArgumentElimination
-// O1-NOT: Running pass: InstCombine
-// O1-NOT: Running pass: PostOrderFunctionAttrs
-
-// O2-DAG: Running pass: LowerExpectIntrinsic
-// O2-DAG: Running pass: SimplifyCFG
-// O2-DAG: Running pass: SROA
-// O2-DAG: Running pass: EarlyCSE
-// O2-DAG: Running pass: ForceFunctionAttrs
-// O2-DAG: Running pass: InferFunctionAttrs
-// O2-DAG: Running pass: IPSCCP
-// O2-DAG: Running pass: GlobalOpt
-// O2-DAG: Running pass: Promote
-// O2-DAG: Running pass: DeadArgumentElimination
-// O2-DAG: Running pass: InstCombine
-// O2-DAG: Running pass: PostOrderFunctionAttrs
+// O-DAG: Running pass: LowerExpectIntrinsic
+// O-DAG: Running pass: SimplifyCFG
+// O-DAG: Running pass: SROA
+// O-DAG: Running pass: EarlyCSE
+// O-DAG: Running pass: ForceFunctionAttrs
+// O-DAG: Running pass: InferFunctionAttrs
+// O-DAG: Running pass: IPSCCP
+// O-DAG: Running pass: GlobalOpt
+// O-DAG: Running pass: Promote
+// O-DAG: Running pass: DeadArgumentElimination
+// O-DAG: Running pass: InstCombine
+// O-DAG: Running pass: PostOrderFunctionAttrs
 
 void foo() {}

>From 2230231bfa7ce820fe2eaae24333827b5f09f265 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Mon, 12 Oct 2026 19:39:43 +0100
Subject: [PATCH 05/16] Guard size optimizations via flag.

---
 clang/include/clang/Basic/CodeGenOptions.def | 1 +
 clang/include/clang/Options/Options.td       | 7 +++++++
 clang/lib/CodeGen/BackendUtil.cpp            | 8 +++++---
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index 10d9a4e3a6a82c..bb86ae58f7c2f3 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -205,6 +205,7 @@ CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0, Benign) 
///< -cl-fp32-correctly-
 CODEGENOPT(HIPCorrectlyRoundedDivSqrt, 1, 1, Benign) ///< 
-fno-hip-fp32-correctly-rounded-divide-sqrt
 CODEGENOPT(DisableBlockSignatureString, 1, 0, Benign) ///< Set when 
-fdisable-block-signature-string is enabled.
 CODEGENOPT(HIPSaveKernelArgName, 1, 0, Benign) ///< Set when 
-fhip-kernel-arg-name is enabled.
+CODEGENOPT(AMDGCNSPIRVSizeOptimization, 1, 0, Benign) ///< Set when 
fenable-spirv-size-optimization is enabled.
 CODEGENOPT(UniqueInternalLinkageNames, 1, 0, Benign) ///< Internal Linkage 
symbols get unique names.
 CODEGENOPT(SplitMachineFunctions, 1, 0, Benign) ///< Split machine functions 
using profile information.
 CODEGENOPT(PartitionStaticDataSections, 1, 0, Benign) /// < Partition static 
data sections using profile information.
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 60ae84cb0af5c7..a0f5706749e08e 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1580,6 +1580,13 @@ def no_use_spirv_backend
       Group<hip_Group>,
       Flags<[HelpHidden]>,
       HelpText<"Do not use the SPIRV backend for compilation ">;
+def fenable_spirv_size_optimization
+    : Flag<["-"], "fenable-spirv-size-optimization">,
+      MarshallingInfoFlag<CodeGenOpts<"AMDGCNSPIRVSizeOptimization">>,
+      Visibility<[ClangOption, CC1Option]>,
+      Group<hip_Group>,
+      Flags<[HelpHidden]>,
+      HelpText<"Enable size reducing optimizations for AMDGCNSPIRV">;
 }
 
 // Clang specific/exclusive options for OpenACC.
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index ee4e4be696de9b..a9924f2619de61 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1157,9 +1157,11 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
     } else {
       MPM.addPass(PB.buildPerModuleDefaultPipeline(Level));
     }
-  } else if (TargetTriple.isSPIRV() &&
-             TargetTriple.getVendor() == llvm::Triple::VendorType::AMD &&
-             mapToLevel(CodeGenOpts) > OptimizationLevel::O1) {
+  } else if (mapToLevel(CodeGenOpts) > OptimizationLevel::O0 &&
+             CodeGenOpts.AMDGCNSPIRVSizeOptimization) {
+    assert(TargetTriple.isSPIRV() &&
+           TargetTriple.getVendor() == llvm::Triple::VendorType::AMD &&
+           "Invalid target triple!");
     addAMDGCNSPIRVSizeOptimizationPasses(MPM);
   }
 

>From 35e3959fc73d47221cb452fc616e3ee97ca171dd Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Mon, 12 Oct 2026 19:40:17 +0100
Subject: [PATCH 06/16] Update test.

---
 clang/test/CodeGen/amdgcnspirv-size-optimization.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/clang/test/CodeGen/amdgcnspirv-size-optimization.c 
b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
index cf512d3a4d7af9..f052c0c740358f 100644
--- a/clang/test/CodeGen/amdgcnspirv-size-optimization.c
+++ b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
@@ -1,10 +1,18 @@
 
 // RUN: %clang_cc1 -O0 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -O0 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O0
 // RUN: %clang_cc1 -O1 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -O2 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -O3 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
 // RUN: %clang_cc1 -Og -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
-// RUN: %clang_cc1 -O2 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O
-// RUN: %clang_cc1 -Os -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O
-// RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O
+// RUN: %clang_cc1 -Os -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -o /dev/null -fdebug-pass-manager %s 2>&1 | FileCheck %s 
--check-prefix=O0
+// RUN: %clang_cc1 -O1 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
+// RUN: %clang_cc1 -O2 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
+// RUN: %clang_cc1 -O3 -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
+// RUN: %clang_cc1 -Og -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
+// RUN: %clang_cc1 -Os -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
+// RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
 
 // O0-NOT: Running pass: LowerExpectIntrinsic
 // O0-NOT: Running pass: SimplifyCFG

>From b5c7ff151009a5d60f04b347b3082017ce98d58d Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Tue, 13 Oct 2026 10:54:58 +0100
Subject: [PATCH 07/16] Add missing Clang side handling.

---
 clang/lib/Driver/ToolChains/Clang.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index fb6effb65d71f7..35fc112fce400d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7480,6 +7480,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     Args.AddLastArg(CmdArgs, options::OPT_hipstdpar_interpose_alloc);
     Args.addOptInFlag(CmdArgs, options::OPT_fhip_kernel_arg_name,
                       options::OPT_fno_hip_kernel_arg_name);
+    Args.addLastArg(CmdArgs, options::OPT_fenable_spirv_size_optimization);
   }
 
   if ((IsCuda || IsHIP || IsSYCL) && IsRDCMode)
@@ -9845,7 +9846,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const 
JobAction &JA,
       OPT_fno_sanitize_trap_EQ,
       OPT_fslp_vectorize,
       OPT_fno_slp_vectorize,
-      OPT_hipstdpar};
+      OPT_hipstdpar,
+      OPT_fenable_spirv_size_optimization};
   const llvm::DenseSet<unsigned> LinkerOptions{OPT_mllvm, OPT_Zlinker_input};
   // Suppress verbose output for HIP non-RDC fat binaries because it confuses
   // CMake implicit linker argument parsing.

>From bb147f89c06ba2673677a8339d9d25f51b6afed8 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Tue, 13 Oct 2026 18:13:08 +0100
Subject: [PATCH 08/16] Correctly constrain to AMDGCNSPIRV.

---
 clang/lib/Driver/ToolChains/Clang.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 35fc112fce400d..dcc9d0502a1b44 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7480,6 +7480,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     Args.AddLastArg(CmdArgs, options::OPT_hipstdpar_interpose_alloc);
     Args.addOptInFlag(CmdArgs, options::OPT_fhip_kernel_arg_name,
                       options::OPT_fno_hip_kernel_arg_name);
+    if (TC.getTriple().isSPIRV() &&
+        TC.getTriple().getVendor() == llvm::Triple::VendorType::AMD)
     Args.addLastArg(CmdArgs, options::OPT_fenable_spirv_size_optimization);
   }
 

>From bc402094dfc0479c8ec512a65e077750081fb524 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Wed, 14 Oct 2026 22:22:57 +0100
Subject: [PATCH 09/16] Use a hard error instead of an `assert`.

---
 clang/lib/CodeGen/BackendUtil.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index e22e8da04a6ee5..306946d10dda61 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1156,9 +1156,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
     }
   } else if (mapToLevel(CodeGenOpts) > OptimizationLevel::O0 &&
              CodeGenOpts.AMDGCNSPIRVSizeOptimization) {
-    assert(TargetTriple.isSPIRV() &&
-           TargetTriple.getVendor() == llvm::Triple::VendorType::AMD &&
-           "Invalid target triple!");
+    if (!TargetTriple.isSPIRV() ||
+        (TargetTriple.getVendor() != llvm::Triple::VendorType::AMD))
+      Diags.Report(diag::err_opt_not_valid_on_target)
+          << "fenable-spirv-size-optimization";
     addAMDGCNSPIRVSizeOptimizationPasses(MPM);
   }
 

>From 7b56e65f9b034be72db0c5ff6396ca16236f68f9 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Wed, 14 Oct 2026 22:23:44 +0100
Subject: [PATCH 10/16] Apply suggestion.

---
 clang/include/clang/Basic/CodeGenOptions.def | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index bb86ae58f7c2f3..1bd9afc684c3ab 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -205,7 +205,7 @@ CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0, Benign) 
///< -cl-fp32-correctly-
 CODEGENOPT(HIPCorrectlyRoundedDivSqrt, 1, 1, Benign) ///< 
-fno-hip-fp32-correctly-rounded-divide-sqrt
 CODEGENOPT(DisableBlockSignatureString, 1, 0, Benign) ///< Set when 
-fdisable-block-signature-string is enabled.
 CODEGENOPT(HIPSaveKernelArgName, 1, 0, Benign) ///< Set when 
-fhip-kernel-arg-name is enabled.
-CODEGENOPT(AMDGCNSPIRVSizeOptimization, 1, 0, Benign) ///< Set when 
fenable-spirv-size-optimization is enabled.
+CODEGENOPT(AMDGCNSPIRVSizeOptimization, 1, 0, Benign) ///< Set when 
-fenable-spirv-size-optimization is enabled.
 CODEGENOPT(UniqueInternalLinkageNames, 1, 0, Benign) ///< Internal Linkage 
symbols get unique names.
 CODEGENOPT(SplitMachineFunctions, 1, 0, Benign) ///< Split machine functions 
using profile information.
 CODEGENOPT(PartitionStaticDataSections, 1, 0, Benign) /// < Partition static 
data sections using profile information.

>From 2169eabb6762d74d715674ef780ae917f6a7dda8 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Wed, 14 Oct 2026 22:39:50 +0100
Subject: [PATCH 11/16] Check BC as well.

---
 clang/test/CodeGen/amdgcnspirv-size-optimization.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/clang/test/CodeGen/amdgcnspirv-size-optimization.c 
b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
index f052c0c740358f..864337c01d3d29 100644
--- a/clang/test/CodeGen/amdgcnspirv-size-optimization.c
+++ b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
@@ -13,6 +13,8 @@
 // RUN: %clang_cc1 -Og -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
 // RUN: %clang_cc1 -Os -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
 // RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
+// RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm -o - %s | FileCheck %s --check-prefix=O0-BC
+// RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm -fenable-spirv-size-optimization -o - %s | FileCheck %s 
--check-prefix=O-BC
 
 // O0-NOT: Running pass: LowerExpectIntrinsic
 // O0-NOT: Running pass: SimplifyCFG
@@ -40,4 +42,9 @@
 // O-DAG: Running pass: InstCombine
 // O-DAG: Running pass: PostOrderFunctionAttrs
 
-void foo() {}
+// O0-BC: alloca
+// O-BC-NOT: alloca
+int foo(int x) {
+    int y = x;
+    return y;
+}

>From fa78c92c2b61e2fa05c1c91691f7999613a9db32 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Wed, 14 Oct 2026 22:59:56 +0100
Subject: [PATCH 12/16] Add Clang side test.

---
 clang/test/Driver/hip-options.hip | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/test/Driver/hip-options.hip 
b/clang/test/Driver/hip-options.hip
index a53c1a61abefab..d6b77a0822d06a 100644
--- a/clang/test/Driver/hip-options.hip
+++ b/clang/test/Driver/hip-options.hip
@@ -286,3 +286,8 @@
 // NO-COV-NOT: --device-compiler=amdgcn-amd-amdhsa=-fprofile-instr-generate
 // NO-COV-NOT: --device-compiler=amdgcn-amd-amdhsa=-fcoverage-mapping
 
+// Check that AMDGCNSPIRV size optimization is forwarded to -cc1
+// RUN: %clang -### -nogpuinc -nogpulib -fenable-spirv-size-optimization \
+// RUN:   --offload-arch=amdgcnspirv  %s 2>&1 | FileCheck 
-check-prefix=AMDGCNSPIRV-SIZE-OPT %s
+// AMDGCNSPIRV-SIZE-OPT: "-cc1"{{.*}} "-triple" "spirv64-amd-amdhsa" {{.*}} 
"-fenable-spirv-size-optimization"
+

>From a460c19411dd0d60ac1fce3091102086c862a4be Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Wed, 14 Oct 2026 23:04:08 +0100
Subject: [PATCH 13/16] Fix formatting.

---
 clang/lib/Driver/ToolChains/Clang.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index dcc9d0502a1b44..cf00632a935ba2 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7482,7 +7482,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
                       options::OPT_fno_hip_kernel_arg_name);
     if (TC.getTriple().isSPIRV() &&
         TC.getTriple().getVendor() == llvm::Triple::VendorType::AMD)
-    Args.addLastArg(CmdArgs, options::OPT_fenable_spirv_size_optimization);
+      Args.addLastArg(CmdArgs, options::OPT_fenable_spirv_size_optimization);
   }
 
   if ((IsCuda || IsHIP || IsSYCL) && IsRDCMode)

>From 18aa0a2ab0dc1fb2cfd852b161cab9f0c0caa01d Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Thu, 15 Oct 2026 17:45:18 +0100
Subject: [PATCH 14/16] Test for error state as well.

---
 clang/test/CodeGen/amdgcnspirv-size-optimization.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/test/CodeGen/amdgcnspirv-size-optimization.c 
b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
index 864337c01d3d29..38428cef345d08 100644
--- a/clang/test/CodeGen/amdgcnspirv-size-optimization.c
+++ b/clang/test/CodeGen/amdgcnspirv-size-optimization.c
@@ -15,6 +15,7 @@
 // RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm-bc -fenable-spirv-size-optimization -o /dev/null 
-fdebug-pass-manager %s 2>&1 | FileCheck %s --check-prefix=O
 // RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm -o - %s | FileCheck %s --check-prefix=O0-BC
 // RUN: %clang_cc1 -Oz -triple spirv64-amd-amdhsa -disable-llvm-passes 
-emit-llvm -fenable-spirv-size-optimization -o - %s | FileCheck %s 
--check-prefix=O-BC
+// RUN: not %clang_cc1 -Oz -triple spirv64-unknown-unknown 
-disable-llvm-passes -emit-llvm -fenable-spirv-size-optimization %s 2>&1 | 
FileCheck %s --check-prefix=ERR
 
 // O0-NOT: Running pass: LowerExpectIntrinsic
 // O0-NOT: Running pass: SimplifyCFG
@@ -48,3 +49,5 @@ int foo(int x) {
     int y = x;
     return y;
 }
+
+// ERR: error: option 'fenable-spirv-size-optimization' cannot be specified on 
this target

>From f832e020e79207772103fd96fa214c247d6ad9fa Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Thu, 15 Oct 2026 17:49:58 +0100
Subject: [PATCH 15/16] Return immediately after erroring out.

---
 clang/lib/CodeGen/BackendUtil.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 306946d10dda61..599c0dab717fb5 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1157,9 +1157,11 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   } else if (mapToLevel(CodeGenOpts) > OptimizationLevel::O0 &&
              CodeGenOpts.AMDGCNSPIRVSizeOptimization) {
     if (!TargetTriple.isSPIRV() ||
-        (TargetTriple.getVendor() != llvm::Triple::VendorType::AMD))
+        (TargetTriple.getVendor() != llvm::Triple::VendorType::AMD)) {
       Diags.Report(diag::err_opt_not_valid_on_target)
           << "fenable-spirv-size-optimization";
+      return;
+    }
     addAMDGCNSPIRVSizeOptimizationPasses(MPM);
   }
 

>From 04d84d29e4616153eb2e923b4b533c62bc7ac4f6 Mon Sep 17 00:00:00 2001
From: Alex Voicu <[email protected]>
Date: Wed, 21 Oct 2026 18:42:45 +0100
Subject: [PATCH 16/16] Always create constants in the entry block.

---
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 30 +++++++++----------
 .../all_memory_barrier_with_group_sync.ll     |  2 +-
 .../device_memory_barrier_with_group_sync.ll  |  2 +-
 .../hlsl-intrinsics/group_memory_barrier.ll   |  2 +-
 .../group_memory_barrier_with_group_sync.ll   |  2 +-
 5 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp 
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index fbbf00dbb6c05d..083ab6db784797 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -2146,7 +2146,7 @@ bool SPIRVInstructionSelector::selectAtomicLoad(Register 
ResVReg,
 
   uint32_t Scope = static_cast<uint32_t>(
       getMemScope(STI.getTargetTriple(), Context, MemOp.getSyncScopeID()));
-  Register ScopeReg = buildI32Constant(Scope, I);
+  Register ScopeReg = buildI32ConstantInEntryBlock(Scope, I);
 
   AtomicOrdering AO = MemOp.getSuccessOrdering();
   uint32_t StorageClass = static_cast<uint32_t>(getMemSemanticsForStorageClass(
@@ -2156,7 +2156,7 @@ bool SPIRVInstructionSelector::selectAtomicLoad(Register 
ResVReg,
     MemSem |= static_cast<uint32_t>(SPIRV::MemorySemantics::Volatile);
   uint32_t Sem = getMemSemanticsWithStorageClass(STI.getTargetTriple(), MemSem,
                                                  StorageClass);
-  Register MemSemReg = buildI32Constant(Sem, I);
+  Register MemSemReg = buildI32ConstantInEntryBlock(Sem, I);
 
   MachineIRBuilder MIRBuilder(I);
 
@@ -2322,7 +2322,7 @@ bool 
SPIRVInstructionSelector::selectAtomicStore(MachineInstr &I) const {
 
   uint32_t Scope = static_cast<uint32_t>(
       getMemScope(STI.getTargetTriple(), Context, MemOp.getSyncScopeID()));
-  Register ScopeReg = buildI32Constant(Scope, I);
+  Register ScopeReg = buildI32ConstantInEntryBlock(Scope, I);
 
   AtomicOrdering AO = MemOp.getSuccessOrdering();
   uint32_t StorageClass = static_cast<uint32_t>(getMemSemanticsForStorageClass(
@@ -2332,7 +2332,7 @@ bool 
SPIRVInstructionSelector::selectAtomicStore(MachineInstr &I) const {
     MemSem |= static_cast<uint32_t>(SPIRV::MemorySemantics::Volatile);
   uint32_t Sem = getMemSemanticsWithStorageClass(STI.getTargetTriple(), MemSem,
                                                  StorageClass);
-  Register MemSemReg = buildI32Constant(Sem, I);
+  Register MemSemReg = buildI32ConstantInEntryBlock(Sem, I);
   MachineIRBuilder MIRBuilder(I);
 
   if (PointeeType.isTypePtr()) {
@@ -2391,7 +2391,7 @@ bool 
SPIRVInstructionSelector::selectMaskedGather(Register ResVReg,
   const uint32_t Alignment = I.getOperand(3).getImm();
   const Register MaskReg = I.getOperand(4).getReg();
   const Register PassthruReg = I.getOperand(5).getReg();
-  const Register AlignmentReg = buildI32Constant(Alignment, I);
+  const Register AlignmentReg = buildI32ConstantInEntryBlock(Alignment, I);
 
   MachineBasicBlock &BB = *I.getParent();
   auto MIB =
@@ -2418,7 +2418,7 @@ bool 
SPIRVInstructionSelector::selectMaskedScatter(MachineInstr &I) const {
   const Register PtrsReg = I.getOperand(2).getReg();
   const uint32_t Alignment = I.getOperand(3).getImm();
   const Register MaskReg = I.getOperand(4).getReg();
-  const Register AlignmentReg = buildI32Constant(Alignment, I);
+  const Register AlignmentReg = buildI32ConstantInEntryBlock(Alignment, I);
   MachineBasicBlock &BB = *I.getParent();
 
   auto MIB =
@@ -2615,14 +2615,14 @@ bool SPIRVInstructionSelector::selectAtomicRMW(Register 
ResVReg,
   uint32_t Scope = static_cast<uint32_t>(
       getMemScope(STI.getTargetTriple(), GR.CurMF->getFunction().getContext(),
                   MemOp->getSyncScopeID()));
-  Register ScopeReg = buildI32Constant(Scope, I);
+  Register ScopeReg = buildI32ConstantInEntryBlock(Scope, I);
 
   Register Ptr = I.getOperand(1).getReg();
   uint32_t ScSem = static_cast<uint32_t>(
       getMemSemanticsForStorageClass(GR.getPointerStorageClass(Ptr)));
   AtomicOrdering AO = MemOp->getSuccessOrdering();
   uint32_t OrderSem = static_cast<uint32_t>(getMemSemantics(AO));
-  Register MemSemReg = buildI32Constant(
+  Register MemSemReg = buildI32ConstantInEntryBlock(
       getMemSemanticsWithStorageClass(STI.getTargetTriple(), OrderSem, ScSem),
       I);
 
@@ -3709,12 +3709,12 @@ bool 
SPIRVInstructionSelector::selectBarrierInst(MachineInstr &I,
 
   // OpControlBarrier needs to also set Execution Scope
   if (WithGroupSync) {
-    Register ExecReg = buildI32Constant(SPIRV::Scope::Workgroup, I);
+    Register ExecReg = buildI32ConstantInEntryBlock(SPIRV::Scope::Workgroup, 
I);
     MI.addUse(ExecReg);
   }
 
-  Register ScopeReg = buildI32Constant(Scope, I);
-  Register MemSemReg = buildI32Constant(MemSem, I);
+  Register ScopeReg = buildI32ConstantInEntryBlock(Scope, I);
+  Register MemSemReg = buildI32ConstantInEntryBlock(MemSem, I);
 
   MI.addUse(ScopeReg).addUse(MemSemReg).constrainAllUses(TII, TRI, RBI);
   return true;
@@ -6027,7 +6027,7 @@ bool 
SPIRVInstructionSelector::selectUpdateCounter(Register &ResVReg,
   SPIRVTypeInst IntPtrType = GR.getOrCreateSPIRVPointerType(
       LLVMIntType, MIRBuilder, SPIRV::StorageClass::StorageBuffer);
 
-  Register Zero = buildI32Constant(0, I);
+  Register Zero = buildI32ConstantInEntryBlock(0, I);
 
   Register PtrToCounter =
       MRI->createVirtualRegister(GR.getRegClass(IntPtrType));
@@ -6040,11 +6040,11 @@ bool 
SPIRVInstructionSelector::selectUpdateCounter(Register &ResVReg,
 
   // For UAV/SSBO counters, the scope is Device. The counter variable is not
   // used as a flag. So the memory semantics can be None.
-  Register Scope = buildI32Constant(SPIRV::Scope::Device, I);
-  Register Semantics = buildI32Constant(SPIRV::MemorySemantics::None, I);
+  Register Scope = buildI32ConstantInEntryBlock(SPIRV::Scope::Device, I);
+  Register Semantics = 
buildI32ConstantInEntryBlock(SPIRV::MemorySemantics::None, I);
 
   int64_t IncrVal = getIConstValSext(IncrReg, MRI);
-  Register Incr = buildI32Constant(static_cast<uint32_t>(IncrVal), I);
+  Register Incr = buildI32ConstantInEntryBlock(static_cast<uint32_t>(IncrVal), 
I);
 
   Register AtomicRes = MRI->createVirtualRegister(GR.getRegClass(ResType));
   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpAtomicIAdd))
diff --git 
a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all_memory_barrier_with_group_sync.ll 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all_memory_barrier_with_group_sync.ll
index b39c305b45a075..af0fe2f8b9b467 100644
--- 
a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all_memory_barrier_with_group_sync.ll
+++ 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all_memory_barrier_with_group_sync.ll
@@ -6,9 +6,9 @@
 define void @test_all_memory_barrier_with_group_sync() #0 {
 entry:
   ; CHECK: %[[#TY:]] = OpTypeInt 32 0
+  ; CHECK-DAG: %[[#MEM_SEM:]] = OpConstant %[[#TY]] 2376
   ; CHECK-DAG: %[[#EXEC_SCOPE:]] = OpConstant %[[#TY]] 2
   ; CHECK-DAG: %[[#MEM_SCOPE:]] = OpConstant %[[#TY]] 1
-  ; CHECK-DAG: %[[#MEM_SEM:]] = OpConstant %[[#TY]] 2376
   ; CHECK: OpControlBarrier %[[#EXEC_SCOPE]] %[[#MEM_SCOPE]] %[[#MEM_SEM]]
   call void @llvm.spv.all.memory.barrier.with.group.sync()
   ret void
diff --git 
a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/device_memory_barrier_with_group_sync.ll
 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/device_memory_barrier_with_group_sync.ll
index 08eb0ed5706a51..614dfb636ed4c1 100644
--- 
a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/device_memory_barrier_with_group_sync.ll
+++ 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/device_memory_barrier_with_group_sync.ll
@@ -6,9 +6,9 @@
 define void @test_device_memory_barrier_with_group_sync() #0 {
 entry:
   ; CHECK: %[[#TY:]] = OpTypeInt 32 0
+  ; CHECK-DAG: %[[#MEM_SEM:]] = OpConstant %[[#TY]] 2120
   ; CHECK-DAG: %[[#EXEC_SCOPE:]] = OpConstant %[[#TY]] 2
   ; CHECK-DAG: %[[#MEM_SCOPE:]] = OpConstant %[[#TY]] 1
-  ; CHECK-DAG: %[[#MEM_SEM:]] = OpConstant %[[#TY]] 2120
   ; CHECK: OpControlBarrier %[[#EXEC_SCOPE]] %[[#MEM_SCOPE]] %[[#MEM_SEM]]
   call void @llvm.spv.device.memory.barrier.with.group.sync()
   ret void
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier.ll 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier.ll
index 987e7b57662c90..a045c8a00f4ed0 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier.ll
@@ -6,8 +6,8 @@
 define void @test_group_memory_barrier() #0 {
 entry:
   ; CHECK: %[[#TY:]] = OpTypeInt 32 0
-  ; CHECK-DAG: %[[#MEM_SCOPE:]] = OpConstant %[[#TY]] 2
   ; CHECK-DAG: %[[#MEM_SEM:]] = OpConstant %[[#TY]] 264
+  ; CHECK-DAG: %[[#MEM_SCOPE:]] = OpConstant %[[#TY]] 2
   ; CHECK: OpMemoryBarrier %[[#MEM_SCOPE]] %[[#MEM_SEM]]
   call void @llvm.spv.group.memory.barrier()
   ret void
diff --git 
a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier_with_group_sync.ll
 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier_with_group_sync.ll
index 0ecd0a053ae3b9..3dcd21ef64be72 100644
--- 
a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier_with_group_sync.ll
+++ 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/group_memory_barrier_with_group_sync.ll
@@ -6,8 +6,8 @@
 define void @test_group_memory_barrier_with_group_sync() #0 {
 entry:
   ; CHECK: %[[#TY:]] = OpTypeInt 32 0
-  ; CHECK-DAG: %[[#EXEC_AND_MEM_SCOPE:]] = OpConstant %[[#TY]] 2
   ; CHECK-DAG: %[[#MEM_SEM:]] = OpConstant %[[#TY]] 264
+  ; CHECK-DAG: %[[#EXEC_AND_MEM_SCOPE:]] = OpConstant %[[#TY]] 2
   ; CHECK: OpControlBarrier %[[#EXEC_AND_MEM_SCOPE]] %[[#EXEC_AND_MEM_SCOPE]] 
%[[#MEM_SEM]]
   call void @llvm.spv.group.memory.barrier.with.group.sync()
   ret void

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

Reply via email to