}
// icmp eq/ne(GV,null) -> false/true
} else if (C2->isNullValue()) {
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C1))
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(C1)) {
// Don't try to evaluate aliases. External weak GV can be null.
if (!isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage() &&
!NullPointerIsDefined(nullptr /* F */,
else if (pred == ICmpInst::ICMP_NE)
return ConstantInt::getTrue(C1->getContext());
}
+ }
+
+ // The caller is expected to commute the operands if the constant expression
+ // is C2.
+ // C1 >= 0 --> true
+ if (pred == ICmpInst::ICMP_UGE)
+ return Constant::getAllOnesValue(ResultTy);
+ // C1 < 0 --> false
+ if (pred == ICmpInst::ICMP_ULT)
+ return Constant::getNullValue(ResultTy);
}
// If the comparison is a comparison between two i1's, simplify it.
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: li r3, 0
-; CHECK-NEXT: isel r3, 0, r3, 4*cr5+lt
; CHECK-NEXT: blr
entry:
br label %next
define <vscale x 2 x i1> @test8() {
; CHECK-LABEL: @test8(
-; CHECK-NEXT: ret <vscale x 2 x i1> icmp ult (<vscale x 2 x i64> zext (<vscale x 2 x i32> shufflevector (<vscale x 2 x i32> insertelement (<vscale x 2 x i32> poison, i32 1, i32 0), <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer) to <vscale x 2 x i64>), <vscale x 2 x i64> zeroinitializer)
+; CHECK-NEXT: ret <vscale x 2 x i1> zeroinitializer
;
%ins = insertelement <vscale x 2 x i32> poison, i32 1, i32 0
%b = shufflevector <vscale x 2 x i32> %ins, <vscale x 2 x i32> poison, <vscale x 2 x i32> zeroinitializer
define <vscale x 2 x i1> @test8() {
; CHECK-LABEL: @test8(
-; CHECK-NEXT: ret <vscale x 2 x i1> icmp ult (<vscale x 2 x i64> zext (<vscale x 2 x i32> shufflevector (<vscale x 2 x i32> insertelement (<vscale x 2 x i32> undef, i32 1, i32 0), <vscale x 2 x i32> undef, <vscale x 2 x i32> zeroinitializer) to <vscale x 2 x i64>), <vscale x 2 x i64> zeroinitializer)
+; CHECK-NEXT: ret <vscale x 2 x i1> zeroinitializer
;
%ins = insertelement <vscale x 2 x i32> undef, i32 1, i32 0
%b = shufflevector <vscale x 2 x i32> %ins, <vscale x 2 x i32> undef, <vscale x 2 x i32> zeroinitializer
define i1 @ule_null_constexpr(i8* %x) {
; CHECK-LABEL: @ule_null_constexpr(
-; CHECK-NEXT: ret i1 icmp uge (i8 (...)* bitcast (i1 (i8*)* @ule_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT: ret i1 true
;
%cmp = icmp ule i8 (...)* null, bitcast (i1 (i8*)* @ule_null_constexpr to i8 (...)*)
ret i1 %cmp
define i1 @ugt_null_constexpr(i8* %x) {
; CHECK-LABEL: @ugt_null_constexpr(
-; CHECK-NEXT: ret i1 icmp ult (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT: ret i1 false
;
%cmp = icmp ugt i8 (...)* null, bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*)
ret i1 %cmp
define i1 @uge_constexpr_null(i8* %x) {
; CHECK-LABEL: @uge_constexpr_null(
-; CHECK-NEXT: ret i1 icmp uge (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT: ret i1 true
;
%cmp = icmp uge i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), null
ret i1 %cmp
define i1 @ult_constexpr_null(i8* %x) {
; CHECK-LABEL: @ult_constexpr_null(
-; CHECK-NEXT: ret i1 icmp ult (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
+; CHECK-NEXT: ret i1 false
;
%cmp = icmp ult i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), null
ret i1 %cmp
}
+; Negative test - we don't know if the constexpr is null.
+
define i1 @ule_constexpr_null(i8* %x) {
; CHECK-LABEL: @ule_constexpr_null(
; CHECK-NEXT: ret i1 icmp ule (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
ret i1 %cmp
}
+; Negative test - we don't know if the constexpr is *signed* less-than null.
+
define i1 @slt_constexpr_null(i8* %x) {
; CHECK-LABEL: @slt_constexpr_null(
; CHECK-NEXT: ret i1 icmp slt (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* null)
ret i1 %cmp
}
+; Negative test - we don't try to evaluate this comparison of constant expressions.
+
define i1 @ult_constexpr_constexpr_one(i8* %x) {
; CHECK-LABEL: @ult_constexpr_constexpr_one(
; CHECK-NEXT: ret i1 icmp ult (i8 (...)* bitcast (i1 (i8*)* @ugt_null_constexpr to i8 (...)*), i8 (...)* inttoptr (i32 1 to i8 (...)*))
ret void
}
-; TODO: This is a special-case of the above pattern:
+; This is a special-case of the above pattern:
; Null is guaranteed to be unsigned <= all values.
define void @icmp_ule_null_constexpr(i8* %arg1, i8* %arg2) {
; CHECK-LABEL: @icmp_ule_null_constexpr(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8* [[ARG1:%.*]], null
-; CHECK-NEXT: br i1 [[CMP1]], label [[BB_BAR1:%.*]], label [[BB_END:%.*]]
-; CHECK: bb_bar1:
-; CHECK-NEXT: call void @bar(i32 1)
-; CHECK-NEXT: br label [[BB_END]]
+; CHECK-NEXT: br i1 [[CMP1]], label [[BB_END_THREAD:%.*]], label [[BB_END:%.*]]
; CHECK: bb_end:
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8* [[ARG2:%.*]], null
; CHECK-NEXT: br i1 [[CMP2]], label [[BB_CONT:%.*]], label [[BB_BAR2:%.*]]
+; CHECK: bb_end.thread:
+; CHECK-NEXT: call void @bar(i32 1)
+; CHECK-NEXT: [[CMP21:%.*]] = icmp ne i8* [[ARG2]], null
+; CHECK-NEXT: br i1 [[CMP21]], label [[BB_EXIT:%.*]], label [[BB_BAR2]]
; CHECK: bb_bar2:
; CHECK-NEXT: call void @bar(i32 2)
-; CHECK-NEXT: br label [[BB_EXIT:%.*]]
+; CHECK-NEXT: br label [[BB_EXIT]]
; CHECK: bb_cont:
; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i8* [[ARG1]], inttoptr (i64 4 to i8*)
; CHECK-NEXT: br i1 [[CMP3]], label [[BB_EXIT]], label [[BB_BAR3:%.*]]