[llvm-commits] [PATCH][SOPT] Fix assertion in Reassociate

Shuxin Yang shuxin.llvm at gmail.com
Tue Nov 6 17:14:55 PST 2012


>Two quick questions:
>1. Is it generic enough to expose the class as a LLVM ADT?
Actually I used template to implement this worklist at beginning, hoping it will be promoted into ADT.
I were blocked at the in-place removal. The value_type is actually AssertingVH<Instruction> which is
kinda smartpointer of Instruction*.

In the code excerpted bellow, if I replace the "Instruction*" (@ line 378) with the value_type,
I will see assertion somewhere. The reason is that the destructor of "t" needs to be called
before cb(), which is impossible.


369 // inplace_rremove() is the same as inplace_remove() except that elements
  370 // are visited in backward order.
  371 template <typename pred, typename call_back_func>
  372 int RedoWorklist::inplace_rremove(pred p, call_back_func cb) {
  373   int cnt = 0;
  374   for (typename deque_type::reverse_iterator iter = deque_.rbegin(),
  375        iter_e = deque_.rend(); iter != iter_e; iter++) {
  376     value_type &element = *iter;
  377     if (p(element) && set_.erase(element)) {
  378       Instruction* t = element;
  379       element.~value_type();
  380       new (&element) value_type(NULL);
  381       cb(t);
  382       cnt ++;
  383     }
  384   }
  385   return cnt;
  386 }
  387
  
The original code does not have problem, see following code

     Worklist<<AssertingVH<Instruction> > Worklist;
     
     Instruction* I = Worklist.pop_front_val(); // the AssertingVH<Instruction>::~AssertingVH<Instruction> is called right after this stmt.
  



> 2. Does this patch have noticeable impact on compile time?

  It would be noticeable slower if I use std::list and std::map combination.
I don't know if my implementation is faster or slower than the original worklist (using SetVector) as the TOT revision
exit prematurely. But, I think the the data structures I'm using is very efficient: std::deque + std::map.

Shuxin


On 11/6/12 4:30 PM, Evan Cheng wrote:
> On Nov 5, 2012, at 10:47 PM, Shuxin Yang <shuxin.llvm at gmail.com> wrote:
>
>> This patch is to fix rdar://12571717, it is about assertion in Reassociate pass.
>>
>>   Long story short, the assertion is trigged when the pass try to transform expression
>>      ... + 2 * n * 3 + 2 * m + ...
>>   into:
>>      ... + 2 * (n*3 + m).
>>
>>   In the process of the transformation, a helper routine folds the constant 2*3 into 6,
>> confusing optimizer which is trying the to eliminate the common factor 2, and cannot
>> find 2 any more.
>>
>>   Weaken the assertion doesn't help, as the transformation is half done.
>> There are two ways to fix the probelm:
>>   1) Ask the helper routine don't do better job, just do what it is expected.
>>   2) Walk the expression worklist in a order such that sub-expr is visited prior to
>>      the supper-expr. This way, 2*3 is already folded before the super-expr is visited.
>>
>> 1) entails lots of change, 2) seems to be easier. It is just opposite:-(
>>
>> I go for 2) not only because it seemed to be easier in the first place,
>> I think it is the right order to go through expressions being reassociated.
>>
>> The testing case (reduced by bugpoint) for this probelm is not inclued in the patch, as it
>> is too big.
>>
>> Thanks
>> Shuxin
>>
>> ================================================================================
>>
>> Worklist
>> ========
>>
>>    The worklist WAS using SetVector. It was a container both for dead instructions and
>> the expressions that could be optimized via reassociation. Exprs, no matter dead code
>> or the those to be reassociated, are visited in FILO order.
>>
>>    I rewrite the worklist. The new worklist has following traits:
>>     o. it is basically std::deque
>>     o. has "set" semantic, akin to the SetVector. Unlike the setVector, the
>>        set is implemented using std::map instead of SmallVector for efficiency
>>        purpose (In the case I'm working on, the worklist contains about 1.5k
>>        instrucitons).
>>     o. all dead instructions are eliminated in one loop: optimize iterates the
>>        worklist in *backward* order, identifying the dead code, and
>>        removing them "in-place". The "in-place" removal is done by invlaiding
>>        the element instead of physically removing the space from the worklist.
>>        This way, it obviates the need of memory move, and avoid invalidating
>>        iterator.
>>     o. the rest exprs are visited in forward order (i.e. FIFO)
>>
>>    This part is implemented using STL style. It is so odd to see "PushBack" when
>> we are getting used to "push_back":-)
> Two quick questions:
> 1. Is it generic enough to expose the class as a LLVM ADT?
> 2. Does this patch have noticeable impact on compile time?
>
> Thanks,
>
> Evan
>
>> Other changes:
>> ===============
>>   The new worklist exposes some defects.
>>
>>   1. test/Transforms/Reassociate/multistep.ll
>>      Without my change a*a*b+a*a*c was turned into a*(a*(b+c)); with my
>>      change the result is (a*a)*(b+c). I don't know for sure if the reassociator
>>      intentionally choose tall-and-skinny expr tree in order to reduce register pressure.
>>
>>   2. test/Transforms/Reassociate/mul_neg.ll (new)
>>
>>      The reassociator was not able to perform following simplifiction:
>>       (-x) * c => x * -c ,
>>        -x * -y => -x * -y
>>      if the negations are used in multiple placess.
>>
>>     The optimization now is implemented by Reassociate::removeNegFromMulOps().
>>     Without this opt, we will see three regressions.
>>
>> <diff.patch>_______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list