diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp --- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp +++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @@ -81,6 +81,10 @@ cl::desc("Average loop iteration count cost"), cl::init(10)); +static cl::opt SpecializeOnAddresses( + "func-specialization-on-address", cl::init(false), cl::Hidden, + cl::desc("Enable function specialization on the address of global values")); + // TODO: This needs checking to see the impact on compile-times, which is why // this is off by default for now. static cl::opt EnableSpecializationForLiteralConstant( @@ -672,9 +676,16 @@ auto *V = CS.getArgOperand(A->getArgNo()); // TrackValueOfGlobalVariable only tracks scalar global variables. - if (auto *GV = dyn_cast(V)) + if (auto *GV = dyn_cast(V)) { + // Check if we want to specialize on the address of non-constant + // global values. + if (!GV->isConstant()) + if (!SpecializeOnAddresses) + return false; + if (!GV->getValueType()->isSingleValueType()) return false; + } if (isa(V) && (Solver.getLatticeValueFor(V).isConstant() || EnableSpecializationForLiteralConstant)) diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-nonconst-glob.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-nonconst-glob.ll --- a/llvm/test/Transforms/FunctionSpecialization/function-specialization-nonconst-glob.ll +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-nonconst-glob.ll @@ -1,8 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py + ; RUN: opt -function-specialization -force-function-specialization -S < %s | FileCheck %s +; RUN: opt -function-specialization -force-function-specialization -func-specialization-on-address=0 -S < %s | FileCheck %s +; RUN: opt -function-specialization -force-function-specialization -func-specialization-on-address=1 -S < %s | FileCheck %s --check-prefix=ON-ADDRESS + +; Global B is not constant. We do not specialise on addresses unless we +; enable that: -; Global B is not constant. We do specialise on this global, showing we -; specialise on its address. +; ON-ADDRESS: call i32 @foo.1(i32 %x, i32* @A) +; ON-ADDRESS: call i32 @foo.2(i32 %y, i32* @B) target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" @@ -18,7 +24,7 @@ ; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo.1(i32 [[X]], i32* @A) ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.else: -; CHECK-NEXT: [[CALL1:%.*]] = call i32 @foo.2(i32 [[Y:%.*]], i32* @B) +; CHECK-NEXT: [[CALL1:%.*]] = call i32 @foo(i32 [[Y:%.*]], i32* @B) ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: ; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL]], [[IF_THEN]] ], [ [[CALL1]], [[IF_ELSE]] ] @@ -42,7 +48,7 @@ } define internal i32 @foo(i32 %x, i32* %b) { -; CHECK-LABEL: @foo( +; CHECK-LABEL: define internal i32 @foo( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B:%.*]], align 4 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], [[TMP0]] @@ -61,9 +67,4 @@ ; CHECK-NEXT: ret i32 %add ; CHECK-NEXT: } -; CHECK-LABEL: define internal i32 @foo.2(i32 %x, i32* %b) { -; CHECK-NEXT: entry: -; CHECK-NEXT: %0 = load i32, i32* @B, align 4 -; CHECK-NEXT: %add = add nsw i32 %x, %0 -; CHECK-NEXT: ret i32 %add -; CHECK-NEXT: } +; CHECK-NOT: define internal i32 @foo.2(