[llvm] [MemProf] Support cold-only and min hint when optimizing existing hot/cold new (PR #218803)

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 25 19:52:21 PDT 2026


https://github.com/teresajohnson updated https://github.com/llvm/llvm-project/pull/218803

>From f517aa2396478669ab658b98e0f20b30adb65141 Mon Sep 17 00:00:00 2001
From: Teresa Johnson <tejohnson at google.com>
Date: Tue, 25 Aug 2026 15:09:34 -0700
Subject: [PATCH 1/3] [MemProf] Support cold-only and min hint when optimizing
 existing hot/cold new

Change -optimize-existing-hot-cold-new to an enum option supporting:
- none (default): Do not optimize existing hot/cold new calls
- cold: Only optimize existing hot/cold new calls if determined to be cold
- always: Always optimize existing hot/cold new calls

Add a new option -min-existing-hot-cold-new-hint (off by default) that,
when optimizing an existing hot/cold operator new call, takes the minimum
of the compiler hint and the existing hint. If the existing hint is a
compile-time constant, the minimum is computed at compile time; otherwise,
an llvm.umin intrinsic is emitted.
---
 .../llvm/Transforms/Utils/BuildLibCalls.h     |  13 +-
 llvm/lib/Transforms/Utils/BuildLibCalls.cpp   |  26 ++--
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 142 ++++++++++++------
 .../InstCombine/simplify-libcalls-new.ll      |  64 +++++++-
 4 files changed, 174 insertions(+), 71 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
index f53e7d056ca9f..67b4ff985db63 100644
--- a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -284,27 +284,26 @@ namespace llvm {
   /// Emit a call to the hot/cold operator new function.
   LLVM_ABI Value *emitHotColdNew(Value *Num, IRBuilderBase &B,
                                  const TargetLibraryInfo *TLI, LibFunc NewFunc,
-                                 uint8_t HotCold);
+                                 Value *HotCold);
   LLVM_ABI Value *emitHotColdNewNoThrow(Value *Num, Value *NoThrow,
                                         IRBuilderBase &B,
                                         const TargetLibraryInfo *TLI,
-                                        LibFunc NewFunc, uint8_t HotCold);
+                                        LibFunc NewFunc, Value *HotCold);
   LLVM_ABI Value *emitHotColdNewAligned(Value *Num, Value *Align,
                                         IRBuilderBase &B,
                                         const TargetLibraryInfo *TLI,
-                                        LibFunc NewFunc, uint8_t HotCold);
+                                        LibFunc NewFunc, Value *HotCold);
   LLVM_ABI Value *emitHotColdNewAlignedNoThrow(Value *Num, Value *Align,
                                                Value *NoThrow, IRBuilderBase &B,
                                                const TargetLibraryInfo *TLI,
-                                               LibFunc NewFunc,
-                                               uint8_t HotCold);
+                                               LibFunc NewFunc, Value *HotCold);
   LLVM_ABI Value *emitHotColdSizeReturningNew(Value *Num, IRBuilderBase &B,
                                               const TargetLibraryInfo *TLI,
-                                              LibFunc NewFunc, uint8_t HotCold);
+                                              LibFunc NewFunc, Value *HotCold);
   LLVM_ABI Value *
   emitHotColdSizeReturningNewAligned(Value *Num, Value *Align, IRBuilderBase &B,
                                      const TargetLibraryInfo *TLI,
-                                     LibFunc NewFunc, uint8_t HotCold);
+                                     LibFunc NewFunc, Value *HotCold);
 }
 
 #endif
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 0afcc9df40070..e9ef993e71ec1 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -2160,7 +2160,7 @@ Value *llvm::emitCalloc(Value *Num, Value *Size, IRBuilderBase &B,
 Value *llvm::emitHotColdSizeReturningNew(Value *Num, IRBuilderBase &B,
                                          const TargetLibraryInfo *TLI,
                                          LibFunc SizeFeedbackNewFunc,
-                                         uint8_t HotCold) {
+                                         Value *HotCold) {
   Module *M = B.GetInsertBlock()->getModule();
   if (!isLibFuncEmittable(M, TLI, SizeFeedbackNewFunc))
     return nullptr;
@@ -2173,7 +2173,7 @@ Value *llvm::emitHotColdSizeReturningNew(Value *Num, IRBuilderBase &B,
   FunctionCallee Func =
       M->getOrInsertFunction(Name, SizedPtrT, Num->getType(), B.getInt8Ty());
   inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
-  CallInst *CI = B.CreateCall(Func, {Num, B.getInt8(HotCold)}, "sized_ptr");
+  CallInst *CI = B.CreateCall(Func, {Num, HotCold}, "sized_ptr");
 
   if (const Function *F = dyn_cast<Function>(Func.getCallee()))
     CI->setCallingConv(F->getCallingConv());
@@ -2185,7 +2185,7 @@ Value *llvm::emitHotColdSizeReturningNewAligned(Value *Num, Value *Align,
                                                 IRBuilderBase &B,
                                                 const TargetLibraryInfo *TLI,
                                                 LibFunc SizeFeedbackNewFunc,
-                                                uint8_t HotCold) {
+                                                Value *HotCold) {
   Module *M = B.GetInsertBlock()->getModule();
   if (!isLibFuncEmittable(M, TLI, SizeFeedbackNewFunc))
     return nullptr;
@@ -2198,8 +2198,7 @@ Value *llvm::emitHotColdSizeReturningNewAligned(Value *Num, Value *Align,
   FunctionCallee Func = M->getOrInsertFunction(Name, SizedPtrT, Num->getType(),
                                                Align->getType(), B.getInt8Ty());
   inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
-  CallInst *CI =
-      B.CreateCall(Func, {Num, Align, B.getInt8(HotCold)}, "sized_ptr");
+  CallInst *CI = B.CreateCall(Func, {Num, Align, HotCold}, "sized_ptr");
 
   if (const Function *F = dyn_cast<Function>(Func.getCallee()))
     CI->setCallingConv(F->getCallingConv());
@@ -2209,7 +2208,7 @@ Value *llvm::emitHotColdSizeReturningNewAligned(Value *Num, Value *Align,
 
 Value *llvm::emitHotColdNew(Value *Num, IRBuilderBase &B,
                             const TargetLibraryInfo *TLI, LibFunc NewFunc,
-                            uint8_t HotCold) {
+                            Value *HotCold) {
   Module *M = B.GetInsertBlock()->getModule();
   if (!isLibFuncEmittable(M, TLI, NewFunc))
     return nullptr;
@@ -2218,7 +2217,7 @@ Value *llvm::emitHotColdNew(Value *Num, IRBuilderBase &B,
   FunctionCallee Func =
       M->getOrInsertFunction(Name, B.getPtrTy(), Num->getType(), B.getInt8Ty());
   inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
-  CallInst *CI = B.CreateCall(Func, {Num, B.getInt8(HotCold)}, Name);
+  CallInst *CI = B.CreateCall(Func, {Num, HotCold}, Name);
 
   if (const Function *F =
           dyn_cast<Function>(Func.getCallee()->stripPointerCasts()))
@@ -2229,7 +2228,7 @@ Value *llvm::emitHotColdNew(Value *Num, IRBuilderBase &B,
 
 Value *llvm::emitHotColdNewNoThrow(Value *Num, Value *NoThrow, IRBuilderBase &B,
                                    const TargetLibraryInfo *TLI,
-                                   LibFunc NewFunc, uint8_t HotCold) {
+                                   LibFunc NewFunc, Value *HotCold) {
   Module *M = B.GetInsertBlock()->getModule();
   if (!isLibFuncEmittable(M, TLI, NewFunc))
     return nullptr;
@@ -2238,7 +2237,7 @@ Value *llvm::emitHotColdNewNoThrow(Value *Num, Value *NoThrow, IRBuilderBase &B,
   FunctionCallee Func = M->getOrInsertFunction(
       Name, B.getPtrTy(), Num->getType(), NoThrow->getType(), B.getInt8Ty());
   inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
-  CallInst *CI = B.CreateCall(Func, {Num, NoThrow, B.getInt8(HotCold)}, Name);
+  CallInst *CI = B.CreateCall(Func, {Num, NoThrow, HotCold}, Name);
 
   if (const Function *F =
           dyn_cast<Function>(Func.getCallee()->stripPointerCasts()))
@@ -2249,7 +2248,7 @@ Value *llvm::emitHotColdNewNoThrow(Value *Num, Value *NoThrow, IRBuilderBase &B,
 
 Value *llvm::emitHotColdNewAligned(Value *Num, Value *Align, IRBuilderBase &B,
                                    const TargetLibraryInfo *TLI,
-                                   LibFunc NewFunc, uint8_t HotCold) {
+                                   LibFunc NewFunc, Value *HotCold) {
   Module *M = B.GetInsertBlock()->getModule();
   if (!isLibFuncEmittable(M, TLI, NewFunc))
     return nullptr;
@@ -2258,7 +2257,7 @@ Value *llvm::emitHotColdNewAligned(Value *Num, Value *Align, IRBuilderBase &B,
   FunctionCallee Func = M->getOrInsertFunction(
       Name, B.getPtrTy(), Num->getType(), Align->getType(), B.getInt8Ty());
   inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
-  CallInst *CI = B.CreateCall(Func, {Num, Align, B.getInt8(HotCold)}, Name);
+  CallInst *CI = B.CreateCall(Func, {Num, Align, HotCold}, Name);
 
   if (const Function *F =
           dyn_cast<Function>(Func.getCallee()->stripPointerCasts()))
@@ -2270,7 +2269,7 @@ Value *llvm::emitHotColdNewAligned(Value *Num, Value *Align, IRBuilderBase &B,
 Value *llvm::emitHotColdNewAlignedNoThrow(Value *Num, Value *Align,
                                           Value *NoThrow, IRBuilderBase &B,
                                           const TargetLibraryInfo *TLI,
-                                          LibFunc NewFunc, uint8_t HotCold) {
+                                          LibFunc NewFunc, Value *HotCold) {
   Module *M = B.GetInsertBlock()->getModule();
   if (!isLibFuncEmittable(M, TLI, NewFunc))
     return nullptr;
@@ -2280,8 +2279,7 @@ Value *llvm::emitHotColdNewAlignedNoThrow(Value *Num, Value *Align,
       Name, B.getPtrTy(), Num->getType(), Align->getType(), NoThrow->getType(),
       B.getInt8Ty());
   inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
-  CallInst *CI =
-      B.CreateCall(Func, {Num, Align, NoThrow, B.getInt8(HotCold)}, Name);
+  CallInst *CI = B.CreateCall(Func, {Num, Align, NoThrow, HotCold}, Name);
 
   if (const Function *F =
           dyn_cast<Function>(Func.getCallee()->stripPointerCasts()))
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 44a3cbca85d0c..0275d01fed134 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -57,13 +57,36 @@ static cl::opt<bool>
 static cl::opt<bool>
     OptimizeHotColdNew("optimize-hot-cold-new", cl::Hidden, cl::init(false),
                        cl::desc("Enable hot/cold operator new library calls"));
-static cl::opt<bool> OptimizeExistingHotColdNew(
-    "optimize-existing-hot-cold-new", cl::Hidden, cl::init(false),
+enum class OptimizeExistingHotColdNewKind {
+  None,
+  Cold,
+  Always,
+};
+static cl::opt<OptimizeExistingHotColdNewKind> OptimizeExistingHotColdNew(
+    "optimize-existing-hot-cold-new", cl::Hidden,
     cl::desc(
-        "Enable optimization of existing hot/cold operator new library calls"));
+        "Enable optimization of existing hot/cold operator new library calls"),
+    cl::values(
+        clEnumValN(
+            OptimizeExistingHotColdNewKind::None, "none",
+            "Do not optimize existing hot/cold operator new library calls"),
+        clEnumValN(OptimizeExistingHotColdNewKind::Cold, "cold",
+                   "Only optimize existing hot/cold operator new library calls "
+                   "if determined to be cold"),
+        clEnumValN(
+            OptimizeExistingHotColdNewKind::Always, "always",
+            "Always optimize existing hot/cold operator new library calls"),
+        clEnumValN(
+            OptimizeExistingHotColdNewKind::Always, "",
+            "Always optimize existing hot/cold operator new library calls")),
+    cl::init(OptimizeExistingHotColdNewKind::None), cl::ValueOptional);
 static cl::opt<bool> OptimizeNoBuiltinHotColdNew(
     "optimize-nobuiltin-hot-cold-new-new", cl::Hidden, cl::init(false),
     cl::desc("Enable transformation of nobuiltin operator new library calls"));
+static cl::opt<bool> MinExistingHotColdNewHint(
+    "min-existing-hot-cold-new-hint", cl::Hidden, cl::init(false),
+    cl::desc("Take the minimum of compiler hint and existing hint when "
+             "optimizing existing hot/cold operator new library calls"));
 
 namespace {
 
@@ -1777,7 +1800,7 @@ Value *LibCallSimplifier::maybeOptimizeNoBuiltinOperatorNew(CallInst *CI,
   case LibFunc_size_returning_new_aligned_hot_cold:
     // If the nobuiltin call already passes a hot_cold_t parameter, allow update
     // of that parameter when enabled.
-    if (!OptimizeExistingHotColdNew)
+    if (OptimizeExistingHotColdNew == OptimizeExistingHotColdNewKind::None)
       return nullptr;
     break;
   default:
@@ -1796,10 +1819,12 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
     return nullptr;
 
   uint8_t HotCold;
-  if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "cold")
+  bool IsCold = false;
+  if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "cold") {
     HotCold = ColdNewHintValue;
-  else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() ==
-           "notcold")
+    IsCold = true;
+  } else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() ==
+             "notcold")
     HotCold = NotColdNewHintValue;
   else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "hot")
     HotCold = HotNewHintValue;
@@ -1809,6 +1834,24 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
   else
     return nullptr;
 
+  bool ShouldOptimizeExisting =
+      OptimizeExistingHotColdNew == OptimizeExistingHotColdNewKind::Always ||
+      (OptimizeExistingHotColdNew == OptimizeExistingHotColdNewKind::Cold &&
+       IsCold);
+
+  Value *HotColdVal = B.getInt8(HotCold);
+  auto getHotColdHintForExisting = [&](uint8_t HotCold) -> Value * {
+    if (!MinExistingHotColdNewHint)
+      return HotColdVal;
+    Value *ExistingHint = CI->getArgOperand(CI->arg_size() - 1);
+    if (auto *CIHint = dyn_cast<ConstantInt>(ExistingHint))
+      return B.getInt8(
+          std::min(HotCold, static_cast<uint8_t>(CIHint->getZExtValue())));
+    if (ExistingHint->getType() != B.getInt8Ty())
+      ExistingHint = B.CreateTruncOrBitCast(ExistingHint, B.getInt8Ty());
+    return B.CreateBinaryIntrinsic(Intrinsic::umin, ExistingHint, HotColdVal);
+  };
+
   // For calls that already pass a hot/cold hint, only update the hint if
   // directed by OptimizeExistingHotColdNew. For other calls to new, add a hint
   // if cold or hot, and leave as-is for default handling if "notcold" aka warm.
@@ -1819,112 +1862,121 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
   Value *NewCall = nullptr;
   switch (Func) {
   case LibFunc_Znwm12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
+    if (ShouldOptimizeExisting)
       NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI,
-                               LibFunc_Znwm12__hot_cold_t, HotCold);
+                               LibFunc_Znwm12__hot_cold_t,
+                               getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_Znwm:
     NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI,
-                             LibFunc_Znwm12__hot_cold_t, HotCold);
+                             LibFunc_Znwm12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_Znam12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
+    if (ShouldOptimizeExisting)
       NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI,
-                               LibFunc_Znam12__hot_cold_t, HotCold);
+                               LibFunc_Znam12__hot_cold_t,
+                               getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_Znam:
     NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI,
-                             LibFunc_Znam12__hot_cold_t, HotCold);
+                             LibFunc_Znam12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
-      NewCall = emitHotColdNewNoThrow(
-          CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-          LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);
+    if (ShouldOptimizeExisting)
+      NewCall =
+          emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B,
+                                TLI, LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t,
+                                getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_ZnwmRKSt9nothrow_t:
     NewCall = emitHotColdNewNoThrow(
         CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-        LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);
+        LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
-      NewCall = emitHotColdNewNoThrow(
-          CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-          LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);
+    if (ShouldOptimizeExisting)
+      NewCall =
+          emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B,
+                                TLI, LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t,
+                                getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_ZnamRKSt9nothrow_t:
     NewCall = emitHotColdNewNoThrow(
         CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-        LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);
+        LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
-      NewCall = emitHotColdNewAligned(
-          CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-          LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);
+    if (ShouldOptimizeExisting)
+      NewCall =
+          emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B,
+                                TLI, LibFunc_ZnwmSt11align_val_t12__hot_cold_t,
+                                getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_ZnwmSt11align_val_t:
     NewCall = emitHotColdNewAligned(
         CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-        LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);
+        LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
-      NewCall = emitHotColdNewAligned(
-          CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-          LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);
+    if (ShouldOptimizeExisting)
+      NewCall =
+          emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B,
+                                TLI, LibFunc_ZnamSt11align_val_t12__hot_cold_t,
+                                getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_ZnamSt11align_val_t:
     NewCall = emitHotColdNewAligned(
         CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-        LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);
+        LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
+    if (ShouldOptimizeExisting)
       NewCall = emitHotColdNewAlignedNoThrow(
           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
           TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
-          HotCold);
+          getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
     NewCall = emitHotColdNewAlignedNoThrow(
         CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
-        TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold);
+        TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
+        HotColdVal);
     break;
   case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
-    if (OptimizeExistingHotColdNew)
+    if (ShouldOptimizeExisting)
       NewCall = emitHotColdNewAlignedNoThrow(
           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
           TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
-          HotCold);
+          getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
     NewCall = emitHotColdNewAlignedNoThrow(
         CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
-        TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold);
+        TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
+        HotColdVal);
     break;
   case LibFunc_size_returning_new:
     NewCall = emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI,
                                           LibFunc_size_returning_new_hot_cold,
-                                          HotCold);
+                                          HotColdVal);
     break;
   case LibFunc_size_returning_new_hot_cold:
-    if (OptimizeExistingHotColdNew)
+    if (ShouldOptimizeExisting)
       NewCall = emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI,
                                             LibFunc_size_returning_new_hot_cold,
-                                            HotCold);
+                                            getHotColdHintForExisting(HotCold));
     break;
   case LibFunc_size_returning_new_aligned:
     NewCall = emitHotColdSizeReturningNewAligned(
         CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-        LibFunc_size_returning_new_aligned_hot_cold, HotCold);
+        LibFunc_size_returning_new_aligned_hot_cold, HotColdVal);
     break;
   case LibFunc_size_returning_new_aligned_hot_cold:
-    if (OptimizeExistingHotColdNew)
+    if (ShouldOptimizeExisting)
       NewCall = emitHotColdSizeReturningNewAligned(
           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
-          LibFunc_size_returning_new_aligned_hot_cold, HotCold);
+          LibFunc_size_returning_new_aligned_hot_cold,
+          getHotColdHintForExisting(HotCold));
     break;
   default:
     return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll
index 2765c75f4d5e0..545df33a389ff 100644
--- a/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll
@@ -6,18 +6,24 @@
 ; OFF-LABEL: @new_hot_cold()
 
 ;; First check with the default hint values (254 = -2, 128 = -128, 222 = -34).
-; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF -DCOLD=1 -DHOT=-2 -DNOTCOLD=-128 -DAMBIG=-34 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,MIN-OFF -DCOLD=1 -DHOT=-2 -DNOTCOLD=-128 -DAMBIG=-34 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=2 -DMINCOLD2=7 -DMINHOT1=-6 -DMINHOT2=50
 
 ;; Next check with the non-default cold and hot hint values (200 =-56).
-; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -hot-new-hint-value=200 -notcold-new-hint-value=99 -ambiguous-new-hint-value=44 -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF -DCOLD=5 -DHOT=-56 -DAMBIG=44 -DNOTCOLD=99 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -hot-new-hint-value=200 -notcold-new-hint-value=99 -ambiguous-new-hint-value=44 -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,MIN-OFF -DCOLD=5 -DHOT=-56 -DAMBIG=44 -DNOTCOLD=99 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=2 -DMINCOLD2=7 -DMINHOT1=-6 -DMINHOT2=50
 
 ;; Next check with the same non-default cold and hot hint values (200 =-56),
 ;; but with transformation of nobuiltin calls enabled.
-; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -optimize-nobuiltin-hot-cold-new-new -cold-new-hint-value=5 -hot-new-hint-value=200 -notcold-new-hint-value=99 -ambiguous-new-hint-value=44 -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-ON -DCOLD=5 -DHOT=-56 -DAMBIG=44 -DNOTCOLD=99 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -optimize-nobuiltin-hot-cold-new-new -cold-new-hint-value=5 -hot-new-hint-value=200 -notcold-new-hint-value=99 -ambiguous-new-hint-value=44 -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-ON,MIN-OFF -DCOLD=5 -DHOT=-56 -DAMBIG=44 -DNOTCOLD=99 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=2 -DMINCOLD2=7 -DMINHOT1=-6 -DMINHOT2=50
 
 ;; Try again with the non-default cold and hot hint values (200 =-56), and this
-;; time specify that existing hints should be updated.
-; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=5 -DPREVHINTNOTCOLD=100 -DPREVHINTHOT=-56 -DPREVHINTAMBIG=44
+;; time specify that existing hints should be updated (using default/implicit value,
+;; explicit always, cold, none, and with min hint enabled).
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,NO-MIN-ALWAYS -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=5 -DPREVHINTNOTCOLD=100 -DPREVHINTHOT=-56 -DPREVHINTAMBIG=44 -DMINCOLD1=5 -DMINCOLD2=5 -DMINHOT1=-56 -DMINHOT2=-56
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new=always -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,NO-MIN-ALWAYS -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=5 -DPREVHINTNOTCOLD=100 -DPREVHINTHOT=-56 -DPREVHINTAMBIG=44 -DMINCOLD1=5 -DMINCOLD2=5 -DMINHOT1=-56 -DMINHOT2=-56
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new=cold -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,NO-MIN-COLD -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=5 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=5 -DMINCOLD2=5 -DMINHOT1=-6 -DMINHOT2=50
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new=none -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,MIN-OFF -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=7 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=2 -DMINCOLD2=7 -DMINHOT1=-6 -DMINHOT2=50
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new -min-existing-hot-cold-new-hint -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,MIN-ALWAYS -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=5 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=2 -DMINCOLD2=5 -DMINHOT1=-56 -DMINHOT2=50
+; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=5 -notcold-new-hint-value=100 -hot-new-hint-value=200 -ambiguous-new-hint-value=44 -optimize-existing-hot-cold-new=cold -min-existing-hot-cold-new-hint -S | FileCheck %s --check-prefixes=HOTCOLD,NOBUILTIN-OFF,MIN-COLD -DCOLD=5 -DHOT=-56 -DNOTCOLD=100 -DAMBIG=44 -DPREVHINTCOLD=5 -DPREVHINTNOTCOLD=7 -DPREVHINTHOT=7 -DPREVHINTAMBIG=7 -DMINCOLD1=2 -DMINCOLD2=5 -DMINHOT1=-6 -DMINHOT2=50
 
 ;; Make sure that values not in 0..255 are flagged with an error
 ; RUN: not opt < %s -passes=instcombine -optimize-hot-cold-new -cold-new-hint-value=256 -S 2>&1 | FileCheck %s --check-prefix=ERROR
@@ -620,6 +626,54 @@ define void @new_alloc_token() {
   ret void
 }
 
+;; Check that -min-existing-hot-cold-new-hint takes the min of existing and compiler hints.
+; HOTCOLD-LABEL: @new_hot_cold_min()
+define void @new_hot_cold_min() {
+  ;; Existing hint 2 < cold hint 5 -> min is 2
+  ; HOTCOLD: @_Znwm12__hot_cold_t(i64 10, i8 [[MINCOLD1]])
+  %call = call ptr @_Znwm12__hot_cold_t(i64 10, i8 2) #0
+  call void @dummy(ptr %call)
+  ;; Existing hint 7 > cold hint 5 -> min is 5
+  ; HOTCOLD: @_Znwm12__hot_cold_t(i64 10, i8 [[MINCOLD2]])
+  %call1 = call ptr @_Znwm12__hot_cold_t(i64 10, i8 7) #0
+  call void @dummy(ptr %call1)
+  ;; Existing hint 250 > hot hint 200 (-56) -> min is 200 (-56)
+  ; HOTCOLD: @_Znwm12__hot_cold_t(i64 10, i8 [[MINHOT1]])
+  %call2 = call ptr @_Znwm12__hot_cold_t(i64 10, i8 -6) #2
+  call void @dummy(ptr %call2)
+  ;; Existing hint 50 < hot hint 200 (-56) -> min is 50
+  ; HOTCOLD: @_Znwm12__hot_cold_t(i64 10, i8 [[MINHOT2]])
+  %call3 = call ptr @_Znwm12__hot_cold_t(i64 10, i8 50) #2
+  call void @dummy(ptr %call3)
+  ret void
+}
+
+;; Check that -min-existing-hot-cold-new-hint handles non-constant dynamic hints with umin intrinsic.
+; HOTCOLD-LABEL: @new_hot_cold_dynamic(
+; HOTCOLD-SAME: i8 [[HINT:%[a-zA-Z0-9_]+]])
+define void @new_hot_cold_dynamic(i8 %hint) {
+  ;; Cold allocation
+  ; MIN-OFF: @_Znwm12__hot_cold_t(i64 10, i8 [[HINT]])
+  ; NO-MIN-ALWAYS: @_Znwm12__hot_cold_t(i64 10, i8 [[COLD]])
+  ; NO-MIN-COLD: @_Znwm12__hot_cold_t(i64 10, i8 [[COLD]])
+  ; MIN-ALWAYS: [[UMIN:%[a-zA-Z0-9_]+]] = call i8 @llvm.umin.i8(i8 [[HINT]], i8 [[COLD]])
+  ; MIN-ALWAYS: @_Znwm12__hot_cold_t(i64 10, i8 [[UMIN]])
+  ; MIN-COLD: [[UMIN:%[a-zA-Z0-9_]+]] = call i8 @llvm.umin.i8(i8 [[HINT]], i8 [[COLD]])
+  ; MIN-COLD: @_Znwm12__hot_cold_t(i64 10, i8 [[UMIN]])
+  %call = call ptr @_Znwm12__hot_cold_t(i64 10, i8 %hint) #0
+  call void @dummy(ptr %call)
+  ;; Hot allocation
+  ; MIN-OFF: @_Znwm12__hot_cold_t(i64 10, i8 [[HINT]])
+  ; NO-MIN-ALWAYS: @_Znwm12__hot_cold_t(i64 10, i8 [[HOT]])
+  ; NO-MIN-COLD: @_Znwm12__hot_cold_t(i64 10, i8 [[HINT]])
+  ; MIN-ALWAYS: [[UMIN2:%[a-zA-Z0-9_]+]] = call i8 @llvm.umin.i8(i8 [[HINT]], i8 [[HOT]])
+  ; MIN-ALWAYS: @_Znwm12__hot_cold_t(i64 10, i8 [[UMIN2]])
+  ; MIN-COLD: @_Znwm12__hot_cold_t(i64 10, i8 [[HINT]])
+  %call1 = call ptr @_Znwm12__hot_cold_t(i64 10, i8 %hint) #2
+  call void @dummy(ptr %call1)
+  ret void
+}
+
 ;; So that instcombine doesn't optimize out the call.
 declare void @dummy(ptr)
 

>From 59bc4913ef55ecfefafef3dd51ddb103d99d0bda Mon Sep 17 00:00:00 2001
From: Teresa Johnson <tejohnson at google.com>
Date: Tue, 25 Aug 2026 17:09:38 -0700
Subject: [PATCH 2/3] Address comments

---
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 27 +++++++++++--------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 0275d01fed134..41c7da8592ec7 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1834,19 +1834,24 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
   else
     return nullptr;
 
-  bool ShouldOptimizeExisting =
+  bool ShouldOptimizeExistingHotColdNew =
       OptimizeExistingHotColdNew == OptimizeExistingHotColdNewKind::Always ||
       (OptimizeExistingHotColdNew == OptimizeExistingHotColdNewKind::Cold &&
        IsCold);
 
   Value *HotColdVal = B.getInt8(HotCold);
   auto getHotColdHintForExisting = [&](uint8_t HotCold) -> Value * {
+    // If not taking the minimum, simply use the compiler hint value.
     if (!MinExistingHotColdNewHint)
       return HotColdVal;
     Value *ExistingHint = CI->getArgOperand(CI->arg_size() - 1);
+    // If the existing hint is a compile-time constant, evaluate the minimum
+    // at compile time.
     if (auto *CIHint = dyn_cast<ConstantInt>(ExistingHint))
       return B.getInt8(
           std::min(HotCold, static_cast<uint8_t>(CIHint->getZExtValue())));
+    // If the existing hint is a dynamic/runtime value, emit a umin intrinsic
+    // to compute the minimum at runtime.
     if (ExistingHint->getType() != B.getInt8Ty())
       ExistingHint = B.CreateTruncOrBitCast(ExistingHint, B.getInt8Ty());
     return B.CreateBinaryIntrinsic(Intrinsic::umin, ExistingHint, HotColdVal);
@@ -1862,7 +1867,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
   Value *NewCall = nullptr;
   switch (Func) {
   case LibFunc_Znwm12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI,
                                LibFunc_Znwm12__hot_cold_t,
                                getHotColdHintForExisting(HotCold));
@@ -1872,7 +1877,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
                              LibFunc_Znwm12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_Znam12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall = emitHotColdNew(CI->getArgOperand(0), B, TLI,
                                LibFunc_Znam12__hot_cold_t,
                                getHotColdHintForExisting(HotCold));
@@ -1882,7 +1887,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
                              LibFunc_Znam12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall =
           emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B,
                                 TLI, LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t,
@@ -1894,7 +1899,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
         LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall =
           emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B,
                                 TLI, LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t,
@@ -1906,7 +1911,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
         LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall =
           emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B,
                                 TLI, LibFunc_ZnwmSt11align_val_t12__hot_cold_t,
@@ -1918,7 +1923,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
         LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall =
           emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B,
                                 TLI, LibFunc_ZnamSt11align_val_t12__hot_cold_t,
@@ -1930,7 +1935,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
         LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotColdVal);
     break;
   case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall = emitHotColdNewAlignedNoThrow(
           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
           TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
@@ -1943,7 +1948,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
         HotColdVal);
     break;
   case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall = emitHotColdNewAlignedNoThrow(
           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
           TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
@@ -1961,7 +1966,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
                                           HotColdVal);
     break;
   case LibFunc_size_returning_new_hot_cold:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall = emitHotColdSizeReturningNew(CI->getArgOperand(0), B, TLI,
                                             LibFunc_size_returning_new_hot_cold,
                                             getHotColdHintForExisting(HotCold));
@@ -1972,7 +1977,7 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
         LibFunc_size_returning_new_aligned_hot_cold, HotColdVal);
     break;
   case LibFunc_size_returning_new_aligned_hot_cold:
-    if (ShouldOptimizeExisting)
+    if (ShouldOptimizeExistingHotColdNew)
       NewCall = emitHotColdSizeReturningNewAligned(
           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
           LibFunc_size_returning_new_aligned_hot_cold,

>From 0544e48c8c4476952cf9e4b8806a3c7a60914775 Mon Sep 17 00:00:00 2001
From: Teresa Johnson <tejohnson at google.com>
Date: Tue, 25 Aug 2026 19:52:03 -0700
Subject: [PATCH 3/3] Address comments

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 41c7da8592ec7..1c92409b3379b 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1845,15 +1845,11 @@ Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
     if (!MinExistingHotColdNewHint)
       return HotColdVal;
     Value *ExistingHint = CI->getArgOperand(CI->arg_size() - 1);
-    // If the existing hint is a compile-time constant, evaluate the minimum
-    // at compile time.
-    if (auto *CIHint = dyn_cast<ConstantInt>(ExistingHint))
-      return B.getInt8(
-          std::min(HotCold, static_cast<uint8_t>(CIHint->getZExtValue())));
-    // If the existing hint is a dynamic/runtime value, emit a umin intrinsic
-    // to compute the minimum at runtime.
     if (ExistingHint->getType() != B.getInt8Ty())
       ExistingHint = B.CreateTruncOrBitCast(ExistingHint, B.getInt8Ty());
+    // Emit a umin intrinsic to take the minimum of the existing hint and the
+    // compiler hint. When the existing hint is a compile-time constant, the
+    // IRBuilder folder will automatically constant-fold this into a constant.
     return B.CreateBinaryIntrinsic(Intrinsic::umin, ExistingHint, HotColdVal);
   };
 



More information about the llvm-commits mailing list