loops: fix phi insertion for multi-exit from different BBs to a single BB
MODIFY
ir/function.cpp
ir/function.cpp
@@ -589,14 +589,26 @@ void Function::unroll(unsigned k) {
if (!newphi) {
auto phi = make_unique<Phi>(val->getType(),
val->getName() + "#phi");
- phi->addValue(*const_cast<Value*>(val), string(exit->getName()));
- for (auto &[bb, val] : copies) {
- phi->addValue(*val, string(bb->getName()));
- }
newphi = phi.get();
dst->addInstr(move(phi), true);
}
+ // we may have multiple edges from the loop into this BB
+ // we need to duplicate the predecessor list for each of the
+ // original incoming BB
+ auto all_preds = newphi->sources();
+ if (find(all_preds.begin(), all_preds.end(), exit->getName()) ==
+ all_preds.end()) {
+ newphi->addValue(*const_cast<Value*>(val), string(exit->getName()));
+ auto &bb_dups = bbmap.at(exit);
+ auto bb_I = bb_dups.begin(), bb_E = bb_dups.end();
+ for (auto &[_, val] : copies) {
+ if (++bb_I == bb_E)
+ break;
+ newphi->addValue(*val, string((*bb_I)->getName()));
+ }
+ }
+
auto *i = dynamic_cast<Instr*>(user);
assert(i);
i->rauw(*val, *newphi);

ADD
tests/alive-tv/loops/multi-exit2-fail.srctgt.ll
+; TEST-ARGS: -src-unroll=3 -tgt-unroll=3
+; ERROR: Value mismatch
+
+define i32 @src() {
+entry:
+ br label %for.cond
+
+for.cond:
+ %i = phi i32 [ 0, %entry ], [ %inc1, %for.body ]
+ %r = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+ %cmp = icmp uge i32 %i, 4
+ br i1 %cmp, label %for.end, label %for.body
+
+for.body:
+ %inc = add i32 %r, 2
+ %inc1 = add i32 %i, 1
+ %cmp2 = icmp eq i32 %inc, 6
+ br i1 %cmp2, label %for.end, label %for.cond
+
+for.end:
+ ret i32 %r
+}
+
+define i32 @tgt() {
+ ret i32 0
+}

ADD
tests/alive-tv/loops/multi-exit2.srctgt.ll
+; TEST-ARGS: -src-unroll=3 -tgt-unroll=3
+
+define i32 @src() {
+entry:
+ br label %for.cond
+
+for.cond:
+ %i = phi i32 [ 0, %entry ], [ %inc1, %for.body ]
+ %r = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+ %cmp = icmp uge i32 %i, 4
+ br i1 %cmp, label %for.end, label %for.body
+
+for.body:
+ %inc = add i32 %r, 2
+ %inc1 = add i32 %i, 1
+ %cmp2 = icmp eq i32 %inc, 6
+ br i1 %cmp2, label %for.end, label %for.cond
+
+for.end:
+ ret i32 %r
+}
+
+define i32 @tgt() {
+ ret i32 4
+}

loops: fix phi insertion for multi-exit from different BBs to a single BB