From: Sanjay Patel Date: Fri, 3 Jul 2020 19:34:55 +0000 (-0400) Subject: [InstCombine] fold mul of sext bools to 'and' X-Git-Tag: llvmorg-12-init~1065 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7fd8af1de052e5bb0e07adba1d2c9e58d1a8f6a4;p=platform%2Fupstream%2Fllvm.git [InstCombine] fold mul of sext bools to 'and' Alive2: define i32 @src(i1 %x, i1 %y) { %0: %zx = sext i1 %x to i32 %zy = sext i1 %y to i32 %r = mul i32 %zx, %zy ret i32 %r } => define i32 @tgt(i1 %x, i1 %y) { %0: %a = and i1 %x, %y %r = zext i1 %a to i32 ret i32 %r } Transformation seems to be correct! https://alive2.llvm.org/ce/z/gaPQxA --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 39b6c67..2965103 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -367,8 +367,11 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { } // (zext bool X) * (zext bool Y) --> zext (and X, Y) - if (match(Op0, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1) && - match(Op1, m_ZExt(m_Value(Y))) && Y->getType()->isIntOrIntVectorTy(1) && + // (sext bool X) * (sext bool Y) --> zext (and X, Y) + // Note: -1 * -1 == 1 * 1 == 1 (if the extends match, the result is the same) + if (((match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) || + (match(Op0, m_SExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) && + X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() && (Op0->hasOneUse() || Op1->hasOneUse())) { Value *And = Builder.CreateAnd(X, Y, "mulbool"); return CastInst::Create(Instruction::ZExt, And, I.getType()); diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll index b23dff3..9d1b8ad 100644 --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -188,9 +188,8 @@ define i32 @mul_bools_use3(i1 %x, i1 %y) { define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @mul_bools_sext( -; CHECK-NEXT: [[SX:%.*]] = sext <3 x i1> [[X:%.*]] to <3 x i32> -; CHECK-NEXT: [[SY:%.*]] = sext <3 x i1> [[Y:%.*]] to <3 x i32> -; CHECK-NEXT: [[R:%.*]] = mul nsw <3 x i32> [[SX]], [[SY]] +; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = zext <3 x i1> [[MULBOOL]] to <3 x i32> ; CHECK-NEXT: ret <3 x i32> [[R]] ; %sx = sext <3 x i1> %x to <3 x i32> @@ -201,10 +200,10 @@ define <3 x i32> @mul_bools_sext(<3 x i1> %x, <3 x i1> %y) { define i32 @mul_bools_sext_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_use1( -; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32 ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SX]], [[SY]] +; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -216,10 +215,10 @@ define i32 @mul_bools_sext_use1(i1 %x, i1 %y) { define i32 @mul_bools_sext_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_sext_use2( -; CHECK-NEXT: [[SX:%.*]] = sext i1 [[X:%.*]] to i32 ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[R:%.*]] = mul nsw i32 [[SY]], [[SX]] +; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = zext i1 [[MULBOOL]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32