All the existing tests test code either in ConstantFolding or InstSimplify, so move them to use -passes=instsimplify instead of -passes=instcombine. This makes sure we keep InstSimplify coverage even if there are subsuming InstCombine folds. This requires writing some of the constant folding tests in a different way, as InstSimplify does not try to re-fold already existing constant expressions.
210 lines
6.6 KiB
LLVM
210 lines
6.6 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
|
|
}
|