588 lines
21 KiB
LLVM
588 lines
21 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
|
|
}
|
|
|
|
define i1 @non_zero_ptrtoaddr(ptr nonnull %p, i64 %unknown) {
|
|
; CHECK-LABEL: define i1 @non_zero_ptrtoaddr(
|
|
; CHECK-SAME: ptr nonnull [[P:%.*]], i64 [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%p.addr = ptrtoaddr ptr %p to i64
|
|
%or = or i64 %p.addr, %unknown
|
|
%cmp = icmp ne i64 %or, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @non_zero_ptrtoaddr_addrsize(ptr addrspace(1) nonnull %p, i32 %unknown) {
|
|
; CHECK-LABEL: define i1 @non_zero_ptrtoaddr_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) nonnull [[P:%.*]], i32 [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%p.addr = ptrtoaddr ptr addrspace(1) %p to i32
|
|
%or = or i32 %p.addr, %unknown
|
|
%cmp = icmp ne i32 %or, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @non_zero_ptrtoint_equal_addrsize(ptr addrspace(1) nonnull %p, i32 %unknown) {
|
|
; CHECK-LABEL: define i1 @non_zero_ptrtoint_equal_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) nonnull [[P:%.*]], i32 [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%p.addr = ptrtoint ptr addrspace(1) %p to i32
|
|
%or = or i32 %p.addr, %unknown
|
|
%cmp = icmp ne i32 %or, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @non_zero_ptrtoint_larger_addrsize(ptr addrspace(1) nonnull %p, i64 %unknown) {
|
|
; CHECK-LABEL: define i1 @non_zero_ptrtoint_larger_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) nonnull [[P:%.*]], i64 [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%p.addr = ptrtoint ptr addrspace(1) %p to i64
|
|
%or = or i64 %p.addr, %unknown
|
|
%cmp = icmp ne i64 %or, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @non_zero_ptrtoint_smaller_addrsize(ptr addrspace(1) nonnull %p, i16 %unknown) {
|
|
; CHECK-LABEL: define i1 @non_zero_ptrtoint_smaller_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) nonnull [[P:%.*]], i16 [[UNKNOWN:%.*]]) {
|
|
; CHECK-NEXT: [[P_ADDR:%.*]] = ptrtoint ptr addrspace(1) [[P]] to i16
|
|
; CHECK-NEXT: [[OR:%.*]] = or i16 [[P_ADDR]], [[UNKNOWN]]
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[OR]], 0
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%p.addr = ptrtoint ptr addrspace(1) %p to i16
|
|
%or = or i16 %p.addr, %unknown
|
|
%cmp = icmp ne i16 %or, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @ptrtoaddr_diff_non_equal(ptr %p0, ptr %p1) {
|
|
; CHECK-LABEL: define i1 @ptrtoaddr_diff_non_equal(
|
|
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) {
|
|
; CHECK-NEXT: [[I0:%.*]] = ptrtoaddr ptr [[P0]] to i64
|
|
; CHECK-NEXT: [[I1:%.*]] = ptrtoaddr ptr [[P1]] to i64
|
|
; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[I0]], [[I1]]
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[DIFF]], 12
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
%i0 = ptrtoaddr ptr %p0 to i64
|
|
%i1 = ptrtoaddr ptr %p1 to i64
|
|
%diff = sub i64 %i0, %i1
|
|
%cond = icmp eq i64 %diff, 12
|
|
call void @llvm.assume(i1 %cond)
|
|
%cmp = icmp eq ptr %p0, %p1
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @ptrtoaddr_diff_non_equal_addrsize(ptr addrspace(1) %p0, ptr addrspace(1) %p1) {
|
|
; CHECK-LABEL: define i1 @ptrtoaddr_diff_non_equal_addrsize(
|
|
; CHECK-SAME: ptr addrspace(1) [[P0:%.*]], ptr addrspace(1) [[P1:%.*]]) {
|
|
; CHECK-NEXT: [[I0:%.*]] = ptrtoaddr ptr addrspace(1) [[P0]] to i32
|
|
; CHECK-NEXT: [[I1:%.*]] = ptrtoaddr ptr addrspace(1) [[P1]] to i32
|
|
; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I0]], [[I1]]
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[DIFF]], 12
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
%i0 = ptrtoaddr ptr addrspace(1) %p0 to i32
|
|
%i1 = ptrtoaddr ptr addrspace(1) %p1 to i32
|
|
%diff = sub i32 %i0, %i1
|
|
%cond = icmp eq i32 %diff, 12
|
|
call void @llvm.assume(i1 %cond)
|
|
%cmp = icmp eq ptr addrspace(1) %p0, %p1
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @ptrtoaddr_diff_non_equal_addrsize_commuted(ptr addrspace(1) %p0, ptr addrspace(1) %p1) {
|
|
; CHECK-LABEL: define i1 @ptrtoaddr_diff_non_equal_addrsize_commuted(
|
|
; CHECK-SAME: ptr addrspace(1) [[P0:%.*]], ptr addrspace(1) [[P1:%.*]]) {
|
|
; CHECK-NEXT: [[I0:%.*]] = ptrtoaddr ptr addrspace(1) [[P0]] to i32
|
|
; CHECK-NEXT: [[I1:%.*]] = ptrtoaddr ptr addrspace(1) [[P1]] to i32
|
|
; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I0]], [[I1]]
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[DIFF]], 12
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
%i0 = ptrtoaddr ptr addrspace(1) %p0 to i32
|
|
%i1 = ptrtoaddr ptr addrspace(1) %p1 to i32
|
|
%diff = sub i32 %i0, %i1
|
|
%cond = icmp eq i32 %diff, 12
|
|
call void @llvm.assume(i1 %cond)
|
|
%cmp = icmp eq ptr addrspace(1) %p1, %p0
|
|
ret i1 %cmp
|
|
}
|