[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