Optimize (add (shl x, c0), (shl y, c1)) to
(SLLI (SHxADD y, x), c0) if applicable.
Paths
| Differential D109729
[RISCV] Optimize (add (shl x, c0), (shl y, c1)) AbandonedPublic Authored by benshi001 on Sep 13 2021, 4:36 PM.
Details
Summary Optimize (add (shl x, c0), (shl y, c1)) to (SLLI (SHxADD y, x), c0) if applicable.
Diff Detail Event TimelineHerald added subscribers: vkmr, frasercrmck, evandro and 22 others. · View Herald TranscriptSep 13 2021, 4:36 PM Comment Actions The reason I write both AddShlShl_1A and def AddShlShl_1B, is that add is not commutative in PatFrag.
Comment Actions
You should write that as a comment in the code. Comment Actions
Actually it's worse than that. Tablegen does know the pattern is commutable and will call you predicate function twice. But one of the calls will be wrong. I hope it is guaranteed that the correct check always happens first. There is a feature to make this work. It involves setting "let PredicateCodeUsesOperands = 1;" on the PatFrag. Only AMDGPU uses it. You should look up the patch that added it. Comment Actions Using let PredicateCodeUsesOperands = 1 makes code more boring and complex. So I have resorted to using DAG2GAG selection which looks more clear. Comment Actions
I'm not sure what you mean by boring here. Can you share one of the PatFrags using that feature? Comment Actions
I mean the similar code is copied 6 times which is boring, and it becomes more complex than I expected. and I think using DAG2DAG is more clear. Comment Actions
Using let PredicateCodeUsesOperands = 1 also needs implementing let GISelPredicateCode = [{...}], otherwise the TableGen will failed. such as def patfrags_test_pat : PatFrags< (ops node:$x, node:$y, node:$z), [ (xor (add node:$x, node:$y), node:$z), (xor (sub node:$x, node:$y), node:$z) ], [{ return foo(); }]> { let GISelPredicateCode = [{ return doesComplexCheck(MI); }]; let PredicateCodeUsesOperands = 1; } That make the code becomes more redundant and complex. Comment Actions
The PredicateCodeUsesOperands feature should only require 3 PatFrags that look like this, but I can't get it to compile. let PredicateCodeUsesOperands = 1 in def AddShlShl_1A : PatFrag<(ops node:$A, node:$B, node:$C, node:$D), (add (shl node:$A, node:$B), (shl node:$C, node:$D)), [{ SDValue N0 = Operands[0], N1 = Operands[1]; if (!N0.hasOneUse() || !N1.hasOneUse()) return false; auto *N0C = cast<ConstantSDNode>(N0.getOperand(1)); auto *N1C = cast<ConstantSDNode>(N1.getOperand(1)); uint64_t C0 = N0C->getZExtValue(), C1 = N1C->getZExtValue(); return C0 == C1 + 1; }]>;
benshi001 marked 3 inline comments as done.
Revision Contents
Diff 372366 llvm/lib/Target/RISCV/RISCVInstrInfoB.td
llvm/test/CodeGen/RISCV/rv32zba.ll
llvm/test/CodeGen/RISCV/rv64zba.ll
|
This should just be a templated class that takes the +/- 1/2/3 as an argument rather than copy-pasting the same thing 6 times. Though the number of patterns and special cases for all the bitmanip stuff seems to be getting rather crazy; is there an end in sight?