summaryrefslogtreecommitdiff
path: root/src/passes/RelooperJumpThreading.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/RelooperJumpThreading.cpp')
-rw-r--r--src/passes/RelooperJumpThreading.cpp16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/passes/RelooperJumpThreading.cpp b/src/passes/RelooperJumpThreading.cpp
index 7f74220d5..bd257c568 100644
--- a/src/passes/RelooperJumpThreading.cpp
+++ b/src/passes/RelooperJumpThreading.cpp
@@ -182,7 +182,21 @@ private:
assert(labelChecksInOrigin[num] == 0);
if (labelSetsInOrigin[num] != labelSets[num]) {
assert(labelSetsInOrigin[num] < labelSets[num]);
- return true; // label set somewhere outside of origin TODO: if set in the if body here, it might be safe in some cases
+ // the label is set outside of the origin
+ // if the only other location is inside the if body, then it is ok - it must be in a loop
+ // and returning to the top of the loop body, so we don't need to do anything for that
+ // label setting anyhow
+ std::map<Index, Index> labelChecksInIfTrue;
+ std::map<Index, Index> labelSetsInIfTrue;
+ LabelUseFinder finder(labelIndex, labelChecksInIfTrue, labelSetsInIfTrue);
+ finder.walk(iff->ifTrue);
+ if (labelSetsInOrigin[num] + labelSetsInIfTrue[num] < labelSets[num]) {
+ // label set somewhere we can't see now, could be irreducible control flow
+ // TODO: one case where this happens is instead of an if-chain, we have
+ // ifs and a switch on label|0, in separate elements. perhaps not
+ // emitting switches on label|0 in the relooper would avoid that.
+ return true;
+ }
}
iff = isLabelCheckingIf(iff->ifFalse, labelIndex);
}