diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -256,21 +256,46 @@ TLI_DEFINE_STRING_INTERNAL("_Znam") TLI_DEFINE_SIG_INTERNAL(Ptr, Long) +/// void *operator new[](unsigned long, hot_cold_t) +/// Currently this and other operator new interfaces that take a hot_cold_t +/// hint are supported by the open source version of tcmalloc, see: +/// https://github.com/google/tcmalloc/blob/master/tcmalloc/new_extension.h +/// and for the definition of the hot_cold_t parameter see: +/// https://github.com/google/tcmalloc/blob/master/tcmalloc/malloc_extension.h +TLI_DEFINE_ENUM_INTERNAL(Znam10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_Znam10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Bool) + /// void *operator new[](unsigned long, const std::nothrow_t&); TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t") TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Ptr) +/// void *operator new[](unsigned long, const std::nothrow_t&, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Ptr, Bool) + /// void *operator new[](unsigned long, std::align_val_t) TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_t) TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_t") TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long) +/// void *operator new[](unsigned long, std::align_val_t, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_t10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_t10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long, Bool) + /// void *operator new[](unsigned long, std::align_val_t, const std::nothrow_t&) TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_tRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_tRKSt9nothrow_t") TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long, Ptr) +/// void *operator new[](unsigned long, std::align_val_t, const std::nothrow_t&, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long, Ptr, Bool) + /// void *operator new(unsigned int); TLI_DEFINE_ENUM_INTERNAL(Znwj) TLI_DEFINE_STRING_INTERNAL("_Znwj") @@ -296,21 +321,41 @@ TLI_DEFINE_STRING_INTERNAL("_Znwm") TLI_DEFINE_SIG_INTERNAL(Ptr, Long) +/// void *operator new(unsigned long, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(Znwm10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_Znwm10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Bool) + /// void *operator new(unsigned long, const std::nothrow_t&); TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t") TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Ptr) +/// void *operator new(unsigned long, const std::nothrow_t&, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Ptr, Bool) + /// void *operator new(unsigned long, std::align_val_t) TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_t) TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_t") TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long) +/// void *operator new(unsigned long, std::align_val_t, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_t10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_t10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long, Bool) + /// void *operator new(unsigned long, std::align_val_t, const std::nothrow_t&) TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_tRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_tRKSt9nothrow_t") TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long, Ptr) +/// void *operator new(unsigned long, std::align_val_t, const std::nothrow_t&, hot_cold_t) +TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t") +TLI_DEFINE_SIG_INTERNAL(Ptr, Long, Long, Ptr, Bool) + /// double __acos_finite(double x); TLI_DEFINE_ENUM_INTERNAL(acos_finite) TLI_DEFINE_STRING_INTERNAL("__acos_finite") diff --git a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h --- a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -248,6 +248,21 @@ /// Emit a call to the calloc function. Value *emitCalloc(Value *Num, Value *Size, IRBuilderBase &B, const TargetLibraryInfo &TLI); + + /// Emit a call to the hot/cold operator new function. + Value *emitHotColdNew(Value *Num, IRBuilderBase &B, + const TargetLibraryInfo *TLI, LibFunc NewFunc, + uint8_t HotCold); + Value *emitHotColdNewNoThrow(Value *Num, Value *NoThrow, IRBuilderBase &B, + const TargetLibraryInfo *TLI, LibFunc NewFunc, + uint8_t HotCold); + Value *emitHotColdNewAligned(Value *Num, Value *Align, IRBuilderBase &B, + const TargetLibraryInfo *TLI, LibFunc NewFunc, + uint8_t HotCold); + Value *emitHotColdNewAlignedNoThrow(Value *Num, Value *Align, Value *NoThrow, + IRBuilderBase &B, + const TargetLibraryInfo *TLI, + LibFunc NewFunc, uint8_t HotCold); } #endif diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h --- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -181,6 +181,7 @@ Value *optimizeMemMove(CallInst *CI, IRBuilderBase &B); Value *optimizeMemSet(CallInst *CI, IRBuilderBase &B); Value *optimizeRealloc(CallInst *CI, IRBuilderBase &B); + Value *optimizeNew(CallInst *CI, IRBuilderBase &B, LibFunc &Func); Value *optimizeWcslen(CallInst *CI, IRBuilderBase &B); Value *optimizeBCopy(CallInst *CI, IRBuilderBase &B); diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -115,17 +115,25 @@ {LibFunc_ZnwjSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t) {LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned int, align_val_t, nothrow) {LibFunc_Znwm, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long) + {LibFunc_Znwm10hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, hot_cold_t) {LibFunc_ZnwmRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow) + {LibFunc_ZnwmRKSt9nothrow_t10hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new(unsigned long, nothrow, hot_cold_t) {LibFunc_ZnwmSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t) + {LibFunc_ZnwmSt11align_val_t10hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, hot_cold_t) {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, nothrow) + {LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new(unsigned long, align_val_t, nothrow, hot_cold_t) {LibFunc_Znaj, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int) {LibFunc_ZnajRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned int, nothrow) {LibFunc_ZnajSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t) {LibFunc_ZnajSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned int, align_val_t, nothrow) {LibFunc_Znam, {OpNewLike, 1, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long) + {LibFunc_Znam10hot_cold_t, {OpNewLike, 2, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, hot_cold_t) {LibFunc_ZnamRKSt9nothrow_t, {MallocLike, 2, 0, -1, -1, MallocFamily::CPPNewArray}}, // new[](unsigned long, nothrow) + {LibFunc_ZnamRKSt9nothrow_t10hot_cold_t, {MallocLike, 3, 0, -1, -1, MallocFamily::CPPNew}}, // new[](unsigned long, nothrow, hot_cold_t) {LibFunc_ZnamSt11align_val_t, {OpNewLike, 2, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t) + {LibFunc_ZnamSt11align_val_t10hot_cold_t, {OpNewLike, 3, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new[](unsigned long, align_val_t, hot_cold_t) {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t, {MallocLike, 3, 0, -1, 1, MallocFamily::CPPNewArrayAligned}}, // new[](unsigned long, align_val_t, nothrow) + {LibFunc_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t, {MallocLike, 4, 0, -1, 1, MallocFamily::CPPNewAligned}}, // new[](unsigned long, align_val_t, nothrow, hot_cold_t) {LibFunc_msvc_new_int, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int) {LibFunc_msvc_new_int_nothrow, {MallocLike, 2, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned int, nothrow) {LibFunc_msvc_new_longlong, {OpNewLike, 1, 0, -1, -1, MallocFamily::MSVCNew}}, // new(unsigned long long) diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -474,6 +474,7 @@ TLI.setUnavailable(LibFunc_ZnajSt11align_val_tRKSt9nothrow_t); TLI.setUnavailable(LibFunc_Znam); TLI.setUnavailable(LibFunc_ZnamRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnamRKSt9nothrow_t10hot_cold_t); TLI.setUnavailable(LibFunc_ZnamSt11align_val_t); TLI.setUnavailable(LibFunc_ZnamSt11align_val_tRKSt9nothrow_t); TLI.setUnavailable(LibFunc_Znwj); @@ -482,8 +483,15 @@ TLI.setUnavailable(LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t); TLI.setUnavailable(LibFunc_Znwm); TLI.setUnavailable(LibFunc_ZnwmRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_ZnwmRKSt9nothrow_t10hot_cold_t); TLI.setUnavailable(LibFunc_ZnwmSt11align_val_t); TLI.setUnavailable(LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t); + TLI.setUnavailable(LibFunc_Znwm10hot_cold_t); + TLI.setUnavailable(LibFunc_ZnwmSt11align_val_t10hot_cold_t); + TLI.setUnavailable(LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t); + TLI.setUnavailable(LibFunc_Znam10hot_cold_t); + TLI.setUnavailable(LibFunc_ZnamSt11align_val_t10hot_cold_t); + TLI.setUnavailable(LibFunc_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t); } else { // Not MSVC, assume it's Itanium. TLI.setUnavailable(LibFunc_msvc_new_int); diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1941,3 +1941,87 @@ return CI; } + +Value *llvm::emitHotColdNew(Value *Num, IRBuilderBase &B, + const TargetLibraryInfo *TLI, LibFunc NewFunc, + uint8_t HotCold) { + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, NewFunc)) + return nullptr; + + StringRef Name = TLI->getName(NewFunc); + FunctionCallee Func = M->getOrInsertFunction(Name, B.getInt8PtrTy(), + Num->getType(), B.getInt8Ty()); + inferNonMandatoryLibFuncAttrs(M, Name, *TLI); + CallInst *CI = B.CreateCall(Func, {Num, B.getInt8(HotCold)}, Name); + + if (const Function *F = + dyn_cast(Func.getCallee()->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +Value *llvm::emitHotColdNewNoThrow(Value *Num, Value *NoThrow, IRBuilderBase &B, + const TargetLibraryInfo *TLI, + LibFunc NewFunc, uint8_t HotCold) { + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, NewFunc)) + return nullptr; + + StringRef Name = TLI->getName(NewFunc); + FunctionCallee Func = + M->getOrInsertFunction(Name, B.getInt8PtrTy(), Num->getType(), + NoThrow->getType(), B.getInt8Ty()); + inferNonMandatoryLibFuncAttrs(M, Name, *TLI); + CallInst *CI = B.CreateCall(Func, {Num, NoThrow, B.getInt8(HotCold)}, Name); + + if (const Function *F = + dyn_cast(Func.getCallee()->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +Value *llvm::emitHotColdNewAligned(Value *Num, Value *Align, IRBuilderBase &B, + const TargetLibraryInfo *TLI, + LibFunc NewFunc, uint8_t HotCold) { + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, NewFunc)) + return nullptr; + + StringRef Name = TLI->getName(NewFunc); + FunctionCallee Func = M->getOrInsertFunction( + Name, B.getInt8PtrTy(), Num->getType(), Align->getType(), B.getInt8Ty()); + inferNonMandatoryLibFuncAttrs(M, Name, *TLI); + CallInst *CI = B.CreateCall(Func, {Num, Align, B.getInt8(HotCold)}, Name); + + if (const Function *F = + dyn_cast(Func.getCallee()->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +Value *llvm::emitHotColdNewAlignedNoThrow(Value *Num, Value *Align, + Value *NoThrow, IRBuilderBase &B, + const TargetLibraryInfo *TLI, + LibFunc NewFunc, uint8_t HotCold) { + Module *M = B.GetInsertBlock()->getModule(); + if (!isLibFuncEmittable(M, TLI, NewFunc)) + return nullptr; + + StringRef Name = TLI->getName(NewFunc); + FunctionCallee Func = M->getOrInsertFunction( + Name, B.getInt8PtrTy(), Num->getType(), Align->getType(), + NoThrow->getType(), B.getInt8Ty()); + inferNonMandatoryLibFuncAttrs(M, Name, *TLI); + CallInst *CI = + B.CreateCall(Func, {Num, Align, NoThrow, B.getInt8(HotCold)}, Name); + + if (const Function *F = + dyn_cast(Func.getCallee()->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -44,6 +44,13 @@ cl::desc("Enable unsafe double to float " "shrinking for math lib calls")); +// Enable conversion of operator new calls with a MemProf hot or cold hint +// to an operator new call that takes a hot/cold hint. Off by default since +// not all allocators currently support this extension. +static cl::opt + OptimizeHotColdNew("optimize-hot-cold-new", cl::Hidden, cl::init(false), + cl::desc("Enable hot/cold operator new library calls")); + //===----------------------------------------------------------------------===// // Helper Functions //===----------------------------------------------------------------------===// @@ -1653,6 +1660,59 @@ return nullptr; } +// When enabled, replace operator new() calls marked with a hot or cold memprof +// attribute with an operator new() call that takes a hot_cold_t parameter. +// Currently this is supported by the open source version of tcmalloc, see: +// https://github.com/google/tcmalloc/blob/master/tcmalloc/new_extension.h +Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B, + LibFunc &Func) { + if (!OptimizeHotColdNew) + return nullptr; + + uint8_t HotCold; + if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "cold") + HotCold = 0; // Coldest setting. + else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "hot") + HotCold = 255; // Hottest setting. + else + return nullptr; + + switch (Func) { + case LibFunc_Znwm: + return emitHotColdNew(CI->getArgOperand(0), B, TLI, + LibFunc_Znwm10hot_cold_t, HotCold); + case LibFunc_Znam: + return emitHotColdNew(CI->getArgOperand(0), B, TLI, + LibFunc_Znam10hot_cold_t, HotCold); + case LibFunc_ZnwmRKSt9nothrow_t: + return emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B, + TLI, LibFunc_ZnwmRKSt9nothrow_t10hot_cold_t, + HotCold); + case LibFunc_ZnamRKSt9nothrow_t: + return emitHotColdNewNoThrow(CI->getArgOperand(0), CI->getArgOperand(1), B, + TLI, LibFunc_ZnamRKSt9nothrow_t10hot_cold_t, + HotCold); + case LibFunc_ZnwmSt11align_val_t: + return emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B, + TLI, LibFunc_ZnwmSt11align_val_t10hot_cold_t, + HotCold); + case LibFunc_ZnamSt11align_val_t: + return emitHotColdNewAligned(CI->getArgOperand(0), CI->getArgOperand(1), B, + TLI, LibFunc_ZnamSt11align_val_t10hot_cold_t, + HotCold); + case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t: + return emitHotColdNewAlignedNoThrow( + CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, + TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t, HotCold); + case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t: + return emitHotColdNewAlignedNoThrow( + CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, + TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t, HotCold); + default: + assert(false); + } +} + //===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -3448,6 +3508,15 @@ return optimizeWcslen(CI, Builder); case LibFunc_bcopy: return optimizeBCopy(CI, Builder); + case LibFunc_Znwm: + case LibFunc_ZnwmRKSt9nothrow_t: + case LibFunc_ZnwmSt11align_val_t: + case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t: + case LibFunc_Znam: + case LibFunc_ZnamRKSt9nothrow_t: + case LibFunc_ZnamSt11align_val_t: + case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t: + return optimizeNew(CI, Builder, Func); default: break; } diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls-new.ll @@ -0,0 +1,182 @@ +; RUN: opt < %s -passes=instcombine -S | FileCheck %s --implicit-check-not=hot_cold_t +; RUN: opt < %s -passes=instcombine -optimize-hot-cold-new -S | FileCheck %s --check-prefix=HOTCOLD + +;; Check that operator new(unsigned long) converted to +;; operator new(unsigned long, hot_cold_t) with a hot or cold attribute. +; HOTCOLD-LABEL: @new() +define void @new() { + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_Znwm10hot_cold_t(i64 10, i8 0) + %call = call ptr @_Znwm(i64 10) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_Znwm(i64 10) + %call1 = call ptr @_Znwm(i64 10) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_Znwm10hot_cold_t(i64 10, i8 -1) + %call2 = call ptr @_Znwm(i64 10) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new(unsigned long, std::align_val_t) converted to +;; operator new(unsigned long, std::align_val_t, hot_cold_t) with a hot or +;; cold attribute. +; HOTCOLD-LABEL: @new_align() +define void @new_align() { + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_ZnwmSt11align_val_t10hot_cold_t(i64 10, i64 8, i8 0) + %call = call ptr @_ZnwmSt11align_val_t(i64 10, i64 8) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_ZnwmSt11align_val_t(i64 10, i64 8) + %call1 = call ptr @_ZnwmSt11align_val_t(i64 10, i64 8) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_ZnwmSt11align_val_t10hot_cold_t(i64 10, i64 8, i8 -1) + %call2 = call ptr @_ZnwmSt11align_val_t(i64 10, i64 8) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new(unsigned long, const std::nothrow_t&) converted to +;; operator new(unsigned long, const std::nothrow_t&, hot_cold_t) with a hot or +;; cold attribute. +; HOTCOLD-LABEL: @new_nothrow() +define void @new_nothrow() { + %nt = alloca i8 + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_ZnwmRKSt9nothrow_t10hot_cold_t(i64 10, ptr nonnull %nt, i8 0) + %call = call ptr @_ZnwmRKSt9nothrow_t(i64 10, ptr %nt) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_ZnwmRKSt9nothrow_t(i64 10, ptr nonnull %nt) + %call1 = call ptr @_ZnwmRKSt9nothrow_t(i64 10, ptr %nt) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_ZnwmRKSt9nothrow_t10hot_cold_t(i64 10, ptr nonnull %nt, i8 -1) + %call2 = call ptr @_ZnwmRKSt9nothrow_t(i64 10, ptr %nt) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new(unsigned long, std::align_val_t, const std::nothrow_t&) +;; converted to +;; operator new(unsigned long, std::align_val_t, const std::nothrow_t&, hot_cold_t) +;; with a hot or cold attribute. +; HOTCOLD-LABEL: @new_align_nothrow() +define void @new_align_nothrow() { + %nt = alloca i8 + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t(i64 10, i64 8, ptr nonnull %nt, i8 0) + %call = call ptr @_ZnwmSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr %nt) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_ZnwmSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr nonnull %nt) + %call1 = call ptr @_ZnwmSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr %nt) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t(i64 10, i64 8, ptr nonnull %nt, i8 -1) + %call2 = call ptr @_ZnwmSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr %nt) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new[](unsigned long) converted to +;; operator new[](unsigned long, hot_cold_t) with a hot or cold attribute. +; HOTCOLD-LABEL: @array_new() +define void @array_new() { + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_Znam10hot_cold_t(i64 10, i8 0) + %call = call ptr @_Znam(i64 10) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_Znam(i64 10) + %call1 = call ptr @_Znam(i64 10) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_Znam10hot_cold_t(i64 10, i8 -1) + %call2 = call ptr @_Znam(i64 10) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new[](unsigned long, std::align_val_t) converted to +;; operator new[](unsigned long, std::align_val_t, hot_cold_t) with a hot or +;; cold attribute. +; HOTCOLD-LABEL: @array_new_align() +define void @array_new_align() { + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_ZnamSt11align_val_t10hot_cold_t(i64 10, i64 8, i8 0) + %call = call ptr @_ZnamSt11align_val_t(i64 10, i64 8) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_ZnamSt11align_val_t(i64 10, i64 8) + %call1 = call ptr @_ZnamSt11align_val_t(i64 10, i64 8) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_ZnamSt11align_val_t10hot_cold_t(i64 10, i64 8, i8 -1) + %call2 = call ptr @_ZnamSt11align_val_t(i64 10, i64 8) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new[](unsigned long, const std::nothrow_t&) converted to +;; operator new[](unsigned long, const std::nothrow_t&, hot_cold_t) with a hot or +;; cold attribute. +; HOTCOLD-LABEL: @array_new_nothrow() +define void @array_new_nothrow() { + %nt = alloca i8 + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_ZnamRKSt9nothrow_t10hot_cold_t(i64 10, ptr nonnull %nt, i8 0) + %call = call ptr @_ZnamRKSt9nothrow_t(i64 10, ptr %nt) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_ZnamRKSt9nothrow_t(i64 10, ptr nonnull %nt) + %call1 = call ptr @_ZnamRKSt9nothrow_t(i64 10, ptr %nt) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_ZnamRKSt9nothrow_t10hot_cold_t(i64 10, ptr nonnull %nt, i8 -1) + %call2 = call ptr @_ZnamRKSt9nothrow_t(i64 10, ptr %nt) #2 + call void @dummy(ptr %call2) + ret void +} + +;; Check that operator new[](unsigned long, std::align_val_t, const std::nothrow_t&) +;; converted to +;; operator new[](unsigned long, std::align_val_t, const std::nothrow_t&, hot_cold_t) +;; with a hot or cold attribute. +; HOTCOLD-LABEL: @array_new_align_nothrow() +define void @array_new_align_nothrow() { + %nt = alloca i8 + ;; Attribute cold converted to hot_cold_t value 0 (coldest). + ; HOTCOLD: @_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t(i64 10, i64 8, ptr nonnull %nt, i8 0) + %call = call ptr @_ZnamSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr %nt) #0 + call void @dummy(ptr %call) + ;; Attribute notcold has no effect. + ; HOTCOLD: @_ZnamSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr nonnull %nt) + %call1 = call ptr @_ZnamSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr %nt) #1 + call void @dummy(ptr %call1) + ;; Attribute hot converted to hot_cold_t value 255 (-1) (hottest). + ; HOTCOLD: @_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t(i64 10, i64 8, ptr nonnull %nt, i8 -1) + %call2 = call ptr @_ZnamSt11align_val_tRKSt9nothrow_t(i64 10, i64 8, ptr %nt) #2 + call void @dummy(ptr %call2) + ret void +} + +;; So that instcombine doesn't optimize out the call. +declare void @dummy(ptr) + +declare ptr @_Znwm(i64) +declare ptr @_ZnwmSt11align_val_t(i64, i64) +declare ptr @_ZnwmRKSt9nothrow_t(i64, ptr) +declare ptr @_ZnwmSt11align_val_tRKSt9nothrow_t(i64, i64, ptr) +declare ptr @_Znam(i64) +declare ptr @_ZnamSt11align_val_t(i64, i64) +declare ptr @_ZnamRKSt9nothrow_t(i64, ptr) +declare ptr @_ZnamSt11align_val_tRKSt9nothrow_t(i64, i64, ptr) + +attributes #0 = { builtin allocsize(0) "memprof"="cold" } +attributes #1 = { builtin allocsize(0) "memprof"="notcold" } +attributes #2 = { builtin allocsize(0) "memprof"="hot" } diff --git a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml --- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml +++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml @@ -32,13 +32,14 @@ # RUN: FileCheck %s --check-prefix=AVAIL --input-file %t3.txt # RUN: FileCheck %s --check-prefix=UNAVAIL --input-file %t3.txt # -# CHECK: << Total TLI yes SDK no: 0 +# CHECK: << Total TLI yes SDK no: 8 # CHECK: >> Total TLI no SDK yes: 0 # CHECK: == Total TLI yes SDK yes: 235 # # WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*) # WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int) -# WRONG_SUMMARY: << Total TLI yes SDK no: 1{{$}} +# WRONG_DETAIL-COUNT-8: << TLI yes SDK no : {{.*}}hot_cold_t +# WRONG_SUMMARY: << Total TLI yes SDK no: 9{{$}} # WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}} # WRONG_SUMMARY: == Total TLI yes SDK yes: 234 # @@ -46,8 +47,8 @@ ## the exact count first; the two directives should add up to that. ## Yes, this means additions to TLI will fail this test, but the argument ## to -COUNT can't be an expression. -# AVAIL: TLI knows 468 symbols, 235 available -# AVAIL-COUNT-235: {{^}} available +# AVAIL: TLI knows 476 symbols, 243 available +# AVAIL-COUNT-243: {{^}} available # AVAIL-NOT: {{^}} available # UNAVAIL-COUNT-233: not available # UNAVAIL-NOT: not available diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp --- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -433,17 +433,27 @@ "declare i8* @_ZnajSt11align_val_t(i32, i32)\n" "declare i8* @_ZnajSt11align_val_tRKSt9nothrow_t(i32, i32, %struct*)\n" "declare i8* @_Znam(i64)\n" + "declare i8* @_Znam10hot_cold_t(i64, i8)\n" "declare i8* @_ZnamRKSt9nothrow_t(i64, %struct*)\n" + "declare i8* @_ZnamRKSt9nothrow_t10hot_cold_t(i64, %struct*, i8)\n" "declare i8* @_ZnamSt11align_val_t(i64, i64)\n" + "declare i8* @_ZnamSt11align_val_t10hot_cold_t(i64, i64, i8)\n" "declare i8* @_ZnamSt11align_val_tRKSt9nothrow_t(i64, i64, %struct*)\n" + "declare i8* @_ZnamSt11align_val_tRKSt9nothrow_t10hot_cold_t(i64, i64, " + "%struct*, i8)\n" "declare i8* @_Znwj(i32)\n" "declare i8* @_ZnwjRKSt9nothrow_t(i32, %struct*)\n" "declare i8* @_ZnwjSt11align_val_t(i32, i32)\n" "declare i8* @_ZnwjSt11align_val_tRKSt9nothrow_t(i32, i32, %struct*)\n" "declare i8* @_Znwm(i64)\n" + "declare i8* @_Znwm10hot_cold_t(i64, i8)\n" "declare i8* @_ZnwmRKSt9nothrow_t(i64, %struct*)\n" + "declare i8* @_ZnwmRKSt9nothrow_t10hot_cold_t(i64, %struct*, i8)\n" "declare i8* @_ZnwmSt11align_val_t(i64, i64)\n" + "declare i8* @_ZnwmSt11align_val_t10hot_cold_t(i64, i64, i8)\n" "declare i8* @_ZnwmSt11align_val_tRKSt9nothrow_t(i64, i64, %struct*)\n" + "declare i8* @_ZnwmSt11align_val_tRKSt9nothrow_t10hot_cold_t(i64, i64, " + "%struct*, i8)\n" "declare void @\"??3@YAXPEAX@Z\"(i8*)\n" "declare void @\"??3@YAXPEAXAEBUnothrow_t@std@@@Z\"(i8*, %struct*)\n"