[PATCH] D117034: [GlobalOpt] Support "stored once" optimization for different types

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 11 09:36:18 PST 2022


nikic created this revision.
Herald added subscribers: ormris, hiraditya.
nikic requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

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.


https://reviews.llvm.org/D117034

Files:
  llvm/lib/Transforms/IPO/GlobalOpt.cpp
  llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll
  llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll


Index: llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll
===================================================================
--- llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll
+++ llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll
@@ -8,13 +8,8 @@
 
 @0 = internal global %T* null
 
-;.
-; CHECK: @[[_BODY:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr global [[T:%.*]] undef
-;.
 define void @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
 ;
   %1 = tail call i8* @_Znwm(i64 8)
Index: llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll
@@ -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
+
+ at 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
+}
Index: llvm/lib/Transforms/IPO/GlobalOpt.cpp
===================================================================
--- llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -1672,11 +1672,25 @@
     // This is restricted to address spaces that allow globals to have
     // initializers. NVPTX, for example, does not support initializers for
     // shared memory (AS 3).
-    if (SOVConstant && SOVConstant->getType() == GV->getValueType() &&
-        isa<UndefValue>(GV->getInitializer()) &&
+    if (SOVConstant && isa<UndefValue>(GV->getInitializer()) &&
+        DL.getTypeAllocSize(SOVConstant->getType()) ==
+            DL.getTypeAllocSize(GV->getValueType()) &&
         CanHaveNonUndefGlobalInitializer) {
-      // Change the initial value here.
-      GV->setInitializer(SOVConstant);
+      if (SOVConstant->getType() == GV->getValueType()) {
+        // 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.
       CleanupConstantGlobalUsers(GV, DL);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D117034.398987.patch
Type: text/x-patch
Size: 3496 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220111/27c54221/attachment.bin>


More information about the llvm-commits mailing list