[PATCH] Top-Down FunctionAttrs propagation for noalias, dereferenceable and nonnull inference
Hal Finkel
hfinkel at anl.gov
Wed Sep 10 11:13:01 PDT 2014
----- Original Message -----
> From: "Philip Reames" <listmail at philipreames.com>
> To: hfinkel at anl.gov, chandlerc at gmail.com, nicholas at mxc.ca, listmail at philipreames.com
> Cc: llvm-commits at cs.uiuc.edu
> Sent: Wednesday, September 10, 2014 12:59:48 PM
> Subject: Re: [PATCH] Top-Down FunctionAttrs propagation for noalias, dereferenceable and nonnull inference
>
> Overall, looks pretty reasonable. A few minor code comments inline.
>
> I might suggest separating the addition of the patch and adding to
> the pass manager. In particular, adding the second run of the
> attribute analysis should probably be discussed more broadly.
Thanks for the review!
I also need to revisit the way that the noalias inference is done because it is not quite right in this patch. Just checking alias(AI, BI) == NoAlias is not sufficient: a[i] and a[i+1] don't alias, but obviously pointers based on them could. I can really only do this when we have distinct sets of underlying objects (which makes several other things much simpler -- including the capture checking and the ramifications on the optimization pipeline).
-Hal
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:82
> @@ +81,3 @@
> + bool MadeChange = false;
> + if (F.isDeclaration() || !F.hasLocalLinkage() || F.arg_empty() ||
> + F.use_empty())
> ----------------
> Stylistically, I'd prefer this separated into two checks. Your
> combining correctness and profitability criteria. Also, rather than
> "return MadeChange", just "return false" for the early exits. It
> makes the flow clearer.
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:91
> @@ +90,3 @@
> + bool IsAlign;
> + uint64_t MaxSize, MaxAlign;
> +
> ----------------
> Please rename MaxSize. It appears to actually be
> MaxKnownDeferenceable and the current name is highly confusing.
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:112
> @@ +111,3 @@
> + SmallVector<AttrState, 16> ArgumentState;
> + ArgumentState.resize(F.arg_size());
> +
> ----------------
> A comment here that reminds the reader the default state is fully
> speculative/optimistic would be helpful.
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:114
> @@ +113,3 @@
> +
> + for (Use &U : F.uses()) {
> + User *UR = U.getUser();
> ----------------
> Do you need to iterate the uses, or can you iterate the users
> directly?
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:125
> @@ +124,3 @@
> + CallSite CS(cast<Instruction>(UR));
> + if (!CS.isCallee(&U))
> + return MadeChange;
> ----------------
> Shouldn't this be F?
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:131
> @@ +130,3 @@
> + Function::arg_iterator Arg = F.arg_begin();
> + for (unsigned i = 0, e = ArgumentState.size(); i != e; ++i,
> ++AI, ++Arg) {
> + // If we've already excluded this argument, ignore it.
> ----------------
> A general point: this function is *way* too complex. Split it into
> reasonable helper functions. One arrangement would be:
> struct ArgState
> updateArgAtCallSite(...) {}
> updateForCallSite(...) {}
> identifyCallSites(...) {}
> addIndicatedAtrributes(...) {}
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:157
> @@ +156,3 @@
> + ArgumentState[i].IsDereferenceable = false;
> + // FIXME: isSafeToLoadUnconditionally does not understand
> memset.
> + // FIXME: We can use getObjectSize for most things, but
> for mallocs
> ----------------
> Is this a correctness bug? Or a missed optimization? I can't tell
> from your FIXME.
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:170
> @@ +169,3 @@
> + // trap, so we can use at least that size.
> + Size = std::max(Size, TypeSize);
> + }
> ----------------
> Er, this doesn't look right. We've verified that loading from the
> pointer *up to* a certain number of bytes is safe. We have not said
> anything beyond that.
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:175
> @@ +174,3 @@
> + if (!ArgumentState[i].MaxSize)
> + ArgumentState[i].IsDereferenceable = false;
> + }
> ----------------
> It looks like IsDerefernceable could become a function of MaxSize on
> the state object?
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:184
> @@ +183,3 @@
> + unsigned Align = getKnownAlignment(*AI, DL);
> + if (Align > DL->getABITypeAlignment(ETy))
> + ArgumentState[i].MaxAlign =
> ----------------
> I don't understand why you need this check. Is it safe to record an
> align attribute less than the ABI alignment? If not, that seems
> slightly odd.
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:236
> @@ +235,3 @@
> +
> + bool HaveCand = false;
> + for (unsigned i = 0, e = ArgumentState.size(); i != e; ++i)
> ----------------
> I'm not clear why this check is needed. Aren't you only iterating
> 'number of argument' times anyways?
>
> ================
> Comment at: lib/Transforms/IPO/FunctionAttrsTD.cpp:249
> @@ +248,3 @@
> + for (unsigned i = 0, e = ArgumentState.size(); i != e; ++i, ++AI)
> {
> + if (!ArgumentState[i].any() || AI->hasInAllocaAttr() ||
> AI->hasByValAttr())
> + continue;
> ----------------
> The first is just an early exit, but what are the second two checks
> for? Are they functionally required?
>
> http://reviews.llvm.org/D4609
>
>
>
--
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory
More information about the llvm-commits
mailing list