forked from OSchip/llvm-project
[GlobalOpt] recompute alignments for loads and stores of updated globals
GlobalOpt can slice structs/arrays and change GEPs in the process, but it was not updating alignments for load/store users. This eventually causes the crashing seen in: https://llvm.org/PR49661 https://llvm.org/PR50253 On x86, this required SLP+codegen to create an aligned vector store on an invalid address. The bugs would be easier to demonstrate on a target with stricter alignment requirements. I'm not sure if this is a complete solution. The alignment updating code is adapted from InstCombine, so I assume that part is tested and good. Differential Revision: https://reviews.llvm.org/D102552
This commit is contained in:
parent
ee4055cf23
commit
f34311c402
|
@ -630,6 +630,23 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
|
|||
}
|
||||
GEP->replaceAllUsesWith(NewPtr);
|
||||
|
||||
// We changed the pointer of any memory access user. Recalculate alignments.
|
||||
for (User *U : NewPtr->users()) {
|
||||
if (auto *Load = dyn_cast<LoadInst>(U)) {
|
||||
Align PrefAlign = DL.getPrefTypeAlign(Load->getType());
|
||||
Align NewAlign = getOrEnforceKnownAlignment(Load->getPointerOperand(),
|
||||
PrefAlign, DL, Load);
|
||||
Load->setAlignment(NewAlign);
|
||||
}
|
||||
if (auto *Store = dyn_cast<StoreInst>(U)) {
|
||||
Align PrefAlign =
|
||||
DL.getPrefTypeAlign(Store->getValueOperand()->getType());
|
||||
Align NewAlign = getOrEnforceKnownAlignment(Store->getPointerOperand(),
|
||||
PrefAlign, DL, Store);
|
||||
Store->setAlignment(NewAlign);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(GEP))
|
||||
GEPI->eraseFromParent();
|
||||
else
|
||||
|
|
|
@ -17,7 +17,9 @@ target datalayout = "p:16:32:128"
|
|||
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__I_a, i8* null }]
|
||||
@llvm.used = appending global [2 x i8*] [i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_OBJC_METH_VAR_NAME_40", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_41" to i8*)]
|
||||
|
||||
; CHECK: @[[_ZL14BUTTONINITDATA_0_0:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr global i8* null, align 4
|
||||
; Choose the preferred alignment.
|
||||
|
||||
; CHECK: @[[_ZL14BUTTONINITDATA_0_0:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr global i8* null, align 16
|
||||
;.
|
||||
define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
|
||||
%1 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_41", !invariant.load !2009
|
||||
|
@ -32,9 +34,11 @@ define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_i
|
|||
|
||||
declare void @test(i8*)
|
||||
|
||||
; The preferred alignment is available.
|
||||
|
||||
define void @print() {
|
||||
; CHECK-LABEL: @print(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i8*, i8** @_ZL14buttonInitData.0.0, align 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i8*, i8** @_ZL14buttonInitData.0.0, align 16
|
||||
; CHECK-NEXT: call void @test(i8* [[TMP1]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
|
|
@ -5,12 +5,13 @@ target datalayout = "p:16:32:64" ; 16-bit pointers with 32-bit ABI alignment and
|
|||
|
||||
@a = internal externally_initialized global [3 x [7 x i32*]] zeroinitializer, align 16
|
||||
|
||||
; FIXME:
|
||||
; PR50253
|
||||
; The store alignments are correct initially, but they should be updated
|
||||
; after transforming the global. The global pointer retains its original
|
||||
; "align 16", so access to element N into the new array should be offset
|
||||
; by the ABI alignment of N pointers.
|
||||
; 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_1:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr externally_initialized global [7 x i32*] zeroinitializer, align 16
|
||||
|
@ -22,7 +23,7 @@ target datalayout = "p:16:32:64" ; 16-bit pointers with 32-bit ABI alignment and
|
|||
define i32* @reduce_align_0() {
|
||||
; CHECK-LABEL: @reduce_align_0(
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.0, align 8
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 0), align 4
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 0), 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 0), align 8
|
||||
|
@ -32,8 +33,8 @@ define i32* @reduce_align_0() {
|
|||
|
||||
define i32* @reduce_align_1() {
|
||||
; CHECK-LABEL: @reduce_align_1(
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.1, align 4
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 1), align 16
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.1, align 8
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 1), align 4
|
||||
; 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
|
||||
|
@ -43,8 +44,8 @@ define i32* @reduce_align_1() {
|
|||
|
||||
define i32* @reduce_align_2() {
|
||||
; CHECK-LABEL: @reduce_align_2(
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.2, align 16
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 2), align 4
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.2, align 8
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 2), 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 2), align 16
|
||||
|
@ -54,8 +55,8 @@ define i32* @reduce_align_2() {
|
|||
|
||||
define i32* @reduce_align_3() {
|
||||
; CHECK-LABEL: @reduce_align_3(
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.3, align 4
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 3), align 8
|
||||
; CHECK-NEXT: [[X:%.*]] = load i32*, i32** @a.2.3, align 8
|
||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([7 x i32*], [7 x i32*]* @a.1, i32 0, i64 3), align 4
|
||||
; 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
|
||||
|
|
Loading…
Reference in New Issue