This is basically the same change as #162653, but for InstSimplify instead of ConstantFolding. It folds `icmp (ptrtoaddr x, ptrtoaddr y)` to `icmp (x, y)` and `icmp (ptrtoaddr x, C)` to `icmp (x, inttoptr C)`. The fold is restricted to the case where the result type is the address type, as icmp only compares the icmp bits. As in the other PR, I think in practice all the folds are also going to work if the ptrtoint result type is larger than the address size, but it's unclear how to justify this in general.
473 lines
16 KiB
LLVM
473 lines
16 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
|
|
|
|
; The ptrtoaddr folds are also valid for pointers that have external state.
|
|
target datalayout = "pe1:64:64:64:32"
|
|
|
|
@g = external global i8
|
|
@g2 = external global i8
|
|
|
|
@g.as1 = external addrspace(1) global i8
|
|
@g2.as1 = external addrspace(1) global i8
|
|
|
|
define i64 @ptrtoaddr_inttoptr_arg(i64 %a) {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_inttoptr_arg(
|
|
; CHECK-SAME: i64 [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i64 [[A]]
|
|
;
|
|
%toptr = inttoptr i64 %a to ptr
|
|
%toaddr = ptrtoaddr ptr %toptr to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_inttoptr_arg_addrsize(i32 %a) {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_arg_addrsize(
|
|
; CHECK-SAME: i32 [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i32 [[A]]
|
|
;
|
|
%toptr = inttoptr i32 %a to ptr addrspace(1)
|
|
%toaddr = ptrtoaddr ptr addrspace(1) %toptr to i32
|
|
ret i32 %toaddr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_inttoptr() {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr() {
|
|
; CHECK-NEXT: ret i32 -1
|
|
;
|
|
%toptr = inttoptr i32 -1 to ptr addrspace(1)
|
|
%toaddr = ptrtoaddr ptr addrspace(1) %toptr to i32
|
|
ret i32 %toaddr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_inttoptr_diff_size1() {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_diff_size1() {
|
|
; CHECK-NEXT: ret i32 -1
|
|
;
|
|
%toptr = inttoptr i64 -1 to ptr addrspace(1)
|
|
%toaddr = ptrtoaddr ptr addrspace(1) %toptr to i32
|
|
ret i32 %toaddr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_inttoptr_diff_size2() {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_inttoptr_diff_size2() {
|
|
; CHECK-NEXT: ret i32 65535
|
|
;
|
|
%toptr = inttoptr i16 -1 to ptr addrspace(1)
|
|
%toaddr = ptrtoaddr ptr addrspace(1) %toptr to i32
|
|
ret i32 %toaddr
|
|
}
|
|
|
|
define i64 @ptrtoaddr_inttoptr_noas1() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_inttoptr_noas1() {
|
|
; CHECK-NEXT: ret i64 1
|
|
;
|
|
%toptr = getelementptr i8, ptr null, i64 1
|
|
%toaddr = ptrtoaddr ptr %toptr to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i64 @ptr2addr2_inttoptr_noas2() {
|
|
; CHECK-LABEL: define i64 @ptr2addr2_inttoptr_noas2() {
|
|
; CHECK-NEXT: ret i64 123
|
|
;
|
|
%toptr = inttoptr i64 123 to ptr
|
|
%toaddr = ptrtoaddr ptr %toptr to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i64 @ptrtoaddr_inttoptr_noas_diff_size1() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_inttoptr_noas_diff_size1() {
|
|
; CHECK-NEXT: ret i64 4294967295
|
|
;
|
|
%toptr = inttoptr i32 -1 to ptr
|
|
%toaddr = ptrtoaddr ptr %toptr to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i64 @ptrtoaddr_inttoptr_noas_diff_size2() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_inttoptr_noas_diff_size2() {
|
|
; CHECK-NEXT: ret i64 -1
|
|
;
|
|
%toptr = inttoptr i128 -1 to ptr
|
|
%toaddr = ptrtoaddr ptr %toptr to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i64 @ptrtoaddr_gep_null() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_gep_null() {
|
|
; CHECK-NEXT: ret i64 42
|
|
;
|
|
%toaddr = ptrtoaddr ptr getelementptr (i8, ptr null, i64 42) to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_gep_null_addrsize() {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_gep_null_addrsize() {
|
|
; CHECK-NEXT: ret i32 42
|
|
;
|
|
%toaddr = ptrtoaddr ptr addrspace(1) getelementptr (i8, ptr addrspace(1) null, i32 42) to i32
|
|
ret i32 %toaddr
|
|
}
|
|
|
|
define i64 @ptrtoaddr_gep_sub() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_gep_sub() {
|
|
; CHECK-NEXT: ret i64 sub (i64 ptrtoaddr (ptr @g to i64), i64 ptrtoaddr (ptr @g2 to i64))
|
|
;
|
|
%toaddr = ptrtoaddr ptr getelementptr (i8, ptr @g, i64 sub (i64 0, i64 ptrtoaddr (ptr @g2 to i64))) to i64
|
|
ret i64 %toaddr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_gep_sub_addrsize() {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_gep_sub_addrsize() {
|
|
; CHECK-NEXT: ret i32 sub (i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), i32 ptrtoaddr (ptr addrspace(1) @g2.as1 to i32))
|
|
;
|
|
%toaddr = ptrtoaddr ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @g.as1, i32 sub (i32 0, i32 ptrtoaddr (ptr addrspace(1) @g2.as1 to i32))) to i32
|
|
ret i32 %toaddr
|
|
}
|
|
|
|
; Don't fold inttoptr of ptrtoaddr away. inttoptr will pick a previously
|
|
; exposed provenance, which is not necessarily that of @g (especially as
|
|
; ptrtoaddr does not expose the provenance.)
|
|
define ptr @inttoptr_of_ptrtoaddr() {
|
|
; CHECK-LABEL: define ptr @inttoptr_of_ptrtoaddr() {
|
|
; CHECK-NEXT: ret ptr inttoptr (i64 ptrtoaddr (ptr @g to i64) to ptr)
|
|
;
|
|
%toptr = inttoptr i64 ptrtoaddr (ptr @g to i64) to ptr
|
|
ret ptr %toptr
|
|
}
|
|
|
|
define i64 @ptrtoaddr_sub_consts_unrelated() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_sub_consts_unrelated() {
|
|
; CHECK-NEXT: ret i64 sub (i64 ptrtoaddr (ptr @g to i64), i64 ptrtoaddr (ptr @g2 to i64))
|
|
;
|
|
%sub = sub i64 ptrtoaddr (ptr @g to i64), ptrtoaddr (ptr @g2 to i64)
|
|
ret i64 %sub
|
|
}
|
|
|
|
define i64 @ptrtoaddr_sub_consts_offset() {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_sub_consts_offset() {
|
|
; CHECK-NEXT: ret i64 42
|
|
;
|
|
%sub = sub i64 ptrtoaddr (ptr getelementptr (i8, ptr @g, i64 42) to i64), ptrtoaddr (ptr @g to i64)
|
|
ret i64 %sub
|
|
}
|
|
|
|
define i32 @ptrtoaddr_sub_consts_offset_addrsize() {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_sub_consts_offset_addrsize() {
|
|
; CHECK-NEXT: ret i32 42
|
|
;
|
|
%sub = sub i32 ptrtoaddr (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @g.as1, i32 42) to i32), ptrtoaddr (ptr addrspace(1) @g.as1 to i32)
|
|
ret i32 %sub
|
|
}
|
|
|
|
define i64 @ptrtoaddr_sub_known_offset(ptr %p) {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_sub_known_offset(
|
|
; CHECK-SAME: ptr [[P:%.*]]) {
|
|
; CHECK-NEXT: ret i64 42
|
|
;
|
|
%p2 = getelementptr inbounds i8, ptr %p, i64 42
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%p2.addr = ptrtoaddr ptr %p2 to i64
|
|
%sub = sub i64 %p2.addr, %p.addr
|
|
ret i64 %sub
|
|
}
|
|
|
|
define i32 @ptrtoaddr_sub_known_offset_addrsize(ptr addrspace(1) %p) {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_sub_known_offset_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret i32 42
|
|
;
|
|
%p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i32 42
|
|
%p.addr = ptrtoaddr ptr addrspace(1) %p to i32
|
|
%p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32
|
|
%sub = sub i32 %p2.addr, %p.addr
|
|
ret i32 %sub
|
|
}
|
|
|
|
define i64 @ptrtoaddr_of_ptradd_of_sub(i64 %x, ptr %p) {
|
|
; CHECK-LABEL: define i64 @ptrtoaddr_of_ptradd_of_sub(
|
|
; CHECK-SAME: i64 [[X:%.*]], ptr [[P:%.*]]) {
|
|
; CHECK-NEXT: ret i64 [[X]]
|
|
;
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%sub = sub i64 %x, %p.addr
|
|
%ptradd = getelementptr i8, ptr %p, i64 %sub
|
|
%ptradd.addr = ptrtoaddr ptr %ptradd to i64
|
|
ret i64 %ptradd.addr
|
|
}
|
|
|
|
define i32 @ptrtoaddr_of_ptradd_of_sub_addrsize(i32 %x, ptr addrspace(1) %p) {
|
|
; CHECK-LABEL: define i32 @ptrtoaddr_of_ptradd_of_sub_addrsize(
|
|
; CHECK-SAME: i32 [[X:%.*]], ptr addrspace(1) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret i32 [[X]]
|
|
;
|
|
%p.addr = ptrtoaddr ptr addrspace(1) %p to i32
|
|
%sub = sub i32 %x, %p.addr
|
|
%ptradd = getelementptr i8, ptr addrspace(1) %p, i32 %sub
|
|
%ptradd.addr = ptrtoaddr ptr addrspace(1) %ptradd to i32
|
|
ret i32 %ptradd.addr
|
|
}
|
|
|
|
define ptr @gep_of_sub_ptrtoaddr_unrelated_pointers(ptr %p, ptr %p2, i64 %x) {
|
|
; CHECK-LABEL: define ptr @gep_of_sub_ptrtoaddr_unrelated_pointers(
|
|
; CHECK-SAME: ptr [[P:%.*]], ptr [[P2:%.*]], i64 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[P2_ADDR:%.*]] = ptrtoaddr ptr [[P2]] to i64
|
|
; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i64
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[P2_ADDR]], [[P_ADDR]]
|
|
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[P]], i64 [[SUB]]
|
|
; CHECK-NEXT: ret ptr [[GEP2]]
|
|
;
|
|
%p2.addr = ptrtoaddr ptr %p2 to i64
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%sub = sub i64 %p2.addr, %p.addr
|
|
%gep2 = getelementptr i8, ptr %p, i64 %sub
|
|
ret ptr %gep2
|
|
}
|
|
|
|
define ptr @gep_of_sub_ptrtoaddr(ptr %p, i64 %x) {
|
|
; CHECK-LABEL: define ptr @gep_of_sub_ptrtoaddr(
|
|
; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]]
|
|
; CHECK-NEXT: ret ptr [[GEP1]]
|
|
;
|
|
%gep1 = getelementptr i8, ptr %p, i64 %x
|
|
%gep1.addr = ptrtoaddr ptr %gep1 to i64
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%sub = sub i64 %gep1.addr, %p.addr
|
|
%gep2 = getelementptr i8, ptr %p, i64 %sub
|
|
ret ptr %gep2
|
|
}
|
|
|
|
define ptr addrspace(1) @gep_of_sub_ptrtoaddr_addrsize(ptr addrspace(1) %p, i32 %x) {
|
|
; CHECK-LABEL: define ptr addrspace(1) @gep_of_sub_ptrtoaddr_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr addrspace(1) [[P]], i32 [[X]]
|
|
; CHECK-NEXT: ret ptr addrspace(1) [[GEP1]]
|
|
;
|
|
%gep1 = getelementptr i8, ptr addrspace(1) %p, i32 %x
|
|
%gep1.addr = ptrtoaddr ptr addrspace(1) %gep1 to i32
|
|
%p.addr = ptrtoaddr ptr addrspace(1) %p to i32
|
|
%sub = sub i32 %gep1.addr, %p.addr
|
|
%gep2 = getelementptr i8, ptr addrspace(1) %p, i32 %sub
|
|
ret ptr addrspace(1) %gep2
|
|
}
|
|
|
|
define ptr @gep_of_sub_ptrtoaddr_ashr(ptr %p, i64 %x) {
|
|
; CHECK-LABEL: define ptr @gep_of_sub_ptrtoaddr_ashr(
|
|
; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[P]], i64 [[X]]
|
|
; CHECK-NEXT: ret ptr [[GEP1]]
|
|
;
|
|
%gep1 = getelementptr i8, ptr %p, i64 %x
|
|
%gep1.addr = ptrtoaddr ptr %gep1 to i64
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%sub = sub i64 %gep1.addr, %p.addr
|
|
%ashr = ashr i64 %sub, 1
|
|
%gep2 = getelementptr i16, ptr %p, i64 %ashr
|
|
ret ptr %gep2
|
|
}
|
|
|
|
define ptr addrspace(1) @gep_of_sub_ptrtoaddr_ashr_addrsize(ptr addrspace(1) %p, i32 %x) {
|
|
; CHECK-LABEL: define ptr addrspace(1) @gep_of_sub_ptrtoaddr_ashr_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) [[P:%.*]], i32 [[X:%.*]]) {
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr addrspace(1) [[P]], i32 [[X]]
|
|
; CHECK-NEXT: ret ptr addrspace(1) [[GEP1]]
|
|
;
|
|
%gep1 = getelementptr i8, ptr addrspace(1) %p, i32 %x
|
|
%gep1.addr = ptrtoaddr ptr addrspace(1) %gep1 to i32
|
|
%p.addr = ptrtoaddr ptr addrspace(1) %p to i32
|
|
%sub = sub i32 %gep1.addr, %p.addr
|
|
%sdiv = sdiv i32 %sub, 3
|
|
%gep2 = getelementptr [3 x i8], ptr addrspace(1) %p, i32 %sdiv
|
|
ret ptr addrspace(1) %gep2
|
|
}
|
|
|
|
; Not folding this to inttoptr(123), as this may have different provenance from
|
|
; %p, and the use of ptrtoaddr implies that the provenance of %p may not be
|
|
; exposed, such that inttoptr cannot recover it.
|
|
define ptr @gep_gep_neg_ptrtoaddr(ptr %p) {
|
|
; CHECK-LABEL: define ptr @gep_gep_neg_ptrtoaddr(
|
|
; CHECK-SAME: ptr [[P:%.*]]) {
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 123
|
|
; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i64
|
|
; CHECK-NEXT: [[P_ADDR_NEG:%.*]] = sub i64 0, [[P_ADDR]]
|
|
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[GEP1]], i64 [[P_ADDR_NEG]]
|
|
; CHECK-NEXT: ret ptr [[GEP2]]
|
|
;
|
|
%gep1 = getelementptr inbounds i8, ptr %p, i64 123
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%p.addr.neg = sub i64 0, %p.addr
|
|
%gep2 = getelementptr i8, ptr %gep1, i64 %p.addr.neg
|
|
ret ptr %gep2
|
|
}
|
|
|
|
define ptr @gep_gep_inv_ptrtoaddr(ptr %p) {
|
|
; CHECK-LABEL: define ptr @gep_gep_inv_ptrtoaddr(
|
|
; CHECK-SAME: ptr [[P:%.*]]) {
|
|
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 123
|
|
; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoaddr ptr [[P]] to i64
|
|
; CHECK-NEXT: [[P_ADDR_INV:%.*]] = xor i64 [[P_ADDR]], -1
|
|
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[GEP1]], i64 [[P_ADDR_INV]]
|
|
; CHECK-NEXT: ret ptr [[GEP2]]
|
|
;
|
|
%gep1 = getelementptr inbounds i8, ptr %p, i64 123
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%p.addr.inv = xor i64 %p.addr, -1
|
|
%gep2 = getelementptr i8, ptr %gep1, i64 %p.addr.inv
|
|
ret ptr %gep2
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_0() {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_0() {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%cmp = icmp ne i64 ptrtoaddr (ptr @g to i64), 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; This fails to fold because we currently don't assume that globals are located
|
|
; at a non-null address for non-default address spaces.
|
|
define i1 @icmp_ptrtoaddr_0_addrsize() {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_0_addrsize() {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), 0
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%cmp = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoint_0_addrsize() {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoint_0_addrsize() {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), 0
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%cmp = icmp ne i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_ptrtoaddr() {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr() {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%cmp = icmp ne i64 ptrtoaddr (ptr @g to i64), ptrtoaddr (ptr @g2 to i64)
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_ptrtoaddr_addrsize() {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr_addrsize() {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%cmp = icmp ne i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), ptrtoaddr (ptr addrspace(1) @g2.as1 to i32)
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; This could still be folded because the address being non-equal also implies
|
|
; that all pointer bits together are non-equal.
|
|
define i1 @icmp_ptrtoint_ptrtoint_addrsize() {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoint_ptrtoint_addrsize() {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), ptrtoint (ptr addrspace(1) @g2.as1 to i64)
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%cmp = icmp ne i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), ptrtoint (ptr addrspace(1) @g2.as1 to i64)
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_relational_ptrtoaddr_ptrtoaddr() {
|
|
; CHECK-LABEL: define i1 @icmp_relational_ptrtoaddr_ptrtoaddr() {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%cmp = icmp ult i64 ptrtoaddr (ptr @g to i64), ptrtoaddr (ptr getelementptr inbounds (i8, ptr @g, i64 1) to i64)
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_relational_ptrtoaddr_ptrtoaddr_addrsize() {
|
|
; CHECK-LABEL: define i1 @icmp_relational_ptrtoaddr_ptrtoaddr_addrsize() {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%cmp = icmp ult i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32), ptrtoaddr (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @g.as1, i32 1) to i32)
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; This could still be folded because we know that the non-address bits must be
|
|
; the same, as GEP does not modify them.
|
|
define i1 @icmp_relational_ptrtoint_ptrtoint_addrsize() {
|
|
; CHECK-LABEL: define i1 @icmp_relational_ptrtoint_ptrtoint_addrsize() {
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @g.as1, i64 1) to i64)
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%cmp = icmp ult i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @g.as1, i64 1) to i64)
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn(ptr %a) {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn(
|
|
; CHECK-SAME: ptr [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%gep = getelementptr i8, ptr %a, i64 1
|
|
%a.addr = ptrtoaddr ptr %a to i64
|
|
%gep.addr = ptrtoaddr ptr %gep to i64
|
|
%cmp = icmp ne i64 %a.addr, %gep.addr
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn_addrsize(ptr addrspace(1) %a) {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%gep = getelementptr i8, ptr addrspace(1) %a, i32 1
|
|
%a.addr = ptrtoaddr ptr addrspace(1) %a to i32
|
|
%gep.addr = ptrtoaddr ptr addrspace(1) %gep to i32
|
|
%cmp = icmp ne i32 %a.addr, %gep.addr
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; This could still be folded, because the non-address bits being non-equal
|
|
; implies that all bits taken together are also non-equal.
|
|
define i1 @icmp_ptrtoint_ptrtoint_dyn_addrsize(ptr addrspace(1) %a) {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoint_ptrtoint_dyn_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) [[A:%.*]]) {
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr addrspace(1) [[A]], i32 1
|
|
; CHECK-NEXT: [[A_ADDR:%.*]] = ptrtoint ptr addrspace(1) [[A]] to i64
|
|
; CHECK-NEXT: [[GEP_ADDR:%.*]] = ptrtoint ptr addrspace(1) [[GEP]] to i64
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[A_ADDR]], [[GEP_ADDR]]
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%gep = getelementptr i8, ptr addrspace(1) %a, i32 1
|
|
%a.addr = ptrtoint ptr addrspace(1) %a to i64
|
|
%gep.addr = ptrtoint ptr addrspace(1) %gep to i64
|
|
%cmp = icmp ne i64 %a.addr, %gep.addr
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_null_dyn(ptr nonnull %a) {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_null_dyn(
|
|
; CHECK-SAME: ptr nonnull [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%a.addr = ptrtoaddr ptr %a to i64
|
|
%cmp = icmp ne i64 %a.addr, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoaddr_null_dyn_addrsize(ptr addrspace(1) nonnull %a) {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_null_dyn_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) nonnull [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%a.addr = ptrtoaddr ptr addrspace(1) %a to i32
|
|
%cmp = icmp ne i32 %a.addr, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @icmp_ptrtoint_null_dyn_addrsize(ptr addrspace(1) nonnull %a) {
|
|
; CHECK-LABEL: define i1 @icmp_ptrtoint_null_dyn_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) nonnull [[A:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%a.addr = ptrtoint ptr addrspace(1) %a to i64
|
|
%cmp = icmp ne i64 %a.addr, 0
|
|
ret i1 %cmp
|
|
}
|