Index: llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def =================================================================== --- llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def +++ llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def @@ -938,6 +938,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: llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp +++ llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp @@ -349,6 +349,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()) { @@ -1263,6 +1266,12 @@ FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1) == SizeTTy && FTy.getParamType(2) == SizeTTy); + // We do not attempt to match the return value here. i.e. thread identifiers + // should be considered opaque, for example, representation using either an + // arithmetic type or a structure is permitted. + case LibFunc_pthread_self: + return NumParams == 0; + case LibFunc_wcslen: return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && FTy.getReturnType()->isIntegerTy()); Index: llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp +++ llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp @@ -38,6 +38,7 @@ STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly"); STATISTIC(NumNoAlias, "Number of function returns inferred as noalias"); STATISTIC(NumNonNull, "Number of function returns inferred as nonnull returns"); +STATISTIC(NumSpeculatable, "Number of functions inferred as speculatable"); static bool setDoesNotAccessMemory(Function &F) { if (F.doesNotAccessMemory()) @@ -71,6 +72,14 @@ return true; } +static bool setSpeculatable(Function &F) { + if (F.isSpeculatable()) + return false; + F.setSpeculatable(); + ++NumSpeculatable; + return true; +} + static bool setRetDoesNotAlias(Function &F) { if (F.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias)) return false; @@ -530,6 +539,9 @@ Changed |= setOnlyReadsMemory(F, 0); Changed |= setOnlyReadsMemory(F, 1); return Changed; + case LibFunc_pthread_self: + Changed |= setSpeculatable(F); + return Changed; case LibFunc_vfscanf: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Index: llvm/trunk/test/Transforms/LICM/pthread.ll =================================================================== --- llvm/trunk/test/Transforms/LICM/pthread.ll +++ llvm/trunk/test/Transforms/LICM/pthread.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -S -inferattrs -licm | FileCheck %s + +; CHECK-LABEL: define void @pthread_self_safe( +; CHECK-NEXT: call i64 @pthread_self() +define void @pthread_self_safe(i32) { + br label %2 + +;