diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index b12c1b9bb9d5e..adae796ee0299 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -612,7 +612,16 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // memory (without proving that the loop doesn't write). if (L->hasLoopInvariantOperands(Inst) && !Inst->mayReadFromMemory() && !Inst->mayWriteToMemory() && !Inst->isTerminator() && - !isa(Inst) && !isa(Inst)) { + !isa(Inst) && !isa(Inst) && + // It is not safe to hoist the value of these instructions in + // coroutines, as the addresses of otherwise eligible variables (e.g. + // thread-local variables and errno) may change if the coroutine is + // resumed in a different thread.Therefore, we disable this + // optimization for correctness. However, this may block other correct + // optimizations. + // FIXME: This should be reverted once we have a better model for + // memory access in coroutines. + !Inst->getFunction()->isPresplitCoroutine()) { if (LoopEntryBranch->getParent()->IsNewDbgInfoFormat && !NextDbgInsts.empty()) { diff --git a/llvm/test/Transforms/LoopRotate/coroutine.ll b/llvm/test/Transforms/LoopRotate/coroutine.ll index 9d7bf595e21cd..4544ac5e72bbe 100644 --- a/llvm/test/Transforms/LoopRotate/coroutine.ll +++ b/llvm/test/Transforms/LoopRotate/coroutine.ll @@ -21,8 +21,9 @@ define void @foo() #0 { ; CHECK-NEXT: ret void ; CHECK: cond.end: ; CHECK-NEXT: call void @bar() -; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP0]], align 4 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @threadlocalint) +; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[WHILE_COND_COND_FALSE_CRIT_EDGE:%.*]] ; entry: