[InstCombine] Fold shl of constant by cttz into multiply of lowest set bit - #214517
Conversation
|
ping |
|
@nikic Could you take a look when you have time? Thank you! |
…project into instcombine-shl # 请输入一个提交信息以解释此合并的必要性,尤其是将一个更新后的上游分支 # 合并到主题分支。 # # 以 '#' 开始的行将被忽略,而空的提交说明将终止提交。
Update comment to clarify behavior of is_zero_poison.
|
ping |
dtcxzyw
left a comment
There was a problem hiding this comment.
Generalized proof: https://alive2.llvm.org/ce/z/TmWxrT
| { | ||
| Value *X; | ||
| const APInt *C; | ||
| if (match(Op0, m_APInt(C)) && |
There was a problem hiding this comment.
It should not be limited to constant LHS cases.
Removing the constraint enables more optimizations:
dtcxzyw/llvm-opt-benchmark-nightly#924
dtcxzyw/llvm-opt-benchmark-nightly#926
| Value *X; | ||
| const APInt *C; | ||
| if (match(Op0, m_APInt(C)) && | ||
| match(Op1, m_OneUse(m_Cttz(m_Value(X), m_One())))) { |
There was a problem hiding this comment.
| match(Op1, m_OneUse(m_Cttz(m_Value(X), m_One())))) { | |
| match(Op1, m_OneUse(m_Cttz(m_Value(X), m_Value())))) { |
is_zero_poison can be false.
| match(Op1, m_OneUse(m_Cttz(m_Value(X), m_One())))) { | ||
| Value *NegX = Builder.CreateNeg(X, "neg"); | ||
| Value *LowBit = Builder.CreateAnd(NegX, X); | ||
| return BinaryOperator::CreateMul(LowBit, Op0); |
There was a problem hiding this comment.
Thank you for your suggestions. I'll update this patch.
|
@dtcxzyw, I've updated the patch to address your feedback:
|
| { | ||
| Value *X; |
There was a problem hiding this comment.
| { | |
| Value *X; |
Just use the declaration above.
There was a problem hiding this comment.
Applied your suggetion, thanks
…sary brace and reuse existing X variable declaration
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/218/builds/6108 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/151/builds/10843 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/158/builds/19926 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/216/builds/6025 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/119/builds/10749 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/105/builds/20560 Here is the relevant piece of the build log for the reference |
|
Should this fold be implemented in codegen instead? It introduced regressions on both aarch64 and x86. |
See https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/926/files. In some cases the mul will be removed by other middle-end optimizations. The backend should recognize this pattern and revert the transform. I am worried that is_zero_poison may not be re-inferred in SDAG. If this is a bottleneck, we have to implement this fold in DAGCombiner. cc @RKSimon |
|
Most likely this needs tweaking in isel as a per-backend (not generic) fold - hopefully avoiding a tuning flag....... |
Currently,
C << cttz(X, true)generates a DeBruijn lookup table on RV64I (13 instructions).And this patch adds a fold in InstCombine:
C << cttz(X, true) --> (-X & X) * CThis reduces the instruction count from 13 to 3 on RV64I.
The fold requires that cttz has a single use (to avoid increasing instruction count)
Alive2 proof: https://alive2.llvm.org/ce/z/TmWxrT