Optimize (add (shl x, c0), (shl y, c1)) to
(SLLI (SHxADD y, x), c0) if applicable.
Differential D109729
[RISCV] Optimize (add (shl x, c0), (shl y, c1)) benshi001 on Sep 13 2021, 4:36 PM. Authored by
Details
Optimize (add (shl x, c0), (shl y, c1)) to (SLLI (SHxADD y, x), c0) if applicable.
Diff Detail Event TimelineComment Actions The reason I write both AddShlShl_1A and def AddShlShl_1B, is that add is not commutative in PatFrag.
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; }]>;
|
vevtor->vector