if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I))
return BinaryOperator::CreateAnd(V, AndRHS);
+ // ((C1-zext(X)) & C2) -> zext((C1-X) & C2) if C2 fits in the bitwidth
+ // of X.
+ if (auto *ZI = dyn_cast<ZExtInst>(Op0RHS)) {
+ auto *X = ZI->getOperand(0);
+ ConstantInt *C1;
+ if (match(Op0LHS, m_ConstantInt(C1)) &&
+ AndRHSMask.isIntN(X->getType()->getScalarSizeInBits())) {
+ auto *TruncC1 = ConstantExpr::getTrunc(C1, X->getType());
+ auto *Sub = Builder->CreateSub(TruncC1, X);
+ auto *TruncC2 = ConstantExpr::getTrunc(AndRHS, X->getType());
+ auto *And = Builder->CreateAnd(Sub, TruncC2);
+ return new ZExtInst(And, I.getType());
+ }
+ }
+
// -x & 1 -> x & 1
if (AndRHSMask == 1 && match(Op0LHS, m_Zero()))
return BinaryOperator::CreateAnd(Op0RHS, AndRHS);
ret <2 x i32> %and
}
+define i64 @test35(i32 %X) {
+; CHECK-LABEL: @test35(
+; CHECK-NEXT: %[[sub:.*]] = sub i32 0, %X
+; CHECK-NEXT: %[[and:.*]] = and i32 %[[sub]], 240
+; CHECK-NEXT: %[[cst:.*]] = zext i32 %[[and]] to i64
+; CHECK-NEXT: ret i64 %[[cst]]
+ %zext = zext i32 %X to i64
+ %zsub = sub i64 0, %zext
+ %res = and i64 %zsub, 240
+ ret i64 %res
+}