[llvm] f3e8717 - [GlobalOpt] Support "stored once" optimization for different types

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 12 00:39:39 PST 2022


Author: Nikita Popov
Date: 2022-01-12T09:39:31+01:00
New Revision: f3e87176e1c58da7b61958eae679adb4bcdb7c41

URL: https://github.com/llvm/llvm-project/commit/f3e87176e1c58da7b61958eae679adb4bcdb7c41
DIFF: https://github.com/llvm/llvm-project/commit/f3e87176e1c58da7b61958eae679adb4bcdb7c41.diff

LOG: [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

Added: 
    llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index 6a2e173d6c0c..4cc00f181f5d 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -1672,11 +1672,25 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
     // 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);

diff  --git a/llvm/test/Transforms/GlobalOpt/stored-once-
diff erent-type.ll b/llvm/test/Transforms/GlobalOpt/stored-once-
diff erent-type.ll
new file mode 100644
index 000000000000..a4fac27e7f6e
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/stored-once-
diff erent-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
+}

diff  --git a/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll b/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll
index a0b0e6c1be01..a971f74f3d77 100644
--- a/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll
+++ b/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)


        


More information about the llvm-commits mailing list