[llvm] r185843 - Fix a SCEV update problem.
Shuxin Yang
shuxin.llvm at gmail.com
Fri Jul 12 00:03:50 PDT 2013
On 7/11/13 11:54 PM, Nick Lewycky wrote:
> Shuxin Yang wrote:
>> Author: shuxin_yang
>> Date: Mon Jul 8 12:33:13 2013
>> New Revision: 185843
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=185843&view=rev
>> Log:
>> Fix a SCEV update problem.
>>
>> The symptom is seg-fault, and the root cause is that a SCEV
>> contains a SCEVUnknown
>> which has null-pointer to a llvm::Value.
>>
>> This is how the problem take place:
>> ===================================
>> 1). In the pristine input IR, there are two relevant instrutions
>> Op1 and Op2,
>> Op1's corresponding SCEV (denoted as SCEV(op1)) is a
>> SCEVUnknown, and
>> SCEV(Op2) contains SCEV(Op1). None of these instructions are
>> dead.
>>
>> Op1 : V1 = ...
>> ...
>> Op2 : V2 = ... // directly or indirectly (data-flow) depends on
>> Op1
>>
>> 2) Optimizer (LSR in my case) generates an instruction holding the
>> equivalent
>> value of Op1, making Op1 dead.
>> Op1': V1' = ...
>> Op1: V1 = ... ; now dead)
>> Op2 : V2 = ... //Now deps on Op1', but the SCEV(Op2) still
>> contains SCEV(Op1)
>>
>> 3) Op1 is deleted, and call-back function is called to reset
>> SCEV(Op1) to indicate it is invalid. However, SCEV(Op2) is not
>> invalidated as well.
>>
>> 4) Following pass get the cached, invalid SCEV(Op2), and try to
>> manipulate it,
>> and cause segfault.
>>
>> The fix:
>> ========
>> It seems there is no clean yet inexpensive fix. I write to dev-list
>> soliciting good solution, unforunately no ack. So, I decide to fix this
>> problem in a brute-force way:
>>
>> When ScalarEvolution::getSCEV is called, check if the cached SCEV
>> contains a invalid SCEVUnknow, if yes, remove the cached SCEV, and
>> re-evaluate the SCEV from scratch.
>>
>> I compile buch of big *.c and *.cpp, fortunately, I don't see any
>> increase
>> in compile time.
>>
>> Misc:
>> =====
>> The reduced test-case has 2357 lines of code+other-stuff, too big
>> to commit.
>>
>> rdar://14283433
>
> I have a question about the symptom. SCEV(Op1) is invalidated, does
> that mean that SCEV(Op2) holds a dangling pointer? If so, don't we
> still have a bug if a new SCEV happens to be allocated at the old
> address?
No dangling pointer.
"SCEV(Op1) is invalidated" by resetting SCEV(Op1)'s field (i.e.
SCEVUnknown::ValPtr) to null.
The SCEV(Op1) instance is still there.
> Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=185843&r1=185842&r2=185843&view=diff
>> ==============================================================================
>>
>> --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
>> +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Jul 8 12:33:13 2013
>> @@ -2715,13 +2715,51 @@ const SCEV *ScalarEvolution::getCouldNot
>> return&CouldNotCompute;
>> }
>>
>> +namespace {
>> + // Helper class working with SCEVTraversal to figure out if a SCEV
>> contains
>> + // a SCEVUnknown with null value-pointer.
>> FindInvalidSCEVUnknown::FindOne
>> + // is set iff if find such SCEVUnknown.
>> + //
>> + struct FindInvalidSCEVUnknown {
>> + bool FindOne;
>> + FindInvalidSCEVUnknown() { FindOne = false; }
>
> Constructor initializer list?
Not sure you question. There is list involved here.
>
>> + bool follow(const SCEV *S) {
>> + switch (S->getSCEVType()) {
>> + case scConstant:
>> + return false;
>> + case scUnknown:
>> + if(!cast<SCEVUnknown>(S)->getValue())
>
> Missing space after 'if'.
Will fix stylistic problems soon.
More information about the llvm-commits
mailing list