Skip to content

Commit

Permalink
[InlineFunction] Fix logic to update PHI nodes in an exceptional block
Browse files Browse the repository at this point in the history
when inlining tasks at an invoke instruction.  Addresses issue llvm#73.
  • Loading branch information
neboat committed Jul 1, 2023
1 parent 65e1d4b commit 3cbb463
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 5 deletions.
22 changes: 17 additions & 5 deletions llvm/lib/Transforms/Utils/InlineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,9 +653,11 @@ static void HandleInlinedTasksHelper(
// Promote any calls in the block to invokes.
if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
BB, UnwindEdge)) {
// Update any PHI nodes in the exceptional block to indicate that there
// is now a new entry in them.
Invoke.addIncomingPHIValuesFor(NewBB);
// If this is the topmost invocation of HandleInlinedTasksHelper, update
// any PHI nodes in the exceptional block to indicate that there is now a
// new entry in them.
if (nullptr == ParentWorklist)
Invoke.addIncomingPHIValuesFor(NewBB);
BlocksToProcess.insert(
cast<InvokeInst>(NewBB->getTerminator())->getNormalDest());
}
Expand Down Expand Up @@ -692,7 +694,7 @@ static void HandleInlinedTasksHelper(
continue;
}

// Process a detach instruction specially. In particular, process th
// Process a detach instruction specially. In particular, process the
// spawned task recursively.
if (DetachInst *DI = dyn_cast<DetachInst>(BB->getTerminator())) {
if (!DI->hasUnwindDest()) {
Expand All @@ -709,8 +711,13 @@ static void HandleInlinedTasksHelper(
// If the new unwind edge is not used, remove it.
if (pred_empty(SubTaskUnwindEdge))
SubTaskUnwindEdge->eraseFromParent();
else
else {
DetachesToReplace.push_back(DI);
// Update PHI nodes in the exceptional block to indicate that
// SubTaskUnwindEdge is a new entry in them. This should only have an
// effect for the topmost call to HandleInlinedTasksHelper.
Invoke.addIncomingPHIValuesFor(SubTaskUnwindEdge);
}

} else if (Visited.insert(DI->getUnwindDest()).second) {
// If the detach-unwind isn't dead, add it to the worklist.
Expand Down Expand Up @@ -740,6 +747,11 @@ static void HandleInlinedTasksHelper(
// Replace detaches that now require unwind destinations.
while (!DetachesToReplace.empty()) {
DetachInst *DI = DetachesToReplace.pop_back_val();
// If this is the topmost invocation of HandleInlinedTasksHelper, update any
// PHI nodes in the exceptional block to indicate that there is now a new
// entry in them.
if (nullptr == ParentWorklist)
Invoke.addIncomingPHIValuesFor(DI->getParent());
ReplaceInstWithInst(DI, DetachInst::Create(
DI->getDetached(), DI->getContinue(), UnwindEdge,
DI->getSyncRegion()));
Expand Down
94 changes: 94 additions & 0 deletions llvm/test/Transforms/Tapir/inline-task-update-phi.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
; RUN: opt < %s -inline -S -o - | FileCheck %s
; RUN: opt < %s -passes='inline' -S -o - | FileCheck %s

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

$_ZN5outerC2ERKS_ = comdat any

$_ZNSt5arrayI5outerLm2EED2Ev = comdat any

define dso_local void @main() local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @_ZN5outerC2ERKS_()
to label %invoke.cont unwind label %lpad

invoke.cont: ; preds = %entry
invoke void @_ZN5outerC2ERKS_()
to label %invoke.cont1 unwind label %lpad

invoke.cont1: ; preds = %invoke.cont
ret void

lpad: ; preds = %entry, %invoke.cont
%arrayinit.endOfInit.0.idx = phi i64 [ 1, %invoke.cont ], [ 0, %entry ]
%0 = landingpad { i8*, i32 }
cleanup
resume { i8*, i32 } %0
}

; CHECK: define {{.*}}void @main()
; CHECK: entry:
; CHECK: detach within %{{.*}}, label %[[PFOR_BODY_1:.+]], label %{{.*}} unwind label %lpad

; CHECK: [[PFOR_BODY_1]]:
; CHECK-NEXT: invoke void @_Znwm()
; CHECK-NEXT: to label %{{.*}} unwind label %[[LPAD1:.+]]

; CHECK: [[LPAD1]]:
; CHECK: invoke void @llvm.detached.rethrow.sl_p0i8i32s(token %{{.*}},
; CHECK-NEXT: to label %{{.*}} unwind label %lpad

; CHECK: invoke.cont:
; CHECK: detach within %{{.*}}, label %[[PFOR_BODY_2:.+]], label %{{.*}} unwind label %lpad

; CHECK: [[PFOR_BODY_2]]:
; CHECK-NEXT: invoke void @_Znwm()
; CHECK-NEXT: to label %{{.*}} unwind label %[[LPAD2:.+]]

; CHECK: [[LPAD2]]:
; CHECK: invoke void @llvm.detached.rethrow.sl_p0i8i32s(token %{{.*}},
; CHECK-NEXT: to label %{{.*}} unwind label %lpad

; CHECK: lpad:
; CHECK-NEXT: %arrayinit.endOfInit.0.idx = phi i64 [ 0, %[[LPAD1]] ], [ 0, %entry ], [ 1, %[[LPAD2]] ], [ 1, %invoke.cont ]

define dso_local void @_ZN5outerC2ERKS_() unnamed_addr #1 comdat align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
%syncreg = call token @llvm.syncregion.start()
br label %pfor.cond

pfor.cond: ; preds = %entry
detach within %syncreg, label %pfor.body.entry, label %pfor.inc

pfor.body.entry: ; preds = %pfor.cond
br label %pfor.body

pfor.body: ; preds = %pfor.body.entry
call void @_Znwm() #3
unreachable

pfor.inc: ; preds = %pfor.cond
unreachable
}

declare dso_local i32 @__gxx_personality_v0(...)

define dso_local void @_ZNSt5arrayI5outerLm2EED2Ev() unnamed_addr #1 comdat align 2 {
entry:
ret void
}

; Function Attrs: argmemonly nounwind willreturn
declare token @llvm.syncregion.start() #2

declare dso_local void @_Znwm() local_unnamed_addr #1

attributes #0 = { "target-cpu"="x86-64" }
attributes #1 = { "use-soft-float"="false" }
attributes #2 = { argmemonly nounwind willreturn }
attributes #3 = { builtin }

!llvm.ident = !{!0}

!0 = !{!"clang version 12.0.0 (git@github.com:OpenCilk/opencilk-project.git 973aa8d610bafa8c98286f78c034ce1c27c26eec)"}

0 comments on commit 3cbb463

Please sign in to comment.