| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | |
| ; RUN: opt < %s -passes=instsimplify,verify -S | FileCheck %s | |
| define i1 @ule_null_constexpr(ptr %x) { | |
| ; CHECK-LABEL: @ule_null_constexpr( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %cmp = icmp ule ptr null, @ule_null_constexpr | |
| ret i1 %cmp | |
| } | |
| define i1 @ugt_null_constexpr(ptr %x) { | |
| ; CHECK-LABEL: @ugt_null_constexpr( | |
| ; CHECK-NEXT: ret i1 false | |
| ; | |
| %cmp = icmp ugt ptr null, @ugt_null_constexpr | |
| ret i1 %cmp | |
| } | |
| define i1 @uge_constexpr_null(ptr %x) { | |
| ; CHECK-LABEL: @uge_constexpr_null( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %cmp = icmp uge ptr @ugt_null_constexpr, null | |
| ret i1 %cmp | |
| } | |
| define i1 @ult_constexpr_null(ptr %x) { | |
| ; CHECK-LABEL: @ult_constexpr_null( | |
| ; CHECK-NEXT: ret i1 false | |
| ; | |
| %cmp = icmp ult ptr @ugt_null_constexpr, null | |
| ret i1 %cmp | |
| } | |
| ; Negative test - we don't know if the constexpr is null. | |
| define i1 @ule_constexpr_null(ptr %x) { | |
| ; CHECK-LABEL: @ule_constexpr_null( | |
| ; CHECK-NEXT: ret i1 false | |
| ; | |
| %cmp = icmp ule ptr @ugt_null_constexpr, null | |
| ret i1 %cmp | |
| } | |
| ; Negative test - we don't know if the constexpr is *signed* less-than null. | |
| define i1 @slt_constexpr_null(ptr %x) { | |
| ; CHECK-LABEL: @slt_constexpr_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt ptr @ugt_null_constexpr, null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %cmp = icmp slt ptr @ugt_null_constexpr, null | |
| ret i1 %cmp | |
| } | |
| ; Negative test - we don't try to evaluate this comparison of constant expressions. | |
| define i1 @ult_constexpr_constexpr_one(ptr %x) { | |
| ; CHECK-LABEL: @ult_constexpr_constexpr_one( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr @ugt_null_constexpr, inttoptr (i32 1 to ptr) | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %cmp = icmp ult ptr @ugt_null_constexpr, inttoptr (i32 1 to ptr) | |
| ret i1 %cmp | |
| } | |
| @g = global [2 x i32] [i32 1, i32 2] | |
| @g2 = global i32 0 | |
| @g2_weak = extern_weak global i32 | |
| @g3 = global i8 0 | |
| define i1 @global_ne_null() { | |
| ; CHECK-LABEL: @global_ne_null( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %cmp = icmp ne ptr @g, null | |
| ret i1 %cmp | |
| } | |
| define i1 @global_ugt_null() { | |
| ; CHECK-LABEL: @global_ugt_null( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %cmp = icmp ugt ptr @g, null | |
| ret i1 %cmp | |
| } | |
| define i1 @global_sgt_null() { | |
| ; CHECK-LABEL: @global_sgt_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr @g, null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %cmp = icmp sgt ptr @g, null | |
| ret i1 %cmp | |
| } | |
| ; Should not fold to true, as the gep computes a null value. | |
| define i1 @global_out_of_bounds_gep_ne_null() { | |
| ; CHECK-LABEL: @global_out_of_bounds_gep_ne_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %cmp = icmp ne ptr getelementptr (i8, ptr @g3, i64 sub (i64 0, i64 ptrtoint (ptr @g3 to i64))), null | |
| ret i1 %cmp | |
| } | |
| define i1 @global_inbounds_gep_ne_null() { | |
| ; CHECK-LABEL: @global_inbounds_gep_ne_null( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 | |
| %cmp = icmp ne ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_ugt_null() { | |
| ; CHECK-LABEL: @global_gep_ugt_null( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 | |
| %cmp = icmp ugt ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_sgt_null() { | |
| ; CHECK-LABEL: @global_gep_sgt_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds nuw (i8, ptr @g, i64 8), null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 | |
| %cmp = icmp sgt ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| ; @g2_weak may be null, in which case this is a zero-index GEP and the pointers | |
| ; are equal. | |
| define i1 @null_gep_ne_null() { | |
| ; CHECK-LABEL: @null_gep_ne_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) | |
| %cmp = icmp ne ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_ugt_null() { | |
| ; CHECK-LABEL: @null_gep_ugt_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) | |
| %cmp = icmp ugt ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_sgt_null() { | |
| ; CHECK-LABEL: @null_gep_sgt_null( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64)), null | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g2_weak to i64) | |
| %cmp = icmp sgt ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_ne_null_constant_int() { | |
| ; CHECK-LABEL: @null_gep_ne_null_constant_int( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 1 | |
| %cmp = icmp ne ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_ugt_null_constant_int() { | |
| ; CHECK-LABEL: @null_gep_ugt_null_constant_int( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 1 | |
| %cmp = icmp ugt ptr %gep, null | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_ne_global() { | |
| ; CHECK-LABEL: @null_gep_ne_global( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), @g3 | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g3 to i64) | |
| %cmp = icmp ne ptr %gep, @g3 | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_ult_global() { | |
| ; CHECK-LABEL: @null_gep_ult_global( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr getelementptr (i8, ptr null, i64 ptrtoint (ptr @g3 to i64)), @g3 | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr i8, ptr null, i64 ptrtoint (ptr @g3 to i64) | |
| %cmp = icmp ult ptr %gep, @g3 | |
| ret i1 %cmp | |
| } | |
| define i1 @null_gep_slt_global() { | |
| ; CHECK-LABEL: @null_gep_slt_global( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp slt ptr getelementptr ([2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64)), @g | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr [2 x i32], ptr null, i64 ptrtoint (ptr @g2 to i64) | |
| %cmp = icmp slt ptr %gep, @g | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_ne_global() { | |
| ; CHECK-LABEL: @global_gep_ne_global( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 | |
| %cmp = icmp ne ptr %gep, @g | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_ugt_global() { | |
| ; CHECK-LABEL: @global_gep_ugt_global( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 | |
| %cmp = icmp ugt ptr %gep, @g | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_sgt_global() { | |
| ; CHECK-LABEL: @global_gep_sgt_global( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds nuw (i8, ptr @g, i64 8), @g | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 | |
| %cmp = icmp sgt ptr %gep, @g | |
| ret i1 %cmp | |
| } | |
| ; This should not fold to true, as the offset is negative. | |
| define i1 @global_gep_ugt_global_neg_offset() { | |
| ; CHECK-LABEL: @global_gep_ugt_global_neg_offset( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr getelementptr (i8, ptr @g, i64 -8), @g | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr [2 x i32], ptr @g, i64 -1 | |
| %cmp = icmp ugt ptr %gep, @g | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_sgt_global_neg_offset() { | |
| ; CHECK-LABEL: @global_gep_sgt_global_neg_offset( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr (i8, ptr @g, i64 -8), @g | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep = getelementptr [2 x i32], ptr @g, i64 -1 | |
| %cmp = icmp sgt ptr %gep, @g | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_ugt_global_gep() { | |
| ; CHECK-LABEL: @global_gep_ugt_global_gep( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep2 = getelementptr inbounds [2 x i32], ptr @g, i64 0, i64 1 | |
| %cmp = icmp ugt ptr %gep2, @g | |
| ret i1 %cmp | |
| } | |
| ; Should not fold due to signed comparison. | |
| define i1 @global_gep_sgt_global_gep() { | |
| ; CHECK-LABEL: @global_gep_sgt_global_gep( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt ptr getelementptr inbounds nuw (i8, ptr @g, i64 4), @g | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %gep2 = getelementptr inbounds [2 x i32], ptr @g, i64 0, i64 1 | |
| %cmp = icmp sgt ptr %gep2, @g | |
| ret i1 %cmp | |
| } | |
| define i1 @global_gep_ugt_global_gep_complex() { | |
| ; CHECK-LABEL: @global_gep_ugt_global_gep_complex( | |
| ; CHECK-NEXT: ret i1 true | |
| ; | |
| %gep3 = getelementptr inbounds i8, ptr @g, i64 2 | |
| %cmp = icmp ugt ptr %gep3, @g | |
| ret i1 %cmp | |
| } | |
| declare void @func() | |
| define i1 @global_no_cfi() { | |
| ; CHECK-LABEL: @global_no_cfi( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr @func, no_cfi @func | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %cmp = icmp eq ptr @func, no_cfi @func | |
| ret i1 %cmp | |
| } | |
| define i1 @blockaddr_no_cfi() { | |
| ; CHECK-LABEL: @blockaddr_no_cfi( | |
| ; CHECK-NEXT: br label [[BB:%.*]] | |
| ; CHECK: bb: | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr blockaddress(@blockaddr_no_cfi, [[BB]]), no_cfi @func | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| br label %bb | |
| bb: | |
| %cmp = icmp eq ptr blockaddress(@blockaddr_no_cfi, %bb), no_cfi @func | |
| ret i1 %cmp | |
| } | |
| define i1 @global_no_cfi_dso_local_equivalent() { | |
| ; CHECK-LABEL: @global_no_cfi_dso_local_equivalent( | |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr dso_local_equivalent @func, no_cfi @func | |
| ; CHECK-NEXT: ret i1 [[CMP]] | |
| ; | |
| %cmp = icmp eq ptr dso_local_equivalent @func, no_cfi @func | |
| ret i1 %cmp | |
| } |