[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 @@
}
// (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());