Skip to content

Commit

Permalink
Fix multi-edge phi node code generation
Browse files Browse the repository at this point in the history
It is possible, after optimziations for the two branches of a conditional
to go to the same basic block. We have an IR invariant that requires the
incoming value to be the same for both incoming edges in this case. LLVM
has the same invariant. However, translating from a julia-incoming-value
to an LLVM one may require additional code generation, and without further
GVN, LLVM does not know that the two values are identical and thus believes
its invariants are violated. The fix is relatively straightforward. Since
we don't have user-inserted switch terminators, we can simply emit a
conditional branch with equal successors as unconditional branches and
skip codegening one of the phi paths. This avoids the issue and also
generates less code in this case.

Fixes #27594
  • Loading branch information
Keno committed Jun 16, 2018
1 parent 85d1d94 commit 6e70c88
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6242,7 +6242,10 @@ static std::unique_ptr<Module> emit_function(
workstack.push_back(lname - 1);
BasicBlock *ifnot = BB[lname];
BasicBlock *ifso = BB[cursor+2];
ctx.builder.CreateCondBr(isfalse, ifnot, ifso);
if (ifnot == ifso)
ctx.builder.CreateBr(ifnot);
else
ctx.builder.CreateCondBr(isfalse, ifnot, ifso);
find_next_stmt(cursor + 1);
continue;
}
Expand Down Expand Up @@ -6332,6 +6335,19 @@ static std::unique_ptr<Module> emit_function(
// This edge was statically unreachable. Don't codegen it.
if (!FromBB)
continue;
// We folded this branch to an unconditional branch, only codegen it once
if (cast<BranchInst>(FromBB->getTerminator())->isUnconditional()) {
bool found = false;
for (size_t j = 0; j < i; ++j) {
size_t j_edge = jl_unbox_long(jl_array_ptr_ref(edges, j));
if (j_edge == edge) {
found = true;
assert(jl_egal(value, jl_array_ptr_ref(values, j)));
}
}
if (found)
continue;
}
#ifndef JL_NDEBUG
if (FromBB) {
bool found_pred = false;
Expand Down
17 changes: 17 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6202,3 +6202,20 @@ function test27566(a,b)
end
test27566(a, b, c, d) = a.*(b, c, d)
@test test27566(1,1) == (1,0,1)

# Issue #27594
struct Iter27594 end
Base.iterate(::Iter27594) = (1, nothing)
Base.iterate(::Iter27594, ::Any) = nothing

function foo27594()
ind = 0
for x in (1,)
for y in Iter27594()
ind += 1
end
end
ind
end

@test foo27594() == 1

0 comments on commit 6e70c88

Please sign in to comment.