}
break;
}
- case ICmpInst::ICMP_ULT:
+ case ICmpInst::ICMP_ULT: {
if (Op0Max.ult(Op1Min)) // A <u B -> true if max(A) < min(B)
return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType()));
if (Op0Min.uge(Op1Max)) // A <u B -> false if min(A) >= max(B)
return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
if (Op1Min == Op0Max) // A <u B -> A != B if max(A) == min(B)
return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
- if (Op1Max == Op0Min+1) // A <u C -> A == C-1 if min(A)+1 == C
- return new ICmpInst(ICmpInst::ICMP_EQ, Op0,
- Builder->getInt(CI->getValue()-1));
+ const APInt *CmpC;
+ if (match(Op1, m_APInt(CmpC))) {
+ // A <u C -> A == C-1 if min(A)+1 == C
+ if (Op1Max == Op0Min + 1) {
+ Constant *CMinus1 = ConstantInt::get(Op0->getType(), *CmpC - 1);
+ return new ICmpInst(ICmpInst::ICMP_EQ, Op0, CMinus1);
+ }
// (x <u 2147483648) -> (x >s -1) -> true if sign bit clear
- if (CI->isMinValue(true))
- return new ICmpInst(ICmpInst::ICMP_SGT, Op0,
- Constant::getAllOnesValue(Op0->getType()));
+ if (CmpC->isMinSignedValue()) {
+ Constant *AllOnes = Constant::getAllOnesValue(Op0->getType());
+ return new ICmpInst(ICmpInst::ICMP_SGT, Op0, AllOnes);
+ }
}
break;
+ }
case ICmpInst::ICMP_UGT: {
if (Op0Min.ugt(Op1Max)) // A >u B -> true if min(A) > max(B)
return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType()));
ret i1 %B
}
-; FIXME: missing vector fold for ult 1 -> eq 0
define <2 x i1> @udiv_icmp2_vec(<2 x i64> %X) {
; CHECK-LABEL: @udiv_icmp2_vec(
-; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i64> %X, <i64 1, i64 1>
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> %X, zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[TMP1]]
;
%A = udiv exact <2 x i64> %X, <i64 5, i64 5>
ret i1 %B
}
-; FIXME: missing vector fold for ult 1 -> eq 0
define <2 x i1> @sdiv_icmp1_vec(<2 x i64> %X) {
; CHECK-LABEL: @sdiv_icmp1_vec(
-; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i64> %X, <i64 1, i64 1>
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> %X, zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[TMP1]]
;
%A = sdiv exact <2 x i64> %X, <i64 5, i64 5>
ret i1 %B
}
-; FIXME: missing vector fold for ult 1 -> eq 0
define <2 x i1> @sdiv_icmp4_vec(<2 x i64> %X) {
; CHECK-LABEL: @sdiv_icmp4_vec(
-; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i64> %X, <i64 1, i64 1>
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> %X, zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[TMP1]]
;
%A = sdiv exact <2 x i64> %X, <i64 -5, i64 -5>
ret <2 x i1> %cmp
}
+define <2 x i1> @ult_min_signed_value(<2 x i8> %x) {
+; CHECK-LABEL: @ult_min_signed_value(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> %x, <i8 -1, i8 -1>
+; CHECK-NEXT: ret <2 x i1> [[CMP]]
+;
+ %cmp = icmp ult <2 x i8> %x, <i8 128, i8 128>
+ ret <2 x i1> %cmp
+}
+
; Zeros are special: they're ConstantAggregateZero.
define <2 x i1> @sge_zero(<2 x i8> %x) {
define <2 x i1> @ule_zero(<2 x i8> %x) {
; CHECK-LABEL: @ule_zero(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> %x, <i8 1, i8 1>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> %x, zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%cmp = icmp ule <2 x i8> %x, <i8 0, i8 0>
ret i1 %cmp
}
-; FIXME: Vectors should fold the same way.
define <2 x i1> @icmp_mul_neq0_vec(<2 x i32> %x) {
; CHECK-LABEL: @icmp_mul_neq0_vec(
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> %x, zeroinitializer
ret i1 %cmp
}
-; FIXME: icmp ult X, 1 -> icmp eq X, 0
define <2 x i1> @test_shift_and_cmp_changed2_vec(<2 x i8> %p) {
; CHECK-LABEL: @test_shift_and_cmp_changed2_vec(
; CHECK-NEXT: [[ANDP:%.*]] = and <2 x i8> %p, <i8 6, i8 6>
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[ANDP]], <i8 1, i8 1>
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[ANDP]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%shlp = shl <2 x i8> %p, <i8 5, i8 5>