[PATCH] D23911: [SimplifyCFG] Change the algorithm in SinkThenElseCodeToEnd
Hans Wennborg via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 26 15:57:49 PDT 2016
hans added a comment.
Nice! But I had to struggle a bit to wrap my head around the code. I've left some questions hoping it's possible to make things clearer.
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:1322
@@ -1321,60 +1321,3 @@
-// Return true if V0 and V1 are equivalent. This handles the obvious cases
-// where V0 == V1 and V0 and V1 are both identical instructions, but also
-// handles loads and stores with identical operands.
-//
-// Because determining if two memory instructions are equivalent
-// depends on control flow, the \c At0 and \c At1 parameters specify a
-// location for the query. This function is essentially answering the
-// query "If V0 were moved to At0, and V1 were moved to At1, are V0 and V1
-// equivalent?". In practice this means checking that moving V0 to At0
-// doesn't cross any other memory instructions.
-static bool areValuesTriviallySame(Value *V0, BasicBlock::const_iterator At0,
- Value *V1, BasicBlock::const_iterator At1) {
- if (V0 == V1)
- return true;
-
- // Also check for instructions that are identical but not pointer-identical.
- // This can include load instructions that haven't been CSE'd.
- if (!isa<Instruction>(V0) || !isa<Instruction>(V1))
- return false;
- const auto *I0 = cast<Instruction>(V0);
- const auto *I1 = cast<Instruction>(V1);
- if (!I0->isIdenticalToWhenDefined(I1))
- return false;
-
- if (!I0->mayReadOrWriteMemory())
- return true;
-
- // Instructions that may read or write memory have extra restrictions. We
- // must ensure we don't treat %a and %b as equivalent in code such as:
- //
- // %a = load %x
- // store %x, 1
- // if (%c) {
- // %b = load %x
- // %d = add %b, 1
- // } else {
- // %d = add %a, 1
- // }
-
- // Be conservative. We don't want to search the entire CFG between def
- // and use; if the def isn't in the same block as the use just bail.
- if (I0->getParent() != At0->getParent() ||
- I1->getParent() != At1->getParent())
- return false;
-
- // Again, be super conservative. Ideally we'd be able to query AliasAnalysis
- // but we currently don't have that available.
- auto WritesMemory = [](const Instruction &I) {
- return I.mayReadOrWriteMemory();
- };
- if (std::any_of(std::next(I0->getIterator()), At0, WritesMemory))
- return false;
- if (std::any_of(std::next(I1->getIterator()), At1, WritesMemory))
- return false;
- return true;
-}
-
// All blocks in Blocks unconditionally jump to a common successor. Analyze
// the last non-terminator instruction in each block and return true if it would
----------------
There's no Blocks parameter anymore, so the comment needs updating.
And is it checking that all instructions in Insts can be sunk together? Maybe rename to canSinkInstructions?
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:1348
@@ -1412,2 +1347,3 @@
- // If this isn't a store, check the only user is a single PHI.
+ // If this isn't a store, check the only user is a single PHI or in this
+ // block. If a user is in this block then it must come after I0 and
----------------
"this" is actually referring to all instructions in Instructions right? This keeps throwing me off, maybe it can be clarified somehow.
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:1368
@@ -1431,3 +1367,3 @@
};
if (!all_of(Insts, SameAsI0)) {
if (I0->mustOperandBeConstant(OI))
----------------
do we know that all the instructions in Insts have the same number of operands as I0?
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:1488
@@ +1487,3 @@
+ // each block upwards in lockstep. If the n'th instruction from the end of each
+ // block can be sunk, the values are added to ValuesToSink and we carry on.
+ // If we can sink an instruction but need to PHI-merge some operands (because
----------------
Does "the values" here refer to those n'th-last instructions or something else?
================
Comment at: lib/Transforms/Utils/SimplifyCFG.cpp:1495
@@ +1494,3 @@
+ SmallVector<SmallVector<Value*,4>,4> ValuesNeedingPHIs;
+ SmallVector<Value*,4> ThisValuesNeedingPHIs;
+ while (PopulateInsts(ScanIdx) &&
----------------
Pretty tricky names here, especially ValuesNeedingPHIs and ThisValuesNeedingPHIs.
Would it help if instead of "values needing phis" these were referred to as PHI operands? And maybe store in a DenseMap from "value (instruction?) to sink" to "PHI operands"?
Anyway I wonder if this could all be made more clear somehow.
Repository:
rL LLVM
https://reviews.llvm.org/D23911
More information about the llvm-commits
mailing list