diff options
author | Xin Tong <trent.xin.tong@gmail.com> | 2017-05-20 22:40:25 +0000 |
---|---|---|
committer | Xin Tong <trent.xin.tong@gmail.com> | 2017-05-20 22:40:25 +0000 |
commit | 75af3af95780e1c379409bf56c516a272c4fa961 (patch) | |
tree | df81d93ee10bd76a5be14744ff2ef967f0ddfeb8 /llvm | |
parent | 36af8f4d42a0d4c5191450f5b729749b56bcc0e7 (diff) | |
download | bcm5719-llvm-75af3af95780e1c379409bf56c516a272c4fa961.tar.gz bcm5719-llvm-75af3af95780e1c379409bf56c516a272c4fa961.zip |
Add pthread_self function prototype and make it speculatable.
Summary: This allows pthread_self to be pulled out of a loop by LICM.
Reviewers: hfinkel, arsenm, davide
Reviewed By: davide
Subscribers: davide, wdng, llvm-commits
Differential Revision: https://reviews.llvm.org/D32782
llvm-svn: 303495
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/Analysis/TargetLibraryInfo.def | 3 | ||||
-rw-r--r-- | llvm/lib/Analysis/TargetLibraryInfo.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 12 | ||||
-rw-r--r-- | llvm/test/Transforms/LICM/pthread.ll | 38 | ||||
-rw-r--r-- | llvm/unittests/Analysis/TargetLibraryInfoTest.cpp | 8 |
5 files changed, 67 insertions, 3 deletions
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def index 9cbe917c146..be6685722d9 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -938,6 +938,9 @@ TLI_DEFINE_STRING_INTERNAL("pread") /// 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") diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 2be5d5caf7c..b12778278ce 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -349,6 +349,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, 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 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, 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()); diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index ebde1f9a17d..cf345325254 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -38,6 +38,7 @@ STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture"); 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 @@ static bool setDoesNotThrow(Function &F) { 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 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { 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); diff --git a/llvm/test/Transforms/LICM/pthread.ll b/llvm/test/Transforms/LICM/pthread.ll new file mode 100644 index 00000000000..6a7aa499b5a --- /dev/null +++ b/llvm/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 + +; <label>:2: ; preds = %7, %1 + %idx = phi i32 [ 0, %1 ], [ %8, %7 ] + %3 = icmp slt i32 %idx, %0 + br i1 %3, label %4, label %9 + +; <label>:4: ; preds = %2 + call void @external_func_that_could_do_anything() + %5 = call i64 @pthread_self() #1 + %6 = trunc i64 %5 to i32 + call void @use_pthread_self(i32 %6) + br label %7 + +; <label>:7: ; preds = %4 + %8 = add nsw i32 %idx, 1 + br label %2 + +; <label>:9: ; preds = %2 + ret void +} + +; CHECK: declare i64 @pthread_self() #0 +; CHECK: attributes #0 = { nounwind readnone speculatable } +; Function Attrs: nounwind readnone +declare i64 @pthread_self() #1 + +declare void @external_func_that_could_do_anything() + +declare void @use_pthread_self(i32) + +attributes #1 = { nounwind readnone } + diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp index 9d852cf0301..64a735de694 100644 --- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -63,12 +63,13 @@ TEST_F(TargetLibraryInfoTest, InvalidProto) { parseAssembly("%foo = type { %foo }\n"); auto *StructTy = M->getTypeByName("foo"); - auto *InvalidFTy = FunctionType::get(StructTy, /*isVarArg=*/false); - for (unsigned FI = 0; FI != LibFunc::NumLibFuncs; ++FI) { LibFunc LF = (LibFunc)FI; + // Using the library function name to create a function that takes + // 1 parameter and returns the same type. There should be no library + // function that matches this egregiously incorrect prototypes. auto *F = cast<Function>( - M->getOrInsertFunction(TLI.getName(LF), InvalidFTy)); + M->getOrInsertFunction(TLI.getName(LF), StructTy, StructTy)); EXPECT_FALSE(isLibFunc(F, LF)); } } @@ -246,6 +247,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare float @powf(float, float)\n" "declare x86_fp80 @powl(x86_fp80, x86_fp80)\n" "declare i32 @printf(i8*, ...)\n" + "declare %struct @pthread_self()\n" "declare i32 @putc(i32, %struct*)\n" "declare i32 @putchar(i32)\n" "declare i32 @puts(i8*)\n" |