summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorFedor Sergeev <fedor.sergeev@azul.com>2018-11-07 20:05:11 +0000
committerFedor Sergeev <fedor.sergeev@azul.com>2018-11-07 20:05:11 +0000
commitf9a02a7006f27c14a8ac69d380649fbddfb72538 (patch)
treed31ae6fcc843b5a997efb78e82d08c199cb259e8 /llvm/lib
parentdf5b09b8ce2e6ceafbb861afba356c39b8fb5ea0 (diff)
downloadbcm5719-llvm-f9a02a7006f27c14a8ac69d380649fbddfb72538.tar.gz
bcm5719-llvm-f9a02a7006f27c14a8ac69d380649fbddfb72538.zip
[SimpleLoopUnswitch] partial unswitch needs to be careful when replacing invariants with constants
When partial unswitch operates on multiple conditions at once, .e.g: if (Cond1 || Cond2 || NonInv) ... it should infer (and replace) values for individual conditions only on one side of unswitch and not another. More precisely only these derivations hold true: (Cond1 || Cond2) == false => Cond1 == Cond2 == false (Cond1 && Cond2) == true => Cond1 == Cond2 == true By the way we organize unswitching it means only replacing on "continue" blocks and never on "unswitched" ones. Since trivial unswitch does not have "unswitched" blocks it does not have this problem. Fixes PR 39568. Reviewers: chandlerc, asbirlea Differential Revision: https://reviews.llvm.org/D54211 llvm-svn: 346350
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp15
1 files changed, 14 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
index 81fba5d15ee..368f0925aba 100644
--- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
@@ -2044,6 +2044,18 @@ static void unswitchNontrivialInvariants(
assert(UnswitchedSuccBBs.size() == 1 &&
"Only one possible unswitched block for a branch!");
BasicBlock *ClonedPH = ClonedPHs.begin()->second;
+
+ // When considering multiple partially-unswitched invariants
+ // we cant just go replace them with constants in both branches.
+ //
+ // For 'AND' we infer that true branch ("continue") means true
+ // for each invariant operand.
+ // For 'OR' we can infer that false branch ("continue") means false
+ // for each invariant operand.
+ // So it happens that for multiple-partial case we dont replace
+ // in the unswitched branch.
+ bool ReplaceUnswitched = FullUnswitch || (Invariants.size() == 1);
+
ConstantInt *UnswitchedReplacement =
Direction ? ConstantInt::getTrue(BI->getContext())
: ConstantInt::getFalse(BI->getContext());
@@ -2063,7 +2075,8 @@ static void unswitchNontrivialInvariants(
// unswitched if in the cloned blocks.
if (DT.dominates(LoopPH, UserI->getParent()))
U->set(ContinueReplacement);
- else if (DT.dominates(ClonedPH, UserI->getParent()))
+ else if (ReplaceUnswitched &&
+ DT.dominates(ClonedPH, UserI->getParent()))
U->set(UnswitchedReplacement);
}
}
OpenPOWER on IntegriCloud