Index: include/llvm/Analysis/TargetLibraryInfo.def =================================================================== --- include/llvm/Analysis/TargetLibraryInfo.def +++ include/llvm/Analysis/TargetLibraryInfo.def @@ -813,6 +813,9 @@ /// int printf(const char *format, ...); TLI_DEFINE_ENUM_INTERNAL(printf) TLI_DEFINE_STRING_INTERNAL("printf") +/// pthread_t pthread_self(void); +TLI_DEFINE_ENUM_INTERNAL(pthread_self) +TLI_DEFINE_STRING_INTERNAL("pthread_self") /// int putc(int c, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(putc) TLI_DEFINE_STRING_INTERNAL("putc") Index: include/llvm/Analysis/ValueTracking.h =================================================================== --- include/llvm/Analysis/ValueTracking.h +++ include/llvm/Analysis/ValueTracking.h @@ -290,7 +290,8 @@ /// for such instructions, moving them may change the resulting value. bool isSafeToSpeculativelyExecute(const Value *V, const Instruction *CtxI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); /// Returns true if the result or effects of the given instructions \p I /// depend on or influence global memory. Index: include/llvm/Transforms/Utils/LoopUtils.h =================================================================== --- include/llvm/Transforms/Utils/LoopUtils.h +++ include/llvm/Transforms/Utils/LoopUtils.h @@ -481,8 +481,8 @@ /// can execute specultatively. /// bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, - Loop *CurLoop, AliasSetTracker *CurAST, - LoopSafetyInfo *SafetyInfo); + TargetLibraryInfo *TLI, Loop *CurLoop, + AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo); } #endif Index: lib/Analysis/TargetLibraryInfo.cpp =================================================================== --- lib/Analysis/TargetLibraryInfo.cpp +++ lib/Analysis/TargetLibraryInfo.cpp @@ -304,6 +304,9 @@ TLI.setUnavailable(LibFunc::atoll); TLI.setUnavailable(LibFunc::frexpf); TLI.setUnavailable(LibFunc::llabs); + + // Win32 does *not* provide pthread_self. + TLI.setUnavailable(LibFunc::pthread_self); } switch (T.getOS()) { Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -3198,9 +3198,9 @@ return true; } -bool llvm::isSafeToSpeculativelyExecute(const Value *V, - const Instruction *CtxI, - const DominatorTree *DT) { +bool llvm::isSafeToSpeculativelyExecute(const Value *V, const Instruction *CtxI, + const DominatorTree *DT, + const TargetLibraryInfo *TLI) { const Operator *Inst = dyn_cast(V); if (!Inst) return false; @@ -3303,6 +3303,20 @@ default: break; } } + + // Use TargetLibraryInfo to determine whether a called function can be + // safely speculated. + if (TLI) { + LibFunc::Func LF; + const CallInst *CI = cast(Inst); + const Function *CF = CI->getCalledFunction(); + // TODO: Add more library functions that are safe to speculate. + if (CF && TLI->getLibFunc(CF->getName(), LF)) { + // pthread_self will not trap. + if (LF == LibFunc::pthread_self) + return true; + } + } return false; // The called function could have undefined behavior or // side-effects, even if marked readnone nounwind. } Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -90,6 +90,7 @@ const LoopSafetyInfo *SafetyInfo); static bool isSafeToExecuteUnconditionally(const Instruction &Inst, const DominatorTree *DT, + const TargetLibraryInfo *TLI, const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, const Instruction *CtxI = nullptr); @@ -333,7 +334,7 @@ // operands of the instruction are loop invariant. // if (isNotUsedInLoop(I, CurLoop, SafetyInfo) && - canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo)) { + canSinkOrHoistInst(I, AA, DT, TLI, CurLoop, CurAST, SafetyInfo)) { ++II; Changed |= sink(I, LI, DT, CurLoop, CurAST, SafetyInfo); } @@ -386,9 +387,9 @@ // is safe to hoist the instruction. // if (CurLoop->hasLoopInvariantOperands(&I) && - canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo) && + canSinkOrHoistInst(I, AA, DT, TLI, CurLoop, CurAST, SafetyInfo) && isSafeToExecuteUnconditionally( - I, DT, CurLoop, SafetyInfo, + I, DT, TLI, CurLoop, SafetyInfo, CurLoop->getLoopPreheader()->getTerminator())) Changed |= hoist(I, DT, CurLoop, SafetyInfo); } @@ -433,7 +434,8 @@ } bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, - Loop *CurLoop, AliasSetTracker *CurAST, + TargetLibraryInfo *TLI, Loop *CurLoop, + AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo) { // Loads have extra constraints we have to verify before we can hoist them. if (LoadInst *LI = dyn_cast(&I)) { @@ -516,7 +518,8 @@ // TODO: Plumb the context instruction through to make hoisting and sinking // more powerful. Hoisting of loads already works due to the special casing // above. - return isSafeToExecuteUnconditionally(I, DT, CurLoop, SafetyInfo, nullptr); + return isSafeToExecuteUnconditionally(I, DT, TLI, CurLoop, SafetyInfo, + nullptr); } /// Returns true if a PHINode is a trivially replaceable with an @@ -749,10 +752,11 @@ /// or if it is a trapping instruction and is guaranteed to execute. static bool isSafeToExecuteUnconditionally(const Instruction &Inst, const DominatorTree *DT, + const TargetLibraryInfo *TLI, const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, const Instruction *CtxI) { - if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT)) + if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT, TLI)) return true; return isGuaranteedToExecute(Inst, DT, CurLoop, SafetyInfo); @@ -950,7 +954,7 @@ if (!GuaranteedToExecute && !CanSpeculateLoad) CanSpeculateLoad = isSafeToExecuteUnconditionally( - *Load, DT, CurLoop, SafetyInfo, Preheader->getTerminator()); + *Load, DT, TLI, CurLoop, SafetyInfo, Preheader->getTerminator()); } else if (const StoreInst *Store = dyn_cast(UI)) { // Stores *of* the pointer are not interesting, only stores *to* the // pointer. Index: lib/Transforms/Scalar/LoopSink.cpp =================================================================== --- lib/Transforms/Scalar/LoopSink.cpp +++ lib/Transforms/Scalar/LoopSink.cpp @@ -284,7 +284,7 @@ for (auto II = Preheader->rbegin(), E = Preheader->rend(); II != E;) { Instruction *I = &*II++; if (!L.hasLoopInvariantOperands(I) || - !canSinkOrHoistInst(*I, &AA, &DT, &L, &CurAST, nullptr)) + !canSinkOrHoistInst(*I, &AA, &DT, nullptr, &L, &CurAST, nullptr)) continue; if (sinkInstruction(L, *I, ColdLoopBBs, LoopBlockNumber, LI, DT, BFI)) Changed = true; Index: test/Transforms/LICM/pthread.ll =================================================================== --- test/Transforms/LICM/pthread.ll +++ test/Transforms/LICM/pthread.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -S -licm | FileCheck %s + +; CHECK-LABEL: define void @pthread_self_safe( +; CHECK: pthread_self() +; CHECK: br label + +define void @pthread_self_safe(i32) { + br label %2 + +;