Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -305,6 +305,13 @@ if (I.getType()->isIntOrIntVectorTy(1)) return BinaryOperator::CreateAnd(Op0, Op1); + // X * Y --> X & Y, iff X, Y can be only 0 or 1 + { + if (match(Op0, m_And(m_Value(X), m_One())) && + match(Op1, m_And(m_Value(Y), m_One()))) + return BinaryOperator::CreateAnd(Op0, Op1); + } + // X*(1 << Y) --> X << Y // (1 << Y)*X --> X << Y { Index: llvm/test/Transforms/InstCombine/trunc.ll =================================================================== --- llvm/test/Transforms/InstCombine/trunc.ll +++ llvm/test/Transforms/InstCombine/trunc.ll @@ -1021,3 +1021,15 @@ %sub = add nsw i16 %cast, -1 ret i16 %sub } + +define i64 @PR55599(i64 %x, i64 %y) { +; CHECK-LABEL: @PR55599( +; 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 +}