unroll: simplify logic to patch existing phis
dont be greedy.. handle only simple cases
MODIFY
ir/function.cpp
ir/function.cpp
@@ -622,30 +622,25 @@ void Function::unroll(unsigned k) {
if (!dom_tree.dominates(bb_val, exit))
continue;
- if (auto phi = dynamic_cast<Phi*>(user)) {
- // Check if the phi uses this value through a path that is reachable
- // from this exit, as it may only be reachable from another exit.
+ if (auto phi = dynamic_cast<Phi*>(user);
+ phi && user_bb == dst) {
+ // Check if the phi uses this value through this predecessor
auto &vals = phi->getValues();
if (!any_of(vals.begin(), vals.end(),
[&](const auto &p) {
- return p.first == val &&
- dom_tree.dominates(exit, &getBB(p.second));
+ return p.first == val && &getBB(p.second) == exit;
}))
continue;
- if (user_bb == dst) {
auto &exit_copies = bbmap.at(exit);
auto exit_I = exit_copies.begin(), exit_E = exit_copies.end();
for (auto &[bb, val] : copies) {
if (++exit_I == exit_E)
break;
- if (dom_tree.dominates(bb, *exit_I)) {
phi->addValue(*val, string((*exit_I)->getName()));
}
- }
continue;
}
- }
auto &newphi = new_phis[make_pair(dst, val)];
if (!newphi) {

ADD
tests/alive-tv/loops/phi6-fail.srctgt.ll
+; TEST-ARGS: -src-unroll=1 -tgt-unroll=1
+; ERROR: Target is more poisonous than source
+
+declare i32 @f()
+
+define i32 @src(i1 %cond, i1 %cond2) {
+entry:
+ br label %header
+header:
+ %a = call i32 @f()
+ br i1 %cond, label %loop, label %return
+loop:
+ br i1 %cond2, label %header, label %return
+return:
+ %p = phi i32 [0, %header], [%a, %loop]
+ ret i32 %p
+}
+
+define i32 @tgt(i1 %cond, i1 %cond2) {
+entry:
+ %fr = freeze i1 %cond2
+ %brmerge.demorgan = and i1 %cond, %fr
+ br label %header
+
+header:
+ %a = tail call i32 @f()
+ br i1 %brmerge.demorgan, label %header, label %return
+
+return:
+ ret i32 %a
+}

ADD
tests/alive-tv/loops/phi6.srctgt.ll
+; TEST-ARGS: -src-unroll=3 -tgt-unroll=3
+
+declare i32 @f()
+
+define i32 @src(i1 %cond, i1 %cond2) {
+entry:
+ br label %header
+header:
+ %a = call i32 @f()
+ br i1 %cond, label %loop, label %return
+loop:
+ br i1 %cond2, label %header, label %return
+return:
+ %p = phi i32 [0, %header], [%a, %loop]
+ ret i32 %p
+}
+
+define i32 @tgt(i1 %cond, i1 %cond2) {
+entry:
+ %fr = freeze i1 %cond2
+ %brmerge.demorgan = and i1 %cond, %fr
+ br label %header
+
+header:
+ %a = tail call i32 @f()
+ br i1 %brmerge.demorgan, label %header, label %return
+
+return:
+ %.mux = select i1 %cond, i32 %a, i32 0
+ ret i32 %.mux
+}

unroll: simplify logic to patch existing phis
dont be greedy.. handle only simple cases