[PATCH] Reassociate GEP operands for loop invariant code motion
Jingyue Wu
jingyue at google.com
Tue Apr 21 16:51:58 PDT 2015
First round.
That's a *lot* of refactoring work. Appreciate it!
REPOSITORY
rL LLVM
================
Comment at: lib/Target/NVPTX/NVPTXTargetMachine.cpp:172
@@ -172,1 +171,3 @@
+ // generates significantly better code than EarlyCSE for some of our
+ // benchmarks.
if (getOptLevel() == CodeGenOpt::Aggressive)
----------------
Should we run LICM after ReassociateGEPs?
================
Comment at: lib/Target/PowerPC/PPCTargetMachine.cpp:266
@@ -265,3 +265,3 @@
if (TM->getOptLevel() == CodeGenOpt::Aggressive && EnableGEPOpt) {
- // Call SeparateConstOffsetFromGEP pass to extract constants within indices
+ // Call ReassociateGEPs pass to extract constants within indices
// and lower a GEP with multiple indices to either arithmetic operations or
----------------
extract loop invariants
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:126
@@ -86,2 +125,3 @@
+// codegen). Such transformation can have following benefits:
// (1) It can always extract constants in the indices of structure type.
// (2) After such Lowering, there are more optimization opportunities such as
----------------
minor: (1) and (2) are used before; try other numbering.
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:332
@@ +331,3 @@
+protected:
+ virtual bool visit(Value *V, bool &ContinueSearch);
+
----------------
I think LLVM generally prefers
```
bool visit(Value *V, bool &ContinueSearch) override;
```
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:616
@@ +615,3 @@
+ /* NonNegative */ false, UserChain)) {
+ Found = true;
+ Operand = Op;
----------------
Is `Found` necessary? Do we need to look at the second operand if already found what we want in the first operand?
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:629
@@ +628,3 @@
+ if (Found)
+ UserChain.clear();
+
----------------
What's the invariant between UserChain and Found? My understanding was, when Found is true, UserChain is non-empty containing the user chain from V to the found value, but the code here clears UserChain when Found.
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:634
@@ +633,3 @@
+ // We cannot do much with Values that are not a User, such as an Argument.
+ if (User *U = dyn_cast<User>(V)) {
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V)) {
----------------
Looks like we cannot do much with `ConstantExprs` either. Maybe just `dyn_cast<Instruction>` to pre-filter out more cases.
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:688
@@ +687,3 @@
+
+int64_t ConstantOffsetFinder::FindConstOffset(
+ GetElementPtrInst *GEP, unsigned OperandIdx,
----------------
s/FindConstOffset/findConstOffset
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:760
@@ +759,3 @@
+
+int LICMRanker::getRank(Value *V) {
+ Instruction *I = dyn_cast<Instruction>(V);
----------------
Can you comment on what the rank computes? Is it the deepest loop-level V can recursively reach?
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:770
@@ +769,3 @@
+ if (Loop *L = LI->getLoopFor(I->getParent())) {
+ int MaxRank = L->getLoopDepth();
+ if (isImmovableInstruction(I))
----------------
An instruction can use a value in a deeper loop if the loop is in a non-LCSSA form. Does `MaxRank = L->getLoopDepth()` still make sense?
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:784
@@ +783,3 @@
+
+bool LoopInvariantFinder::FindLoopInvariantValue(
+ GetElementPtrInst *GEP, unsigned OperandIdx, LICMRanker &Ranker,
----------------
s/FindLoopInvariantValue/findLoopInvariantValue/
or may be just `findLoopInvariant`?
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:786
@@ +785,3 @@
+ GetElementPtrInst *GEP, unsigned OperandIdx, LICMRanker &Ranker,
+ SmallVectorImpl<UserChainElement> &UserChain) {
+ int BaseRank = 0;
----------------
I've seen `UserChain` passed to lots of methods of HoistableValueFinder. Can we make it global to HoistableValueFinder?
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:830
@@ +829,3 @@
+ else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V)) {
+ // Don't recurse into subtract expressions.
+ if (BO->getOpcode() == Instruction::Sub)
----------------
Is recursing into subtract a TODO or problematic?
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:1135
@@ +1134,3 @@
+// %idx = add %a, %b
+// = gep %base, 42, %idx, %foo, %bar
+// The gep can be split at operand 2 (%idx) with IdxPart1 equal to %a
----------------
I was initially confused when I thought I saw
```
add %a, %b = gep %base, 42, %idx, %foo, %bar
```
:)
How about giving the gep a name instead of assigning it to blank? e.g.
```
%idx = add %a, %b
%p = gep %base, 42, %idx, %foo, %bar
```
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:1248
@@ -897,11 +1247,3 @@
- // Lowers a GEP to either GEPs with a single index or arithmetic operations.
- if (LowerGEP) {
- // As currently BasicAA does not analyze ptrtoint/inttoptr, do not lower to
- // arithmetic operations if the target uses alias analysis in codegen.
- if (TM && TM->getSubtargetImpl(*GEP->getParent()->getParent())->useAA())
- lowerToSingleIndexGEPs(GEP, AccumulativeByteOffset);
- else
- lowerToArithmetics(GEP, AccumulativeByteOffset);
- return true;
- }
+bool ReassociateGEPs::splitGEP(GetElementPtrInst *GEP, LICMRanker &Ranker) {
+ bool NeedsExtraction;
----------------
Can we split splitGEPForConst and splitGEPForLICM? The general logic seems:
```
if we can strip const offset from gep
gep = GEP with const offset stripped
splitGEPForLICM()
```
================
Comment at: lib/Transforms/Scalar/ReassociateGEPs.cpp:1359
@@ -989,2 +1358,3 @@
-bool SeparateConstOffsetFromGEP::runOnFunction(Function &F) {
+bool ReassociateGEPs::splitAndLowerGEP(GetElementPtrInst *GEP,
+ LICMRanker &Ranker) {
----------------
I'll come back to this function later. Looks like after we refactor splitGEP, splitGEP and splitAndLowerGEP can be merged?
================
Comment at: test/Transforms/ReassociateGEPs/NVPTX/split-licm-gep.ll:122
@@ +121,3 @@
+; be split at two of the indices forming two new loop-invariant geps which are
+; hoisted to different loop-depths.
+define void @double_loop([5 x [6 x i32]]* %input, i32* %output, i64 %a) {
----------------
Nice! :)
http://reviews.llvm.org/D9136
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
More information about the llvm-commits
mailing list