diff --git a/ir/function.cpp b/ir/function.cpp index e4107b7a4..81a97eb8e 100644 --- a/ir/function.cpp +++ b/ir/function.cpp @@ -608,10 +608,6 @@ void Function::unroll(unsigned k) { // computed bottom-up during the post-order traversal below unordered_map> loop_nodes; - // grab all value users before duplication so the list is shorter - auto users = getUsers(); - auto phi_preds = getPhiPredecessors(*this); - // traverse each loop tree in post-order while (!worklist.empty()) { auto [header, height, flag] = worklist.back(); @@ -644,6 +640,12 @@ void Function::unroll(unsigned k) { } } + // Grab value users before duplicating the current loop so the list stays + // shorter. This must be refreshed per loop because unrolling an inner loop + // can introduce phis that outer-loop exits now use. + auto users = getUsers(); + auto phi_preds = getPhiPredecessors(*this); + // map: original BB -> {BB} U copies-of-BB unordered_map> bbmap; for (auto *bb : loop_bbs) { @@ -1236,5 +1238,4 @@ void LoopAnalysis::printDot(ostream &os) const { os << "}\n"; } -} - +} diff --git a/tests/alive-tv/loops/nested-exit-phi.srctgt.ll b/tests/alive-tv/loops/nested-exit-phi.srctgt.ll new file mode 100644 index 000000000..fa2e86f08 --- /dev/null +++ b/tests/alive-tv/loops/nested-exit-phi.srctgt.ll @@ -0,0 +1,27 @@ +; TEST-ARGS: -src-unroll=2 -tgt-unroll=2 + +define i32 @src() { + br label %1 + +1: + %2 = phi i32 [ 0, %0 ], [ 1, %6 ] + br label %3 + +3: + %4 = mul i32 %2, 1 + br label %5 + +5: + br i1 false, label %3, label %6 + +6: + %7 = icmp slt i32 %2, 1 + br i1 %7, label %1, label %8 + +8: + ret i32 %4 +} + +define i32 @tgt() { + ret i32 1 +}