The malloc to global transform currently determines the type of the global by looking at bitcasts of the malloc. This is limited (the transform fails if there are multiple different types) and incompatible with opaque pointers. My initial approach was to construct an appropriate struct type based on usage in loads/stores. What this patch does instead is to always create an [i8 x AllocSize] global, without trying to guess types at all. This does mean that other transforms that require a certain global type may break. I fixed two of these in D117034 and D117223, which I believe should be sufficient to avoid regressions. In particular, the global SRA change should end up splitting the global into naturally-typed sub-globals, at which point all other optimizations should work. Differential Revision: https://reviews.llvm.org/D117092
50 lines
1.5 KiB
LLVM
50 lines
1.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=globalopt -S < %s | FileCheck %s
|
|
; RUN: opt -passes=globalopt -S < %s | FileCheck %s
|
|
|
|
@g = internal global i32* null, align 8
|
|
|
|
define signext i32 @f() local_unnamed_addr {
|
|
; CHECK-LABEL: @f(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: store i16 -1, i16* bitcast ([4 x i8]* @g.body to i16*), align 2
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
entry:
|
|
%call = call i8* @malloc(i64 4)
|
|
%b = bitcast i8* %call to i32*
|
|
store i32* %b, i32** @g, align 8
|
|
%b2 = bitcast i8* %call to i16*
|
|
store i16 -1, i16* %b2
|
|
ret i32 0
|
|
}
|
|
|
|
define signext i32 @main() {
|
|
; CHECK-LABEL: @main(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = call signext i32 @f()
|
|
; CHECK-NEXT: call void @f1()
|
|
; CHECK-NEXT: store i32 1, i32* bitcast ([4 x i8]* @g.body to i32*), align 4
|
|
; CHECK-NEXT: call void @f1()
|
|
; CHECK-NEXT: store i8 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @g.body, i32 0, i32 0), align 4
|
|
; CHECK-NEXT: call void @f1()
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* bitcast ([4 x i8]* @g.body to i32*), align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%call = call signext i32 @f()
|
|
call void @f1()
|
|
%v0 = load i32*, i32** @g, align 8
|
|
store i32 1, i32* %v0, align 4
|
|
call void @f1()
|
|
%v1 = load i8*, i8** bitcast (i32** @g to i8**), align 8
|
|
store i8 2, i8* %v1, align 4
|
|
call void @f1()
|
|
%v2 = load i32*, i32** @g, align 8
|
|
%res = load i32, i32* %v2, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
declare noalias align 16 i8* @malloc(i64)
|
|
declare void @f1()
|