1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00
llvm-mirror/test/Transforms/InstCombine/non-integral-pointers.ll
Roman Lebedev 0b6b012562 [InstCombine] Revert rL226781 "Teach InstCombine to canonicalize loads which are only ever stored to always use a legal integer type if one is available." (PR47592)
(it was introduced in https://lists.llvm.org/pipermail/llvm-dev/2015-January/080956.html)

This canonicalization seems dubious.

Most importantly, while it does not create `inttoptr` casts by itself,
it may cause them to appear later, see e.g. D88788.

I think it's pretty obvious that it is an undesirable outcome,
by now we've established that seemingly no-op `inttoptr`/`ptrtoint` casts
are not no-op, and are no longer eager to look past them.
Which e.g. means that given
```
%a = load i32
%b = inttoptr %a
%c = inttoptr %a
```
we likely won't be able to tell that `%b` and `%c` is the same thing.

As we can see in D88789 / D88788 / D88806 / D75505,
we can't really teach SCEV about this (not without the https://bugs.llvm.org/show_bug.cgi?id=47592 at least)
And we can't recover the situation post-inlining in instcombine.

So it really does look like this fold is actively breaking
otherwise-good IR, in a way that is not recoverable.
And that means, this fold isn't helpful in exposing the passes
that are otherwise unaware of these patterns it produces.

Thusly, i propose to simply not perform such a canonicalization.
The original motivational RFC does not state what larger problem
that canonicalization was trying to solve, so i'm not sure
how this plays out in the larger picture.

On vanilla llvm test-suite + RawSpeed, this results in
increase of asm instructions and final object size by ~+0.05%
decreases final count of bitcasts by -4.79% (-28990),
ptrtoint casts by -15.41% (-3423),
and of inttoptr casts by -25.59% (-6919, *sic*).
Overall, there's -0.04% less IR blocks, -0.39% instructions.

See https://bugs.llvm.org/show_bug.cgi?id=47592

Differential Revision: https://reviews.llvm.org/D88789
2020-10-06 00:00:30 +03:00

111 lines
4.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -instcombine -S < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4"
target triple = "x86_64-unknown-linux-gnu"
define i8 addrspace(4)* @f_0() {
; CHECK-LABEL: @f_0(
; CHECK-NEXT: ret i8 addrspace(4)* getelementptr (i8, i8 addrspace(4)* null, i64 50)
;
%result = getelementptr i8, i8 addrspace(4)* null, i64 50
ret i8 addrspace(4)* %result
}
define i8 addrspace(3)* @f_1() {
; inttoptr is fine here since addrspace(3) is integral.
; CHECK-LABEL: @f_1(
; CHECK-NEXT: ret i8 addrspace(3)* inttoptr (i64 50 to i8 addrspace(3)*)
;
%result = getelementptr i8, i8 addrspace(3)* null, i64 50
ret i8 addrspace(3)* %result
}
define void @f_2(i8 addrspace(4)** %ptr0, i8 addrspace(4)** %ptr1) {
; It is not okay to convert the load/store pair to load and store
; integers, since pointers in address space 4 are non-integral.
; CHECK-LABEL: @f_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[VAL:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)** [[PTR0:%.*]], align 8
; CHECK-NEXT: store i8 addrspace(4)* [[VAL]], i8 addrspace(4)** [[PTR1:%.*]], align 8
; CHECK-NEXT: ret void
;
entry:
%val = load i8 addrspace(4)*, i8 addrspace(4)** %ptr0
store i8 addrspace(4)* %val, i8 addrspace(4)** %ptr1
ret void
}
define void @f_3(i8 addrspace(3)** %ptr0, i8 addrspace(3)** %ptr1) {
; It *is* okay to convert the load/store pair to load and store
; integers, since pointers in address space 3 are integral.
; CHECK-LABEL: @f_3(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[VAL:%.*]] = load i8 addrspace(3)*, i8 addrspace(3)** [[PTR0:%.*]], align 8
; CHECK-NEXT: store i8 addrspace(3)* [[VAL]], i8 addrspace(3)** [[PTR1:%.*]], align 8
; CHECK-NEXT: ret void
;
entry:
%val = load i8 addrspace(3)*, i8 addrspace(3)** %ptr0
store i8 addrspace(3)* %val, i8 addrspace(3)** %ptr1
ret void
}
define i64 @g(i8 addrspace(4)** %gp) {
; CHECK-LABEL: @g(
; CHECK-NEXT: [[DOTPRE:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)** [[GP:%.*]], align 8
; CHECK-NEXT: [[V74:%.*]] = call i8 addrspace(4)* @alloc()
; CHECK-NEXT: [[V77:%.*]] = getelementptr i8, i8 addrspace(4)* [[V74]], i64 -8
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8 addrspace(4)* [[V77]] to i8 addrspace(4)* addrspace(4)*
; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast i8 addrspace(4)* addrspace(4)* [[TMP1]] to i8 addrspace(4)**
; CHECK-NEXT: store i8 addrspace(4)* [[DOTPRE]], i8 addrspace(4)** [[TMP2]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8 addrspace(4)* [[V77]] to i64 addrspace(4)*
; CHECK-NEXT: [[V80:%.*]] = addrspacecast i64 addrspace(4)* [[TMP3]] to i64*
; CHECK-NEXT: [[V81:%.*]] = load i64, i64* [[V80]], align 8
; CHECK-NEXT: ret i64 [[V81]]
;
%.pre = load i8 addrspace(4)*, i8 addrspace(4)** %gp, align 8
%v74 = call i8 addrspace(4)* @alloc()
%v75 = addrspacecast i8 addrspace(4)* %v74 to i8*
%v76 = bitcast i8* %v75 to i8 addrspace(4)**
%v77 = getelementptr i8 addrspace(4)*, i8 addrspace(4)** %v76, i64 -1
store i8 addrspace(4)* %.pre, i8 addrspace(4)** %v77, align 8
%v80 = bitcast i8 addrspace(4)** %v77 to i64*
%v81 = load i64, i64* %v80, align 8
ret i64 %v81
}
define i64 @g2(i8* addrspace(4)* %gp) {
; CHECK-LABEL: @g2(
; CHECK-NEXT: [[DOTPRE:%.*]] = load i8*, i8* addrspace(4)* [[GP:%.*]], align 8
; CHECK-NEXT: [[V74:%.*]] = call i8 addrspace(4)* @alloc()
; CHECK-NEXT: [[V77:%.*]] = getelementptr i8, i8 addrspace(4)* [[V74]], i64 -8
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8 addrspace(4)* [[V77]] to i8* addrspace(4)*
; CHECK-NEXT: store i8* [[DOTPRE]], i8* addrspace(4)* [[TMP1]], align 8
; CHECK-NEXT: [[V81_CAST:%.*]] = ptrtoint i8* [[DOTPRE]] to i64
; CHECK-NEXT: ret i64 [[V81_CAST]]
;
%.pre = load i8*, i8* addrspace(4)* %gp, align 8
%v74 = call i8 addrspace(4)* @alloc()
%v76 = bitcast i8 addrspace(4)* %v74 to i8* addrspace(4)*
%v77 = getelementptr i8*, i8* addrspace(4)* %v76, i64 -1
store i8* %.pre, i8* addrspace(4)* %v77, align 8
%v80 = bitcast i8* addrspace(4)* %v77 to i64 addrspace(4)*
%v81 = load i64, i64 addrspace(4)* %v80, align 8
ret i64 %v81
}
declare i8 addrspace(4)* @alloc()
define i64 @f_4(i8 addrspace(4)* %v0) {
; CHECK-LABEL: @f_4(
; CHECK-NEXT: [[V6:%.*]] = call i64 bitcast (i64 (i64)* @f_5 to i64 (i8 addrspace(4)*)*)(i8 addrspace(4)* [[V0:%.*]])
; CHECK-NEXT: ret i64 [[V6]]
;
%v5 = bitcast i64 (i64)* @f_5 to i64 (i8 addrspace(4)*)*
%v6 = call i64 %v5(i8 addrspace(4)* %v0)
ret i64 %v6
}
declare i64 @f_5(i64)