[PATCH] Top-Down FunctionAttrs propagation for noalias, dereferenceable and nonnull inference
Philip Reames
listmail at philipreames.com
Wed Sep 10 10:59:48 PDT 2014
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.
================
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
More information about the llvm-commits
mailing list