Mask = APInt::getSignMask(C->getBitWidth());
Pred = ICmpInst::ICMP_NE;
break;
+ case ICmpInst::ICMP_SLE:
+ // X <= -1 is equivalent to (X & SignMask) != 0.
+ if (!C->isAllOnesValue())
+ return false;
+ Mask = APInt::getSignMask(C->getBitWidth());
+ Pred = ICmpInst::ICMP_NE;
+ break;
case ICmpInst::ICMP_SGT:
// X > -1 is equivalent to (X & SignMask) == 0.
if (!C->isAllOnesValue())
Mask = APInt::getSignMask(C->getBitWidth());
Pred = ICmpInst::ICMP_EQ;
break;
+ case ICmpInst::ICMP_SGE:
+ // X >= 0 is equivalent to (X & SignMask) == 0.
+ if (!C->isNullValue())
+ return false;
+ Mask = APInt::getSignMask(C->getBitWidth());
+ Pred = ICmpInst::ICMP_EQ;
+ break;
case ICmpInst::ICMP_ULT:
// X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
if (!C->isPowerOf2())
Mask = -*C;
Pred = ICmpInst::ICMP_EQ;
break;
+ case ICmpInst::ICMP_ULE:
+ // X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0.
+ if (!(*C + 1).isPowerOf2())
+ return false;
+ Mask = ~*C;
+ Pred = ICmpInst::ICMP_EQ;
+ break;
case ICmpInst::ICMP_UGT:
// X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
if (!(*C + 1).isPowerOf2())
Mask = ~*C;
Pred = ICmpInst::ICMP_NE;
break;
+ case ICmpInst::ICMP_UGE:
+ // X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0.
+ if (!C->isPowerOf2())
+ return false;
+ Mask = -*C;
+ Pred = ICmpInst::ICMP_NE;
+ break;
}
X = LHS;
}
; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
define i32 @test4noncanon(i32 %X) {
; CHECK-LABEL: @test4noncanon(
-; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X:%.*]], -1
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], -2147483648
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
+; CHECK-NEXT: ret i32 [[OR]]
;
%cmp = icmp sle i32 %X, -1
%or = or i32 %X, -2147483648
}
; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
define i32 @test9noncanon(i32 %X) {
; CHECK-LABEL: @test9noncanon(
-; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], -2147483648
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[X]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
+; CHECK-NEXT: ret i32 [[OR]]
;
%cmp = icmp sge i32 %X, 0
%or = or i32 %X, -2147483648
}
; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
define i32 @test12noncanon(i32 %X) {
; CHECK-LABEL: @test12noncanon(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[X:%.*]], 3
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 3
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[AND]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT: ret i32 [[AND]]
;
%cmp = icmp ule i32 %X, 3
%and = and i32 %X, 3
}
; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
define i32 @test13noncanon(i32 %X) {
; CHECK-LABEL: @test13noncanon(
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X:%.*]], 4
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 3
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[X]]
-; CHECK-NEXT: ret i32 [[COND]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT: ret i32 [[AND]]
;
%cmp = icmp uge i32 %X, 4
%and = and i32 %X, 3