Prevent swapping of operands when both LHS and RHS are arguments.
Passes llvm regression
Details
- Reviewers
chandlerc mehdi_amini
Diff Detail
- Repository
- rL LLVM
Event Timeline
I came across this when I was reading the code, as such I do not know how to come up with a test case for this specific case.
I don't believe this case is testable, because line 1904 should swap them
back into the right order anyway.
All this patch will do is avoid extra work.
Oh then it is not even clear if it is worth it (avoid extra work here is doing an extra comparison to avoid a "pointer swap")
It seems VN.lookupOrAdd only swaps operands based on value numbers. Preferring constants/arguments on RHS seems unrelated to that, although I'm not sure this preference is useful in anyway.
Please don't avoid extra work in this way IMO, unless you have a very significant compile time hit due to this.
We have a pervasive reliance on canonicalizing constants to the RHS of binary operations so those should be exceedingly rare anyways. We shouldn't fight that, we should run with it.
My two cents. If Danny, Chad, or others working more on GVN disagree, they can happily override me. =D
Thanks for the feedback. This patch will not change the order of preference (RHS should keep Constants/Arguments). it only prevents swap when both LHS and RHS are Arguments.
I think his point is more the same one i made: "we shouldn't have to swap
at all, and if we do, we should fix that"
Chandler explicitly requested we take a different approach, and while I
could overrule him, not sure it's worth it for this patch.
I think we have spent more time on this thank it would take to track down
every place generating it that ends up needing to be swapped and fixing it
at the source
What Danny said here.
It feels like this patch is papering over failure to canonicalize. To make
progress we need to either:
a) Show a super clear example where there *is no canonicalization*. That
is, one usage wants one canonicalization and the other wants the other, so
we have to support both. If you can show that we cannot canonicalize this
because it is in tension with other canonicalization, that is exactly the
motivation that folks have asked for to land this patch.
or...
b) Fix everything to canonicalize so this patch isn't necessary.
So to generate examples where there are redundant swaps, I used this patch.
--- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1892,8 +1892,13 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root, continue; // Prefer a constant on the right-hand side, or an Argument if no constants. - if (isa<Constant>(LHS) || (isa<Argument>(LHS) && !isa<Constant>(RHS))) + if (isa<Constant>(LHS) + || (isa<Argument>(LHS) && !isa<Constant>(RHS))){ std::swap(LHS, RHS); + if (isa<Argument>(LHS) && isa<Argument>(RHS)) + llvm_unreachable("testcase: swapped once"); + } +
Following 7 test cases triggered with this patch:
./bin/opt < llvm/test/Transforms/GVN/2008-07-02-Unreachable.ll -basicaa -gvn -S | grep "ret i8 [%]tmp3"
./bin/opt < llvm/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll -basicaa -gvn -S
./bin/opt < llvm/test/Transforms/GVN/local-pre.ll -gvn -enable-pre -S
./bin/opt < llvm/test/Transforms/GVN/condprop.ll -basicaa -gvn -S
./bin/opt < llvm/test/Transforms/GVN/rle-semidominated.ll -basicaa -gvn -S
./bin/opt < llvm/test/Transforms/GVN/rle.ll -default-data-layout="E-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-n32" -basicaa -gvn -S -die
./bin/opt < llvm/test/Transforms/GVN/rle-nonlocal.ll -basicaa -gvn -S
Ok, so this is eliminating swaps. But these are just pointer swaps -- what is the motivation for eliminating them? What does that improve?