
Fixes #154056. The fat buffer lowering pass was erroniously detecting that it did not need to run on functions that only load/store to the null constant (or other such constants). We thought this would be covered by specializing constants out to instructions, but that doesn't account foc trivial constants like null. Therefore, we check the operands of instructions for buffer fat pointers in order to find such constants and ensure the pass runs. --------- Co-authored-by: Nikita Popov <github@npopov.com>
266 lines
8.6 KiB
LLVM
266 lines
8.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -S -mcpu=gfx900 -amdgpu-lower-buffer-fat-pointers < %s | FileCheck %s
|
|
; RUN: opt -S -mcpu=gfx900 -passes=amdgpu-lower-buffer-fat-pointers < %s | FileCheck %s
|
|
|
|
target triple = "amdgcn--"
|
|
|
|
@buf = external addrspace(8) global i8
|
|
@flat = external global i8
|
|
|
|
define ptr addrspace(7) @null() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @null
|
|
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } zeroinitializer
|
|
;
|
|
ret ptr addrspace(7) null
|
|
}
|
|
|
|
define <2 x ptr addrspace(7)> @null_vector() {
|
|
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @null_vector
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } zeroinitializer
|
|
;
|
|
ret <2 x ptr addrspace(7)> zeroinitializer
|
|
}
|
|
|
|
define ptr addrspace(7) @undef() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @undef
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } undef
|
|
;
|
|
ret ptr addrspace(7) undef
|
|
}
|
|
|
|
define <2 x ptr addrspace(7)> @undef_vec() {
|
|
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @undef_vec
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } undef
|
|
;
|
|
ret <2 x ptr addrspace(7)> undef
|
|
}
|
|
|
|
define ptr addrspace(7) @poison() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @poison
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } poison
|
|
;
|
|
ret ptr addrspace(7) poison
|
|
}
|
|
|
|
define <2 x ptr addrspace(7)> @poison_vec() {
|
|
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @poison_vec
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } poison
|
|
;
|
|
ret <2 x ptr addrspace(7)> poison
|
|
}
|
|
|
|
define ptr addrspace(7) @cast_global() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @cast_global
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } { ptr addrspace(8) @buf, i32 0 }
|
|
;
|
|
ret ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7))
|
|
}
|
|
|
|
define ptr addrspace(7) @cast_null() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @cast_null
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } zeroinitializer
|
|
;
|
|
ret ptr addrspace(7) addrspacecast (ptr addrspace(8) null to ptr addrspace(7))
|
|
}
|
|
|
|
define <2 x ptr addrspace(7)> @cast_vec() {
|
|
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @cast_vec
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } { <2 x ptr addrspace(8)> <ptr addrspace(8) @buf, ptr addrspace(8) null>, <2 x i32> zeroinitializer }
|
|
;
|
|
ret <2 x ptr addrspace(7)> addrspacecast (
|
|
<2 x ptr addrspace(8)> <ptr addrspace(8) @buf, ptr addrspace(8) null>
|
|
to <2 x ptr addrspace(7)>)
|
|
}
|
|
|
|
define ptr addrspace(7) @gep() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @gep
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } { ptr addrspace(8) @buf, i32 36 }
|
|
;
|
|
ret ptr addrspace(7) getelementptr inbounds (
|
|
[4 x i32],
|
|
ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
i64 2, i32 1)
|
|
}
|
|
|
|
define <2 x ptr addrspace(7)> @gep_vector() {
|
|
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @gep_vector
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } { <2 x ptr addrspace(8)> <ptr addrspace(8) @buf, ptr addrspace(8) null>, <2 x i32> <i32 12, i32 4> }
|
|
;
|
|
ret <2 x ptr addrspace(7)> getelementptr (
|
|
i32,
|
|
<2 x ptr addrspace(7)>
|
|
<ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
ptr addrspace(7) null>,
|
|
<2 x i32> <i32 3, i32 1>)
|
|
}
|
|
|
|
define ptr @gep_of_p7() {
|
|
; CHECK-LABEL: define ptr @gep_of_p7
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret ptr getelementptr inbounds (ptr addrspace(7), ptr @flat, i64 2)
|
|
;
|
|
ret ptr getelementptr inbounds (ptr addrspace(7), ptr @flat, i64 2)
|
|
}
|
|
|
|
define ptr @gep_of_p7_vector() {
|
|
; CHECK-LABEL: define ptr @gep_of_p7_vector
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret ptr getelementptr (<2 x ptr addrspace(7)>, ptr @flat, i64 2)
|
|
;
|
|
ret ptr getelementptr (<2 x ptr addrspace(7)>, ptr @flat, i64 2)
|
|
}
|
|
|
|
define ptr @gep_of_p7_struct() {
|
|
; CHECK-LABEL: define ptr @gep_of_p7_struct
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret ptr getelementptr ({ ptr addrspace(7), i32 }, ptr @flat, i64 2)
|
|
;
|
|
ret ptr getelementptr ({ptr addrspace(7), i32}, ptr @flat, i64 2)
|
|
}
|
|
|
|
define ptr addrspace(7) @gep_p7_from_p7() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @gep_p7_from_p7
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } { ptr addrspace(8) @buf, i32 48 }
|
|
;
|
|
ret ptr addrspace(7) getelementptr (ptr addrspace(7),
|
|
ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
i64 2)
|
|
}
|
|
|
|
define i160 @ptrtoint() {
|
|
; CHECK-LABEL: define i160 @ptrtoint
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i160 ptrtoint (ptr addrspace(8) @buf to i160), 32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i160 [[TMP1]], 12
|
|
; CHECK-NEXT: ret i160 [[TMP2]]
|
|
;
|
|
ret i160 ptrtoint(
|
|
ptr addrspace(7) getelementptr(
|
|
i32, ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
i32 3) to i160)
|
|
}
|
|
|
|
define i256 @ptrtoint_long() {
|
|
; CHECK-LABEL: define i256 @ptrtoint_long
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i256 ptrtoint (ptr addrspace(8) @buf to i256), 32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i256 [[TMP1]], 12
|
|
; CHECK-NEXT: ret i256 [[TMP2]]
|
|
;
|
|
ret i256 ptrtoint(
|
|
ptr addrspace(7) getelementptr(
|
|
i32, ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
i32 3) to i256)
|
|
}
|
|
|
|
define i64 @ptrtoint_short() {
|
|
; CHECK-LABEL: define i64 @ptrtoint_short
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 ptrtoint (ptr addrspace(8) @buf to i64), 32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = or i64 [[TMP1]], 12
|
|
; CHECK-NEXT: ret i64 [[TMP2]]
|
|
;
|
|
ret i64 ptrtoint(
|
|
ptr addrspace(7) getelementptr(
|
|
i32, ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
i32 3) to i64)
|
|
}
|
|
|
|
define i32 @ptrtoint_very_short() {
|
|
; CHECK-LABEL: define i32 @ptrtoint_very_short
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret i32 12
|
|
;
|
|
ret i32 ptrtoint(
|
|
ptr addrspace(7) getelementptr(
|
|
i32, ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7)),
|
|
i32 3) to i32)
|
|
}
|
|
|
|
|
|
define <2 x i160> @ptrtoint_vec() {
|
|
; CHECK-LABEL: define <2 x i160> @ptrtoint_vec
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret <2 x i160> zeroinitializer
|
|
;
|
|
ret <2 x i160> ptrtoint (<2 x ptr addrspace(7)> zeroinitializer to <2 x i160>)
|
|
}
|
|
|
|
define ptr addrspace(7) @inttoptr() {
|
|
; CHECK-LABEL: define { ptr addrspace(8), i32 } @inttoptr
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { ptr addrspace(8), i32 } zeroinitializer
|
|
;
|
|
ret ptr addrspace(7) inttoptr (i160 0 to ptr addrspace(7))
|
|
}
|
|
|
|
define <2 x ptr addrspace(7)> @inttoptr_vec() {
|
|
; CHECK-LABEL: define { <2 x ptr addrspace(8)>, <2 x i32> } @inttoptr_vec
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret { <2 x ptr addrspace(8)>, <2 x i32> } { <2 x ptr addrspace(8)> zeroinitializer, <2 x i32> <i32 1, i32 2> }
|
|
;
|
|
ret <2 x ptr addrspace(7)> inttoptr (<2 x i160> <i160 1, i160 2> to <2 x ptr addrspace(7)>)
|
|
}
|
|
|
|
define i32 @fancy_zero() {
|
|
; CHECK-LABEL: define i32 @fancy_zero
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
ret i32 ptrtoint (
|
|
ptr addrspace(7) addrspacecast (ptr addrspace(8) @buf to ptr addrspace(7))
|
|
to i32)
|
|
}
|
|
|
|
define i32 @load_null() {
|
|
; CHECK-LABEL: define i32 @load_null
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) align 4 null, i32 0, i32 0, i32 0)
|
|
; CHECK-NEXT: ret i32 [[X]]
|
|
;
|
|
%x = load i32, ptr addrspace(7) null, align 4
|
|
ret i32 %x
|
|
}
|
|
|
|
define void @store_null() {
|
|
; CHECK-LABEL: define void @store_null
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 0, ptr addrspace(8) align 4 null, i32 0, i32 0, i32 0)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
store i32 0, ptr addrspace(7) null, align 4
|
|
ret void
|
|
}
|
|
|
|
define i32 @load_poison() {
|
|
; CHECK-LABEL: define i32 @load_poison
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.amdgcn.raw.ptr.buffer.load.i32(ptr addrspace(8) align 4 poison, i32 poison, i32 0, i32 0)
|
|
; CHECK-NEXT: ret i32 [[X]]
|
|
;
|
|
%x = load i32, ptr addrspace(7) poison, align 4
|
|
ret i32 %x
|
|
}
|
|
|
|
define void @store_poison() {
|
|
; CHECK-LABEL: define void @store_poison
|
|
; CHECK-SAME: () #[[ATTR0]] {
|
|
; CHECK-NEXT: call void @llvm.amdgcn.raw.ptr.buffer.store.i32(i32 0, ptr addrspace(8) align 4 poison, i32 poison, i32 0, i32 0)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
store i32 0, ptr addrspace(7) poison, align 4
|
|
ret void
|
|
}
|