forked from OSchip/llvm-project
[GlobalOpt] Support "stored once" optimization for different types
GlobalOpt can optimize a global with undef initializer and a single store to put the stored value into the initializer instead. Currently, this requires the type of the global and the store to match. This patch extends support to cases with different types (but same size), in which case we create a new global to replace the old one. Differential Revision: https://reviews.llvm.org/D117034
This commit is contained in:
parent
c4db521cea
commit
f3e87176e1
|
@ -1672,11 +1672,25 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
|
||||||
// This is restricted to address spaces that allow globals to have
|
// This is restricted to address spaces that allow globals to have
|
||||||
// initializers. NVPTX, for example, does not support initializers for
|
// initializers. NVPTX, for example, does not support initializers for
|
||||||
// shared memory (AS 3).
|
// shared memory (AS 3).
|
||||||
if (SOVConstant && SOVConstant->getType() == GV->getValueType() &&
|
if (SOVConstant && isa<UndefValue>(GV->getInitializer()) &&
|
||||||
isa<UndefValue>(GV->getInitializer()) &&
|
DL.getTypeAllocSize(SOVConstant->getType()) ==
|
||||||
|
DL.getTypeAllocSize(GV->getValueType()) &&
|
||||||
CanHaveNonUndefGlobalInitializer) {
|
CanHaveNonUndefGlobalInitializer) {
|
||||||
// Change the initial value here.
|
if (SOVConstant->getType() == GV->getValueType()) {
|
||||||
GV->setInitializer(SOVConstant);
|
// Change the initializer in place.
|
||||||
|
GV->setInitializer(SOVConstant);
|
||||||
|
} else {
|
||||||
|
// Create a new global with adjusted type.
|
||||||
|
auto *NGV = new GlobalVariable(
|
||||||
|
*GV->getParent(), SOVConstant->getType(), GV->isConstant(),
|
||||||
|
GV->getLinkage(), SOVConstant, "", GV, GV->getThreadLocalMode(),
|
||||||
|
GV->getAddressSpace());
|
||||||
|
NGV->takeName(GV);
|
||||||
|
NGV->copyAttributesFrom(GV);
|
||||||
|
GV->replaceAllUsesWith(ConstantExpr::getBitCast(NGV, GV->getType()));
|
||||||
|
GV->eraseFromParent();
|
||||||
|
GV = NGV;
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up any obviously simplifiable users now.
|
// Clean up any obviously simplifiable users now.
|
||||||
CleanupConstantGlobalUsers(GV, DL);
|
CleanupConstantGlobalUsers(GV, DL);
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
|
||||||
|
; RUN: opt -S -globalopt < %s | FileCheck %s
|
||||||
|
|
||||||
|
@g = internal global [4 x i8] undef
|
||||||
|
|
||||||
|
;.
|
||||||
|
; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr constant i32 42
|
||||||
|
;.
|
||||||
|
define void @store() {
|
||||||
|
; CHECK-LABEL: @store(
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
;
|
||||||
|
store i32 42, i32* bitcast ([4 x i8]* @g to i32*)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @load1() {
|
||||||
|
; CHECK-LABEL: @load1(
|
||||||
|
; CHECK-NEXT: ret i32 42
|
||||||
|
;
|
||||||
|
%v = load i32, i32* bitcast ([4 x i8]* @g to i32*)
|
||||||
|
ret i32 %v
|
||||||
|
}
|
||||||
|
|
||||||
|
define i16 @load2() {
|
||||||
|
; CHECK-LABEL: @load2(
|
||||||
|
; CHECK-NEXT: ret i16 42
|
||||||
|
;
|
||||||
|
%v = load i16, i16* bitcast ([4 x i8]* @g to i16*)
|
||||||
|
ret i16 %v
|
||||||
|
}
|
||||||
|
|
||||||
|
define [4 x i8] @load3() {
|
||||||
|
; CHECK-LABEL: @load3(
|
||||||
|
; CHECK-NEXT: [[V:%.*]] = load [4 x i8], [4 x i8]* bitcast (i32* @g to [4 x i8]*), align 1
|
||||||
|
; CHECK-NEXT: ret [4 x i8] [[V]]
|
||||||
|
;
|
||||||
|
%v = load [4 x i8], [4 x i8]* @g
|
||||||
|
ret [4 x i8] %v
|
||||||
|
}
|
|
@ -8,13 +8,8 @@
|
||||||
|
|
||||||
@0 = internal global %T* null
|
@0 = internal global %T* null
|
||||||
|
|
||||||
;.
|
|
||||||
; CHECK: @[[_BODY:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr global [[T:%.*]] undef
|
|
||||||
;.
|
|
||||||
define void @a() {
|
define void @a() {
|
||||||
; CHECK-LABEL: @a(
|
; CHECK-LABEL: @a(
|
||||||
; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([[T:%.*]], %T* @.body, i64 0, i32 0), align 8
|
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = load atomic i64, i64* bitcast (%T* @.body to i64*) acquire, align 8
|
|
||||||
; CHECK-NEXT: ret void
|
; CHECK-NEXT: ret void
|
||||||
;
|
;
|
||||||
%1 = tail call i8* @_Znwm(i64 8)
|
%1 = tail call i8* @_Znwm(i64 8)
|
||||||
|
|
Loading…
Reference in New Issue