Skip to content

Commit a9b5753

Browse files
authored
[LoopRotate][coroutines] Avoid hoisting addresses of thread-local variables outside loops in coroutines (#81937)
Because loops in coroutines may have a co_await statement that reschedules the coroutine to another thread, we cannot cache addresses of thread-local variables obtained inside a loop by moving the computation of thoes addresses outside a loop. Since LLVM doesn't have a model for coroutine memory accesses, this patch fixes this bug by disabling this optimization for coroutines in the same way as https://reviews.llvm.org/D135550 and https://reviews.llvm.org/D151774.
1 parent 807ed69 commit a9b5753

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

llvm/lib/Transforms/Utils/LoopRotationUtils.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,16 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
612612
// memory (without proving that the loop doesn't write).
613613
if (L->hasLoopInvariantOperands(Inst) && !Inst->mayReadFromMemory() &&
614614
!Inst->mayWriteToMemory() && !Inst->isTerminator() &&
615-
!isa<DbgInfoIntrinsic>(Inst) && !isa<AllocaInst>(Inst)) {
615+
!isa<DbgInfoIntrinsic>(Inst) && !isa<AllocaInst>(Inst) &&
616+
// It is not safe to hoist the value of these instructions in
617+
// coroutines, as the addresses of otherwise eligible variables (e.g.
618+
// thread-local variables and errno) may change if the coroutine is
619+
// resumed in a different thread.Therefore, we disable this
620+
// optimization for correctness. However, this may block other correct
621+
// optimizations.
622+
// FIXME: This should be reverted once we have a better model for
623+
// memory access in coroutines.
624+
!Inst->getFunction()->isPresplitCoroutine()) {
616625

617626
if (LoopEntryBranch->getParent()->IsNewDbgInfoFormat &&
618627
!NextDbgInsts.empty()) {

llvm/test/Transforms/LoopRotate/coroutine.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ define void @foo() #0 {
2121
; CHECK-NEXT: ret void
2222
; CHECK: cond.end:
2323
; CHECK-NEXT: call void @bar()
24-
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP0]], align 4
25-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP2]], 0
24+
; CHECK-NEXT: [[TMP2:%.*]] = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @threadlocalint)
25+
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
26+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
2627
; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[WHILE_COND_COND_FALSE_CRIT_EDGE:%.*]]
2728
;
2829
entry:

0 commit comments

Comments
 (0)