isEliminableCastPair() currently tries to support elimination of ptrtoint/inttoptr cast pairs by assuming that the maximum possible pointer size is 64 bits. Of course, this is no longer the case nowadays. This PR changes isEliminableCastPair() to accept an optional DataLayout argument, which is required to eliminate pointer casts. This means that we no longer eliminate these cast pairs during ConstExpr construction, and instead only do it during DL-aware constant folding. This had a lot of annoying fallout on tests, most of which I've addressed in advance of this change.
153 lines
6.3 KiB
LLVM
153 lines
6.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
|
|
|
|
target datalayout = "p1:128:128:128"
|
|
|
|
define i64 @ptrtoint_gep_sub(ptr %ptr, i64 %end.addr) {
|
|
; CHECK-LABEL: define i64 @ptrtoint_gep_sub(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: ret i64 [[END_ADDR]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i64
|
|
%size = sub i64 %end.addr, %ptr.addr
|
|
%end = getelementptr i8, ptr %ptr, i64 %size
|
|
%end.addr2 = ptrtoint ptr %end to i64
|
|
ret i64 %end.addr2
|
|
}
|
|
|
|
define <2 x i64> @ptrtoint_gep_sub_vector(<2 x ptr> %ptr, <2 x i64> %end.addr) {
|
|
; CHECK-LABEL: define <2 x i64> @ptrtoint_gep_sub_vector(
|
|
; CHECK-SAME: <2 x ptr> [[PTR:%.*]], <2 x i64> [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: ret <2 x i64> [[END_ADDR]]
|
|
;
|
|
%ptr.addr = ptrtoint <2 x ptr> %ptr to <2 x i64>
|
|
%size = sub <2 x i64> %end.addr, %ptr.addr
|
|
%end = getelementptr i8, <2 x ptr> %ptr, <2 x i64> %size
|
|
%end.addr2 = ptrtoint <2 x ptr> %end to <2 x i64>
|
|
ret <2 x i64> %end.addr2
|
|
}
|
|
|
|
define i64 @ptrtoint_gep_sub_wrong_gep_type(ptr %ptr, i64 %end.addr) {
|
|
; CHECK-LABEL: define i64 @ptrtoint_gep_sub_wrong_gep_type(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i64
|
|
; CHECK-NEXT: [[SIZE:%.*]] = sub i64 [[END_ADDR]], [[PTR_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i64
|
|
; CHECK-NEXT: ret i64 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i64
|
|
%size = sub i64 %end.addr, %ptr.addr
|
|
%end = getelementptr i32, ptr %ptr, i64 %size
|
|
%end.addr2 = ptrtoint ptr %end to i64
|
|
ret i64 %end.addr2
|
|
}
|
|
|
|
define i64 @ptrtoint_gep_sub_wrong_ptrtoint_op(ptr %ptr, i64 %end.addr, ptr %ptr2) {
|
|
; CHECK-LABEL: define i64 @ptrtoint_gep_sub_wrong_ptrtoint_op(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[END_ADDR:%.*]], ptr [[PTR2:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR2]] to i64
|
|
; CHECK-NEXT: [[SIZE:%.*]] = sub i64 [[END_ADDR]], [[PTR_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i64
|
|
; CHECK-NEXT: ret i64 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr2 to i64
|
|
%size = sub i64 %end.addr, %ptr.addr
|
|
%end = getelementptr i8, ptr %ptr, i64 %size
|
|
%end.addr2 = ptrtoint ptr %end to i64
|
|
ret i64 %end.addr2
|
|
}
|
|
|
|
define i64 @ptrtoint_gep_sub_wrong_operation(ptr %ptr, i64 %end.addr) {
|
|
; CHECK-LABEL: define i64 @ptrtoint_gep_sub_wrong_operation(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i64
|
|
; CHECK-NEXT: [[SIZE:%.*]] = add i64 [[END_ADDR]], [[PTR_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i64
|
|
; CHECK-NEXT: ret i64 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i64
|
|
%size = add i64 %end.addr, %ptr.addr
|
|
%end = getelementptr i8, ptr %ptr, i64 %size
|
|
%end.addr2 = ptrtoint ptr %end to i64
|
|
ret i64 %end.addr2
|
|
}
|
|
|
|
define i64 @ptrtoint_gep_sub_wrong_operand_order(ptr %ptr, i64 %end.addr) {
|
|
; CHECK-LABEL: define i64 @ptrtoint_gep_sub_wrong_operand_order(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i64
|
|
; CHECK-NEXT: [[SIZE:%.*]] = sub i64 [[PTR_ADDR]], [[END_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i64
|
|
; CHECK-NEXT: ret i64 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i64
|
|
%size = sub i64 %ptr.addr, %end.addr
|
|
%end = getelementptr i8, ptr %ptr, i64 %size
|
|
%end.addr2 = ptrtoint ptr %end to i64
|
|
ret i64 %end.addr2
|
|
}
|
|
|
|
define i32 @ptrtoint_gep_sub_wrong_type(ptr %ptr, i64 %end.addr) {
|
|
; CHECK-LABEL: define i32 @ptrtoint_gep_sub_wrong_type(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i64
|
|
; CHECK-NEXT: [[SIZE:%.*]] = sub i64 [[END_ADDR]], [[PTR_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i32
|
|
; CHECK-NEXT: ret i32 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i64
|
|
%size = sub i64 %end.addr, %ptr.addr
|
|
%end = getelementptr i8, ptr %ptr, i64 %size
|
|
%end.addr2 = ptrtoint ptr %end to i32
|
|
ret i32 %end.addr2
|
|
}
|
|
|
|
define i32 @ptrtoint_gep_sub_narrow_type(ptr %ptr, i32 %end.addr) {
|
|
; CHECK-LABEL: define i32 @ptrtoint_gep_sub_narrow_type(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i32 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i32
|
|
; CHECK-NEXT: [[SIZE:%.*]] = sub i32 [[END_ADDR]], [[PTR_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i8, ptr [[PTR]], i32 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i32
|
|
; CHECK-NEXT: ret i32 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i32
|
|
%size = sub i32 %end.addr, %ptr.addr
|
|
%end = getelementptr i8, ptr %ptr, i32 %size
|
|
%end.addr2 = ptrtoint ptr %end to i32
|
|
ret i32 %end.addr2
|
|
}
|
|
|
|
define i128 @ptrtoint_gep_sub_wide_type(ptr %ptr, i128 %end.addr) {
|
|
; CHECK-LABEL: define i128 @ptrtoint_gep_sub_wide_type(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], i128 [[END_ADDR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR_ADDR:%.*]] = ptrtoint ptr [[PTR]] to i128
|
|
; CHECK-NEXT: [[SIZE:%.*]] = sub i128 [[END_ADDR]], [[PTR_ADDR]]
|
|
; CHECK-NEXT: [[END:%.*]] = getelementptr i8, ptr [[PTR]], i128 [[SIZE]]
|
|
; CHECK-NEXT: [[END_ADDR2:%.*]] = ptrtoint ptr [[END]] to i128
|
|
; CHECK-NEXT: ret i128 [[END_ADDR2]]
|
|
;
|
|
%ptr.addr = ptrtoint ptr %ptr to i128
|
|
%size = sub i128 %end.addr, %ptr.addr
|
|
%end = getelementptr i8, ptr %ptr, i128 %size
|
|
%end.addr2 = ptrtoint ptr %end to i128
|
|
ret i128 %end.addr2
|
|
}
|
|
|
|
define ptr addrspace(1) @inttoptr_of_ptrtoint_wide(ptr addrspace(1) %ptr) {
|
|
; CHECK-LABEL: define ptr addrspace(1) @inttoptr_of_ptrtoint_wide(
|
|
; CHECK-SAME: ptr addrspace(1) [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[INT:%.*]] = ptrtoint ptr addrspace(1) [[PTR]] to i64
|
|
; CHECK-NEXT: [[PTR2:%.*]] = inttoptr i64 [[INT]] to ptr addrspace(1)
|
|
; CHECK-NEXT: ret ptr addrspace(1) [[PTR2]]
|
|
;
|
|
%int = ptrtoint ptr addrspace(1) %ptr to i64
|
|
%ptr2 = inttoptr i64 %int to ptr addrspace(1)
|
|
ret ptr addrspace(1) %ptr2
|
|
}
|