[llvm] de24d08 - [FuncSpec] Fix inconsistent treatment of global variables

Momchil Velikov via llvm-commits llvm-commits at lists.llvm.org
Fri May 5 01:56:24 PDT 2023


Author: Momchil Velikov
Date: 2023-05-05T09:56:06+01:00
New Revision: de24d084597a819992bc2e769b88597c9e28b47c

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

LOG: [FuncSpec] Fix inconsistent treatment of global variables

There are a few inaccuracies with how FuncSpec handles global
variables.

When specialisation on non-const global variables is disabled (the
default) the pass could nevertheless perform some specializations,
e.g. on a constant GEP expression, or on a SSA variable, for which the
Solver has determined it has the value of a global variable.

When specialisation on non-const global variables is enabled, the pass
would skip non-scalars, e.g. a global array, but this should be
completely inconsequential, a pointer is a pointer.

Reviewed By: SjoerdMeijer

Differential Revision: https://reviews.llvm.org/D149476

Change-Id: Ic73051b2f8602587306760bf2ec552e5860f8d39

Added: 
    llvm/test/Transforms/FunctionSpecialization/global-var-constants.ll

Modified: 
    llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
    llvm/test/Transforms/FunctionSpecialization/compiler-crash-promote-alloca.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 379211316b95a..3549eec4853c9 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -53,6 +53,7 @@
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/ValueLattice.h"
 #include "llvm/Analysis/ValueLatticeUtils.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/Transforms/Scalar/SCCP.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -732,22 +733,19 @@ Constant *FunctionSpecializer::getCandidateConstant(Value *V) {
   if (isa<PoisonValue>(V))
     return nullptr;
 
-  // TrackValueOfGlobalVariable only tracks scalar global variables.
-  if (auto *GV = dyn_cast<GlobalVariable>(V)) {
-    // Check if we want to specialize on the address of non-constant
-    // global values.
-    if (!GV->isConstant() && !SpecializeOnAddress)
-      return nullptr;
-
-    if (!GV->getValueType()->isSingleValueType())
-      return nullptr;
-  }
-
   // Select for possible specialisation values that are constants or
   // are deduced to be constants or constant ranges with a single element.
   Constant *C = dyn_cast<Constant>(V);
   if (!C)
     C = Solver.getConstantOrNull(V);
+
+  // Don't specialize on (anything derived from) the address of a non-constant
+  // global variable, unless explicitly enabled.
+  if (C && C->getType()->isPointerTy() && !C->isNullValue())
+    if (auto *GV = dyn_cast<GlobalVariable>(getUnderlyingObject(C));
+        GV && !(GV->isConstant() || SpecializeOnAddress))
+      return nullptr;
+
   return C;
 }
 

diff  --git a/llvm/test/Transforms/FunctionSpecialization/compiler-crash-promote-alloca.ll b/llvm/test/Transforms/FunctionSpecialization/compiler-crash-promote-alloca.ll
index 4d00d7a284ab7..fff454db303c9 100644
--- a/llvm/test/Transforms/FunctionSpecialization/compiler-crash-promote-alloca.ll
+++ b/llvm/test/Transforms/FunctionSpecialization/compiler-crash-promote-alloca.ll
@@ -4,7 +4,7 @@
 ; while attempting to promote the alloca in `entry`.
 ; CHECK: bar.1
 
- at block = internal global [8 x i8] zeroinitializer, align 1
+ at block = internal constant [8 x i8] zeroinitializer, align 1
 
 define dso_local void @entry() {
   %1 = alloca i32, align 4

diff  --git a/llvm/test/Transforms/FunctionSpecialization/global-var-constants.ll b/llvm/test/Transforms/FunctionSpecialization/global-var-constants.ll
new file mode 100644
index 0000000000000..14c4855b58a24
--- /dev/null
+++ b/llvm/test/Transforms/FunctionSpecialization/global-var-constants.ll
@@ -0,0 +1,78 @@
+; RUN:  opt -S --passes=ipsccp,deadargelim --force-specialization                       < %s | FileCheck %s --check-prefix=NO-GLOBALS
+; RUN:  opt -S --passes=ipsccp,deadargelim --force-specialization --funcspec-on-address < %s | FileCheck %s --check-prefix=GLOBALS
+ at G = global [10 x i32] zeroinitializer, align 4
+
+define internal i32 @f(ptr %p) noinline {
+entry:
+  %0 = load i32, ptr %p, align 4
+  store i32 0, ptr %p, align 4
+  ret i32 %0
+}
+
+define internal i32 @g(i32 %x, i32 %y, ptr %p) noinline {
+entry:
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  br label %if.end
+
+if.else:
+  br label %if.end
+
+if.end:
+  %x.addr.0 = phi i32 [ %x, %if.then ], [ 11, %if.else ]
+  %p.addr.0 = phi ptr [ @G, %if.then ], [ %p, %if.else ]
+  %call = call i32 @f(ptr %p.addr.0)
+  %add = add nsw i32 %call, %x.addr.0
+  ret i32 %add
+}
+
+define i32 @h0(ptr %p) {
+entry:
+  %call = call i32 @g(i32 2, i32 1, ptr %p)
+  ret i32 %call
+}
+
+define i32 @h1() {
+entry:
+  %call = call i32 @f(ptr @G)
+  ret i32 %call
+}
+
+define i32 @h2() {
+entry:
+  %call = call i32 @f(ptr getelementptr inbounds (i32, ptr @G, i64 1))
+  ret i32 %call
+}
+
+; Check if specialisation on the address of a non-const global variable
+; is not allowed, then it is not performed.
+
+; NO-GLOBALS-LABEL: define internal i32 @g()
+; NO-GLOBALS: call i32 @f(ptr @G)
+
+; NO-GLOBALS-LABEL: define i32 @h0(ptr %p)
+; NO-GLOBALS:call i32 @g()
+
+; NO-GLOBALS-LABEL: define i32 @h1()
+; NO-GLOBALS: call i32 @f(ptr @G)
+
+; NO-GLOBALS-LABEL: define i32 @h2()
+; NO-GLOBALS: call i32 @f(ptr getelementptr inbounds (i32, ptr @G, i64 1))
+
+; Check if specialisation on the address of a non-const global variable
+; is allowed, then it is performed where possible.
+
+; GLOBALS-LABEL: define internal i32 @g()
+; GLOBALS: call i32 @f.2()
+
+; GLOBALS-LABEL: define i32 @h0(ptr %p)
+; GLOBALS: call i32 @g()
+
+; GLOBALS-LABEL: define i32 @h1()
+; GLOBALS: call i32 @f.2()
+
+; GLOBALS-LABEL: define i32 @h2()
+; GLOBALS: call i32 @f.1()
+


        


More information about the llvm-commits mailing list