-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[GVN] Look through select/phi when determining underlying object #99509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f98349d
291ffd2
25857e8
f160e9c
8e5f7b8
cac98c1
44714f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -736,6 +736,10 @@ inline Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6) { | |
return const_cast<Value *>(getUnderlyingObject(VConst, MaxLookup)); | ||
} | ||
|
||
/// Like getUnderlyingObject(), but will try harder to find a single underlying | ||
/// object. In particular, this function also looks through selects and phis. | ||
const Value *getUnderlyingObjectAggressive(const Value *V); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you still expose a parameter to control the aggressiveness? Aggressive without a parameter is kind of scary. E.g. the size of the visited set? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, we should not expose unnecessary options. If we have reason to have different levels of aggressiveness for different callers in the future, we will add the option at the time. Until then, cutoffs should be centrally controlled. |
||
|
||
/// This method is similar to getUnderlyingObject except that it can | ||
/// look through phi and select instructions and return multiple objects. | ||
/// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6609,6 +6609,48 @@ void llvm::getUnderlyingObjects(const Value *V, | |
} while (!Worklist.empty()); | ||
} | ||
|
||
const Value *llvm::getUnderlyingObjectAggressive(const Value *V) { | ||
const unsigned MaxVisited = 8; | ||
|
||
SmallPtrSet<const Value *, 8> Visited; | ||
SmallVector<const Value *, 8> Worklist; | ||
Worklist.push_back(V); | ||
const Value *Object = nullptr; | ||
// Used as fallback if we can't find a common underlying object through | ||
// recursion. | ||
bool First = true; | ||
const Value *FirstObject = getUnderlyingObject(V); | ||
do { | ||
const Value *P = Worklist.pop_back_val(); | ||
P = First ? FirstObject : getUnderlyingObject(P); | ||
First = false; | ||
|
||
if (!Visited.insert(P).second) | ||
continue; | ||
|
||
if (Visited.size() == MaxVisited) | ||
return FirstObject; | ||
|
||
if (auto *SI = dyn_cast<SelectInst>(P)) { | ||
Worklist.push_back(SI->getTrueValue()); | ||
Worklist.push_back(SI->getFalseValue()); | ||
continue; | ||
} | ||
|
||
if (auto *PN = dyn_cast<PHINode>(P)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the loop case, there's also a variant of Would that help/Should this be unified? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that we don't need that isSameUnderlyingObjectInLoop() logic as long as we're reducing down to a single underlying object. What this handles is the case where you have underlying objects from different loop iterations that have the same SSA value -- this is the same basic issue as "value equal in potential cycles" in BasicAA. However, if we're reducing to a single object, then this can't happen, because we have both a contribution from the pre-header and the loop. The loop contribution has to reduce back to the loop phi to end up with a single object. If it reduces to a loop variant value, then we'd have at least two underlying objects. |
||
append_range(Worklist, PN->incoming_values()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe there should be a check that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As implemented, a phi with more than MaxVisited could be accepted as long as some of the arguments reduce to the same object (as returned by getUnderlyingObject). Though I'd be open to make this a more strict limit on the number of getUnderlyingObject calls, regardless of what they return. I mainly want to make sure we don't run into pathological cases. The cost of this analysis seems to be negligible for the average case. |
||
continue; | ||
} | ||
|
||
if (!Object) | ||
Object = P; | ||
else if (Object != P) | ||
return FirstObject; | ||
} while (!Worklist.empty()); | ||
|
||
return Object; | ||
} | ||
|
||
/// This is the function that does the work of looking through basic | ||
/// ptrtoint+arithmetic+inttoptr sequences. | ||
static const Value *getUnderlyingObjectFromInt(const Value *V) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.