[llvm-commits] [PATCH] Make EarlyCSE understand commutativity
Michael Ilseman
milseman at apple.com
Mon Sep 24 09:46:10 PDT 2012
On Sep 22, 2012, at 3:01 AM, Duncan Sands <baldrick at free.fr> wrote:
> Hi Michael,
>
>>> The attached patch and tests alter EarlyCSE to also check for commuted values. This allows EarlyCSE to replace:
>>>
>>> t1 = fadd a, b
>>> t2 = fadd b, a
>>>
>>> with:
>>> t1 = fadd a, b
>
> -ENOTESTCASE.
>
Tests cases were in the commute.ll file that was attached along with the patch.
>> @@ -397,8 +398,30 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
>>
>> // If this is a simple instruction that we can value number, process it.
>> if (SimpleValue::canHandle(Inst)) {
>> +
>> // See if the instruction has an available value. If so, use it.
>> - if (Value *V = AvailableValues->lookup(Inst)) {
>> + Value *V = AvailableValues->lookup(Inst);
>> +
>> + // If this is a commutative op, also see if its commuted value is
>> + // available.
>> + if (!V) {
>> + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst)) {
>> + if (BinOp->isCommutative()) {
>> + BinaryOperator *Commuted = cast<BinaryOperator>(BinOp->clone());
>> + Commuted->swapOperands();
>> + V = AvailableValues->lookup(Commuted);
>> + ilist_node_traits<Instruction>::deleteNode(Commuted);
>
> urgh, I really don't like creating an instruction just to look it up, then
> deleting it again. Can you make the lookup logic more flexible instead?
> By the way, how GVN takes care of commutativity is: when computing the value
> number for an instruction, it sorts the operands of commutative instructions
> (its sorts the operands according to their value number) before calculating
> a value number from them, ensuring that if two commutative instructions are
> the same except for a different operand order then they get the same value
> number. I don't know how EarlyCSE works, but maybe something along these lines
> would also be possible?
>
Thanks for the feedback!
I also don't like making a new instruction, but considered it the lesser of evils. Essentially, EarlyCSE uses a DenseMap over the instructions, but overloading hash to hash the instruction itself rather than its address. It also overloads isEqual to call Instruction::isIdenticalTo.
As far as changing the lookup mechanism, that would involve both sorting operand hashes on getHashValue, and extending Instruction::isIdenticalToWhenDefined to also calculate equality modulo commutativity (or, essentially inlining its body into the overloaded isEqual function rather than making the call). I don't know what is more desirable, but the original patch to EarlyCSE at least kept it very localized and would only trigger when a commutative op was encountered.
Another option is to restructure EarlyCSE to do expression numbering similarly to GVN, as you mentioned. Again, I don't know if this is more desirable over a localized call to clone(), as this would require a re-encapsulation of Instruction's data that would affect all of EarlyCSE.
> Ciao, Duncan.
>
>> + }
>> + } else if (CmpInst *CI = dyn_cast<CmpInst>(Inst)) {
>> + // For CmpInst, swapping will also correct the predicate
>> + CmpInst *Commuted = cast<CmpInst>(CI->clone());
>> + Commuted->swapOperands();
>> + V = AvailableValues->lookup(Commuted);
>> + ilist_node_traits<Instruction>::deleteNode(Commuted);
>> + }
>> + }
>> +
>> + if (V) {
>> DEBUG(dbgs() << "EarlyCSE CSE: " << *Inst << " to: " << *V << '\n');
>> Inst->replaceAllUsesWith(V);
>> Inst->eraseFromParent();
>
>
>
> _______________________________________________
> 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