}
};
+struct is_irem_op {
+ bool isOpType(unsigned Opcode) {
+ return Opcode == Instruction::SRem || Opcode == Instruction::URem;
+ }
+};
+
/// Matches shift operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_shift_op> m_Shift(const LHS &L,
return BinOpPred_match<LHS, RHS, is_idiv_op>(L, R);
}
+/// Matches integer remainder operations.
+template <typename LHS, typename RHS>
+inline BinOpPred_match<LHS, RHS, is_irem_op> m_IRem(const LHS &L,
+ const RHS &R) {
+ return BinOpPred_match<LHS, RHS, is_irem_op>(L, R);
+}
+
//===----------------------------------------------------------------------===//
// Class that matches exact binary ops.
//
return ExtractValueInst::Create(Call, 1, "sadd.overflow");
}
+/// If we have:
+/// icmp eq/ne (urem/srem %x, %y), 0
+/// iff %y is a power-of-two, we can replace this with a bit test:
+/// icmp eq/ne (and %x, (add %y, -1)), 0
+Instruction *InstCombiner::foldIRemByPowerOfTwoToBitTest(ICmpInst &I) {
+ // This fold is only valid for equality predicates.
+ if (!I.isEquality())
+ return nullptr;
+ ICmpInst::Predicate Pred;
+ Value *X, *Y, *Zero;
+ if (!match(&I, m_ICmp(Pred, m_OneUse(m_IRem(m_Value(X), m_Value(Y))),
+ m_CombineAnd(m_Zero(), m_Value(Zero)))))
+ return nullptr;
+ if (!isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, 0, &I))
+ return nullptr;
+ // This may increase instruction count, we don't enforce that Y is a constant.
+ Value *Mask = Builder.CreateAdd(Y, Constant::getAllOnesValue(Y->getType()));
+ Value *Masked = Builder.CreateAnd(X, Mask);
+ return ICmpInst::Create(Instruction::ICmp, Pred, Masked, Zero);
+}
+
// Handle icmp pred X, 0
Instruction *InstCombiner::foldICmpWithZero(ICmpInst &Cmp) {
CmpInst::Predicate Pred = Cmp.getPredicate();
}
}
+ if (Instruction *New = foldIRemByPowerOfTwoToBitTest(Cmp))
+ return New;
+
// Given:
// icmp eq/ne (urem %x, %y), 0
// Iff %x has 0 or 1 bits set, and %y has at least 2 bits set, omit 'urem':
define i1 @test3a(i32 %A) {
; CHECK-LABEL: @test3a(
-; CHECK-NEXT: [[B1:%.*]] = and i32 [[A:%.*]], 7
-; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B1]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 7
+; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[C]]
;
%B = srem i32 %A, -8
define <2 x i1> @test3a_vec(<2 x i32> %A) {
; CHECK-LABEL: @test3a_vec(
-; CHECK-NEXT: [[B1:%.*]] = and <2 x i32> [[A:%.*]], <i32 7, i32 7>
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[B1]], zeroinitializer
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], <i32 7, i32 7>
+; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%B = srem <2 x i32> %A, <i32 -8, i32 -8>
define i1 @test25(i32 %A) {
; CHECK-LABEL: @test25(
-; CHECK-NEXT: [[B:%.*]] = srem i32 [[A:%.*]], -2147483648
-; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[B]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 2147483647
+; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[C]]
;
%B = srem i32 %A, 2147483648 ; signbit
define <2 x i1> @test25_vec(<2 x i32> %A) {
; CHECK-LABEL: @test25_vec(
-; CHECK-NEXT: [[B:%.*]] = srem <2 x i32> [[A:%.*]], <i32 -2147483648, i32 -2147483648>
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[B]], zeroinitializer
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], <i32 2147483647, i32 2147483647>
+; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%B = srem <2 x i32> %A, <i32 2147483648, i32 2147483648>
define i1 @test26(i32 %A, i32 %B) {
; CHECK-LABEL: @test26(
-; CHECK-NEXT: [[C:%.*]] = shl nuw i32 1, [[B:%.*]]
-; CHECK-NEXT: [[D:%.*]] = srem i32 [[A:%.*]], [[C]]
-; CHECK-NEXT: [[E:%.*]] = icmp ne i32 [[D]], 0
+; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[B:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[A:%.*]]
+; CHECK-NEXT: [[E:%.*]] = icmp ne i32 [[TMP2]], 0
; CHECK-NEXT: ret i1 [[E]]
;
%C = shl i32 1, %B ; not a constant
define i1 @test28(i32 %A) {
; CHECK-LABEL: @test28(
-; CHECK-NEXT: [[B:%.*]] = srem i32 [[A:%.*]], -2147483648
-; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[B]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 2147483647
+; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[C]]
;
%B = srem i32 %A, 2147483648 ; signbit