diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -301,9 +301,15 @@ } } - // i1 mul -> i1 and. + // Fold the following two scenarios: + // 1) i1 mul -> i1 and. + // 2) X * Y --> X & Y, iff X, Y can be only {0,1}. + // Note: We could use known bits to generalize this and related patterns with + // shifts/truncs Type *Ty = I.getType(); - if (Ty->isIntOrIntVectorTy(1)) + if (Ty->isIntOrIntVectorTy(1) || + (match(Op0, m_And(m_Value(), m_One())) && + match(Op1, m_And(m_Value(), m_One())))) return BinaryOperator::CreateAnd(Op0, Op1); // X*(1 << Y) --> X << Y diff --git a/llvm/test/Transforms/InstCombine/mul-masked-bits.ll b/llvm/test/Transforms/InstCombine/mul-masked-bits.ll --- a/llvm/test/Transforms/InstCombine/mul-masked-bits.ll +++ b/llvm/test/Transforms/InstCombine/mul-masked-bits.ll @@ -169,13 +169,31 @@ ; Scalar tests define i64 @scalar_mul_bit_x0_y0(i64 %x, i64 %y) { ; CHECK-LABEL: @scalar_mul_bit_x0_y0( +; CHECK-NEXT: [[AND2:%.*]] = and i64 [[Y:%.*]], 1 +; CHECK-NEXT: [[MUL:%.*]] = and i64 [[AND2]], [[X:%.*]] +; CHECK-NEXT: ret i64 [[MUL]] +; + %and1 = and i64 %x, 1 + %and2 = and i64 %y, 1 + %mul = mul i64 %and1, %and2 + ret i64 %mul +} + +declare void @use(i64) + +define i64 @scalar_mul_bit_x0_y0_uses(i64 %x, i64 %y) { +; CHECK-LABEL: @scalar_mul_bit_x0_y0_uses( ; CHECK-NEXT: [[AND1:%.*]] = and i64 [[X:%.*]], 1 +; CHECK-NEXT: call void @use(i64 [[AND1]]) ; CHECK-NEXT: [[AND2:%.*]] = and i64 [[Y:%.*]], 1 -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[AND1]], [[AND2]] +; CHECK-NEXT: call void @use(i64 [[AND2]]) +; CHECK-NEXT: [[MUL:%.*]] = and i64 [[AND2]], [[X]] ; CHECK-NEXT: ret i64 [[MUL]] ; %and1 = and i64 %x, 1 + call void @use(i64 %and1) %and2 = and i64 %y, 1 + call void @use(i64 %and2) %mul = mul i64 %and1, %and2 ret i64 %mul } @@ -210,9 +228,8 @@ ; Vector tests define <2 x i64> @vector_mul_bit_x0_y0(<2 x i64> %x, <2 x i64> %y) { ; CHECK-LABEL: @vector_mul_bit_x0_y0( -; CHECK-NEXT: [[AND1:%.*]] = and <2 x i64> [[X:%.*]], ; CHECK-NEXT: [[AND2:%.*]] = and <2 x i64> [[Y:%.*]], -; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw <2 x i64> [[AND1]], [[AND2]] +; CHECK-NEXT: [[MUL:%.*]] = and <2 x i64> [[AND2]], [[X:%.*]] ; CHECK-NEXT: ret <2 x i64> [[MUL]] ; %and1 = and <2 x i64> %x,