[PATCH] D71568: [InstCombine] `select + mul` -> `select + shl` with power of twos.
Danila Kutenin via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 17 17:09:23 PST 2019
danlark added inline comments.
================
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) {
----------------
lebedev.ri wrote:
> I think it would be better to change Op1 type to `Constant`, and make the caller do the cast.
It would be harder to combine OperandFoldActions then in udiv and mul at the same time, though I changed to only one call
================
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();
+ }
----------------
lebedev.ri wrote:
> If i'm reading this correctly, these are miscompilations:
> https://rise4fun.com/Alive/IKH
Yeah, thank you for the tool. if Shl NSW, this should not happen and this is correct I believe https://rise4fun.com/Alive/sog
================
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]]
----------------
lebedev.ri wrote:
> 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
>
> ```
Same issue with nsw for shift, fixed
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