[PATCH] D71568: [InstCombine] `select + mul` -> `select + shl` with power of twos.
Roman Lebedev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 17 14:20:57 PST 2019
lebedev.ri requested changes to this revision.
lebedev.ri added a comment.
This revision now requires changes to proceed.
Thank you for working on this.
================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:265
+// X mul 2^C -> X << C
+static Instruction *foldMulPow2Cst(Value *Op0, Value *Op1,
+ const BinaryOperator &I, InstCombiner &IC) {
----------------
I think it would be better to change Op1 type to `Constant`, and make the caller do the cast.
================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:268-269
+ Constant *C1 = getLogBase2(Op0->getType(), cast<Constant>(Op1));
+ C1 = Constant::replaceUndefsWith(
+ C1, ConstantInt::get(C1->getType()->getScalarType(), 0));
+ if (!C1)
----------------
Add a comment explaining that we really do need to sanitize `undef` to `0` here.
================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:281
+// X mul (C1 << N), where C1 is "1<<C2" --> X << (N+C2)
+// X mul (zext (C1 << N)), where C1 is "1<<C2" --> X << (N+C2)
+static Instruction *foldMulShl(Value *Op0, Value *Op1, const BinaryOperator &I,
----------------
// X mul (zext (C1 << N)), where C1 is "1<<C2" --> X << (zext (add N, C2))
================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp:320-325
+ // X mul (C1 << N), where C1 is "1<<C2" --> X << (N+C2)
+ if (match(Op1, m_Shl(m_Power2(), m_Value())) ||
+ match(Op1, m_ZExt(m_Shl(m_Power2(), m_Value())))) {
+ Actions.push_back(OperandFoldAction(foldMulShl, Op1));
+ return Actions.size();
+ }
----------------
If i'm reading this correctly, these are miscompilations:
https://rise4fun.com/Alive/IKH
================
Comment at: llvm/test/Transforms/InstCombine/mul.ll:669-682
define i32 @shift_if_power2_double_select(i32 %x, i32 %y, i1 %cond1, i1 %cond2) {
; CHECK-LABEL: @shift_if_power2_double_select(
-; CHECK-NEXT: [[SHL_RES:%.*]] = shl i32 8, [[Y:%.*]]
-; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND1:%.*]], i32 [[SHL_RES]], i32 1024
-; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[COND2:%.*]], i32 16, i32 [[SEL1]]
-; CHECK-NEXT: [[R:%.*]] = mul nuw i32 [[SEL2]], [[X:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], 3
+; CHECK-NEXT: [[DOTV:%.*]] = select i1 [[COND1:%.*]], i32 [[TMP1]], i32 10
+; CHECK-NEXT: [[R_V:%.*]] = select i1 [[COND2:%.*]], i32 4, i32 [[DOTV]]
+; CHECK-NEXT: [[R:%.*]] = shl nuw i32 [[X:%.*]], [[R_V]]
; CHECK-NEXT: ret i32 [[R]]
----------------
This is a miscompile:
```
----------------------------------------
define i32 @shift_if_power2_double_select(i32 %x, i32 %y, i1 %cond1, i1 %cond2) {
%0:
%shl.res = shl i32 8, %y
%sel1 = select i1 %cond1, i32 %shl.res, i32 1024
%sel2 = select i1 %cond2, i32 16, i32 %sel1
%r = mul nuw i32 %x, %sel2
ret i32 %r
}
=>
define i32 @shift_if_power2_double_select(i32 %X, i32 %Y, i1 %COND1, i1 %COND2) {
%0:
%TMP1 = add i32 %Y, 3
%DOTV = select i1 %COND1, i32 %TMP1, i32 10
%R_V = select i1 %COND2, i32 4, i32 %DOTV
%R = shl nuw i32 %X, %R_V
ret i32 %R
}
Transformation doesn't verify!
ERROR: Target is more poisonous than source
Example:
i32 %x = #x0f360904 (255199492)
i32 %y = #x0000001d (29)
i1 %cond1 = #x1 (1)
i1 %cond2 = undef
Source:
i32 %shl.res = #x00000000 (0)
i32 %sel1 = #x00000000 (0)
i32 %sel2 = #x00000000 (0) [based on undef value]
i32 %r = #x00000000 (0)
Target:
i32 %TMP1 = #x00000020 (32)
i32 %DOTV = #x00000020 (32)
i32 %R_V = #x00000020 (32)
i32 %R = poison
Source value: #x00000000 (0)
Target value: poison
Summary:
0 correct transformations
1 incorrect transformations
0 errors
```
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D71568/new/
https://reviews.llvm.org/D71568
More information about the llvm-commits
mailing list