[PATCH] D22599: GVN-hoist: improve code generation for recursive GEPs

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 23:51:33 PDT 2016


On Wed, Jul 20, 2016 at 6:04 PM, Daniel Berlin <dberlin at dberlin.org> wrote:

> FWIW: In gcc, the regeneration is a pair of mutually recursive functions,
> one called "create_expression_by_pieces" (which is the main interface), and
> one called "find_or_generate_expression"  (which in turn, calls
> create_expression_by_pieces for any operand that is itself a complex value
> expression).
>
> Whether you do it similarly, or worklist it, you should have some
> invariant that each iteration guarantees or whatever.
>
> I found mutual recursion easier because you can easily guarantee "at the
> end of this function we return the thing i need to place in this
> expression" for one of the functions, and there you go.
>

Both of these approaches sound find to me, I'd just prefer avoiding the
creation of unnecessary IR.


>
>
> On Wed, Jul 20, 2016 at 3:10 PM, David Majnemer <david.majnemer at gmail.com>
> wrote:
>
>> majnemer added inline comments.
>>
>> ================
>> Comment at: llvm/lib/Transforms/Scalar/GVNHoist.cpp:578-603
>> @@ +577,28 @@
>> +  // Make all operands of the GEP available.
>> +  bool makeGepOperandsAvailable(GetElementPtrInst *Gep, BasicBlock
>> *HoistPt,
>> +                                Instruction *Repl) const {
>> +    for (unsigned i = 0, e = Gep->getNumOperands(); i != e; ++i)
>> +      if (Instruction *Op = dyn_cast<Instruction>(Gep->getOperand(i))) {
>> +
>> +        // Check whether the operand is already available.
>> +        if (DT->dominates(Op->getParent(), HoistPt))
>> +          continue;
>> +
>> +        // As a GEP can refer to other GEPs, recursively check whether
>> all the
>> +        // operands of this GEP can be computed at HoistPt.
>> +        if (GetElementPtrInst *GepOp = dyn_cast<GetElementPtrInst>(Op))
>> +          if (!makeGepOperandsAvailable(GepOp, HoistPt, Gep))
>> +            return false;
>> +
>> +        // Failed to make Op available.
>> +        return false;
>> +      }
>> +
>> +    // Copy Gep and replace its uses in Repl with ClonedGep.
>> +    Instruction *ClonedGep = Gep->clone();
>> +    ClonedGep->insertBefore(HoistPt->getTerminator());
>> +    Repl->replaceUsesOfWith(Gep, ClonedGep);
>> +
>> +    return true;
>> +  }
>> +
>> ----------------
>> IIUC, this can mutate the IR while still returning false.
>>
>> I'd change this to be a worklist algorithm instead of a recursive one.
>> Inside the worklist loop, I'd push GEP candidates onto a vector for later
>> processing (cloning).
>>
>>
>> Repository:
>>   rL LLVM
>>
>> https://reviews.llvm.org/D22599
>>
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160720/727eca29/attachment.html>


More information about the llvm-commits mailing list