summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorXin Tong <trent.xin.tong@gmail.com>2017-05-20 22:40:25 +0000
committerXin Tong <trent.xin.tong@gmail.com>2017-05-20 22:40:25 +0000
commit75af3af95780e1c379409bf56c516a272c4fa961 (patch)
treedf81d93ee10bd76a5be14744ff2ef967f0ddfeb8 /llvm
parent36af8f4d42a0d4c5191450f5b729749b56bcc0e7 (diff)
downloadbcm5719-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.def3
-rw-r--r--llvm/lib/Analysis/TargetLibraryInfo.cpp9
-rw-r--r--llvm/lib/Transforms/Utils/BuildLibCalls.cpp12
-rw-r--r--llvm/test/Transforms/LICM/pthread.ll38
-rw-r--r--llvm/unittests/Analysis/TargetLibraryInfoTest.cpp8
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"
OpenPOWER on IntegriCloud