Index: lib/Transforms/Scalar/LoopIdiomRecognize.cpp =================================================================== --- lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -441,6 +441,13 @@ if (!C) return nullptr; + // While technically constant, the address of a thread_local GlobalVariable + // isn't known until runtime and would require additional tls init code to + // handle correctly. + if (GlobalVariable *GV = dyn_cast(C)) + if (GV->isThreadDependent()) + return nullptr; + // Only handle simple values that are a power of two bytes in size. uint64_t Size = DL->getTypeSizeInBits(V->getType()); if (Size == 0 || (Size & 7) || (Size & (Size - 1))) Index: test/Transforms/LoopIdiom/thread-local.ll =================================================================== --- test/Transforms/LoopIdiom/thread-local.ll +++ test/Transforms/LoopIdiom/thread-local.ll @@ -0,0 +1,29 @@ +; RUN: opt -loop-idiom < %s -S | FileCheck %s + +target triple = "x86_64-apple-darwin10.0.0" + +;void test_tls(int **ptrs) { +; thread_local int tls_var; +; for (int i = 0; i < 1000; i++) { +; p[i] = &tls_var; +; } +;} +@tls_var = internal thread_local global i32 0, align 4 + +define void @test_tls(i32** nocapture %ptrs) nounwind ssp { +entry: + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ] + %arrayidx = getelementptr i32*, i32** %ptrs, i64 %indvar + store i32* @tls_var, i32** %arrayidx, align 8 + %indvar.next = add i64 %indvar, 1 + %exitcond = icmp eq i64 %indvar.next, 1000 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +; CHECK-LABEL: @test_tls( +; CHECK-NOT: call void @memset_pattern +}