[PATCH] Remove unnecessary variable indexing into single-element arrays
Chandler Carruth
chandlerc at gmail.com
Thu Feb 19 18:39:35 PST 2015
Generally looks fine to commit whenever. Mostly small bits below.
================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:474
@@ +473,3 @@
+// or equal to the provided maximum size, then return true. Otherwise, return
+// false (constant global values and allocas fall into this category).
+static bool isObjectSizeLessThanOrEq(Value *V, uint64_t MaxSize,
----------------
Add a FIXME to hoist this into Analysis or somewhere it can be re-used? We should make it widely available. This is a great pattern to detect.
================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:592-595
@@ +591,6 @@
+
+ // If there are more indices after the one we might replace with a zero, make
+ // sure they're all non-negative. If any of them are negative, the overall
+ // address being computed might be before the base address determined by the
+ // first non-zero index.
+ auto AllNonNegative = [&]() -> bool {
----------------
Maybe too clever, but what do you think about bailing the first time you see a positive index as well since you're checking for inbounds? You could make the predicate "canBacktrackFromPastEnd" or some such. As soon as you see a potentially negative index return true, as soon as you see a definitely positive index, return false, if you exhaust the indices return false.
================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:596
@@ +595,3 @@
+ // first non-zero index.
+ auto AllNonNegative = [&]() -> bool {
+ for (unsigned i = Idx+1, e = GEPI->getNumOperands(); i != e; ++i) {
----------------
nit: no need for explicit return type. You can make it more explicit this is a predicate with an 'is' or can' name prefix...
================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:632-634
@@ -491,1 +631,5 @@
+ // If we're indexing into an object with a variable index for the memory
+ // access, but the object has only one element, we can assume that the index
+ // will always be zero.
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Op)) {
----------------
hfinkel wrote:
> chandlerc wrote:
> > Gah. Almost. But not quite.
> >
> > We have to be able to form one-past-the-end of the object. So if all the subsequent pointers are 0, the one that strides the object could be 1 instead of 0.
> >
> > I think we need to look for a *positive* tail (not just non-negative) of the GEP, or we need to look at the users and fold if they would be UB for a one-past-the-end GEP. Essentially, as long as we're post-dominated or only used by a load or store, we're golden.
> No, I think this is fine. We do need to be able to form one-past-the-end, but we don't need to load from it. Here I know we're loading from it, so it can't be the one-past-the-end pointer.
>
> This is why I clone the GEP and then change it, so only the load or store gets the rewritten GEP, not any other users of the original pointer.
>
Totally missed that you were carefully only transforming a load or store's GEP. Yea, we're on the same page now.
================
Comment at: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp:833
@@ +832,3 @@
+ SI.setOperand(SI.getPointerOperandIndex(), NewGEPI);
+ Worklist.Add(NewGEPI);
+ return &SI;
----------------
hfinkel wrote:
> chandlerc wrote:
> > As long as you use the instruction combiner's IR builder, this isn't necessary.
> Right, but I'm not.
Could you? I find that pattern cleaner. We pass IR builders into helper functions regularly.
http://reviews.llvm.org/D7776
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
More information about the llvm-commits
mailing list