Nikita Popov 4796b4ae7b [GlobalOpt] Make global SRA offset based
Currently global SRA uses the GEP structure to determine how to
split the global. This patch instead analyses the loads and stores
that are performed on the global, and collects which types are used
at which offset, and then splits the global according to those.

This is both more general, and works fine with opaque pointers.
This is also closer to how ordinary SROA is performed.

Differential Revision: https://reviews.llvm.org/D117223
2022-01-17 09:28:36 +01:00

61 lines
2.8 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
; RUN: opt < %s -passes=globalopt -S | FileCheck %s
target datalayout = "p:16:32:64" ; 16-bit pointers with 32-bit ABI alignment and 64-bit preferred alignmentt
@a = internal externally_initialized global [3 x [7 x i32*]] zeroinitializer, align 16
; PR50253
; The alignments are correct initially, but they should be updated
; after transforming the global. The stored global pointer array retains
; its original "align 16", so access to element N into the new array
; should be offset by the ABI alignment of N pointers.
; Loaded globals are split into individual pointers and use the
; preferred alignment from the datalayout.
;.
; CHECK: @[[A_4:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr externally_initialized global i32* null, align 8
; CHECK: @[[A_5:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr externally_initialized global i32* null, align 16
; CHECK: @[[A_6:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr externally_initialized global i32* null, align 16
; CHECK: @[[A_7:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr externally_initialized global i32* null, align 16
;.
define i32* @reduce_align_0() {
; CHECK-LABEL: @reduce_align_0(
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.4, align 8
; CHECK-NEXT: ret i32* [[X]]
;
%x = load i32*, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 2, i64 0), align 8
store i32* null, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 1, i64 0), align 4
ret i32* %x
}
define i32* @reduce_align_1() {
; CHECK-LABEL: @reduce_align_1(
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.5, align 16
; CHECK-NEXT: ret i32* [[X]]
;
%x = load i32*, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 2, i64 1), align 4
store i32* null, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 1, i64 1), align 16
ret i32* %x
}
define i32* @reduce_align_2() {
; CHECK-LABEL: @reduce_align_2(
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.6, align 16
; CHECK-NEXT: ret i32* [[X]]
;
%x = load i32*, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 2, i64 2), align 16
store i32* null, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 1, i64 2), align 4
ret i32* %x
}
define i32* @reduce_align_3() {
; CHECK-LABEL: @reduce_align_3(
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.7, align 16
; CHECK-NEXT: ret i32* [[X]]
;
%x = load i32*, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 2, i64 3), align 4
store i32* null, i32** getelementptr inbounds ([3 x [7 x i32*]], [3 x [7 x i32*]]* @a, i64 0, i64 1, i64 3), align 8
ret i32* %x
}