diff options
author | Logan Chien <loganchien@google.com> | 2013-11-06 23:32:34 +0800 |
---|---|---|
committer | Logan Chien <tzuhsiang.chien@gmail.com> | 2013-12-22 22:11:18 +0800 |
commit | d45abfe98e4bdaf24d79014a8a982d827ab2d2da (patch) | |
tree | 13e3396f32d4a0b0438f9132cf08f31ef6ba9851 | |
parent | 6c70b33496e49d1f0cf37c5a9ca4a660ed07bf71 (diff) | |
download | llvm-d45abfe98e4bdaf24d79014a8a982d827ab2d2da.tar.gz |
[ndk] Add -disable-global-ctor-const-promotion option.
The global variable optimization will try to evaluate the
constant global variable and remove the constructors.
However, some legacy code will try to perform const_cast<>()
and assign to the "constant" to avoid static initialization
order fiasco. To workaround those old code, this commit
adds a new option to disable the promotion of the global
constant with constructors.
Change-Id: If5146f1ebc9139008b5899cd474c5f57aef0697a
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 16 | ||||
-rw-r--r-- | test/Transforms/GlobalOpt/disable-global-ctor-const-promotion.ll | 59 |
2 files changed, 71 insertions, 4 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 2ea89a16d86..031d0fdc105 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/Operator.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/GetElementPtrTypeIterator.h" @@ -61,6 +62,12 @@ STATISTIC(NumAliasesResolved, "Number of global aliases resolved"); STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated"); STATISTIC(NumCXXDtorsRemoved, "Number of global C++ destructors removed"); +static cl::opt<bool> DisableGlobalCtorConstPromotion( + "disable-global-ctor-const-promotion", + cl::desc("Disable constant promotion of global constants with constructors."), + cl::init(false), + cl::Hidden); + namespace { struct GlobalOpt : public ModulePass { virtual void getAnalysisUsage(AnalysisUsage &AU) const { @@ -2796,10 +2803,11 @@ static bool EvaluateStaticConstructor(Function *F, const DataLayout *TD, Eval.getMutatedMemory().begin(), E = Eval.getMutatedMemory().end(); I != E; ++I) CommitValueTo(I->second, I->first); - for (SmallPtrSet<GlobalVariable*, 8>::const_iterator I = - Eval.getInvariants().begin(), E = Eval.getInvariants().end(); - I != E; ++I) - (*I)->setConstant(true); + if (!DisableGlobalCtorConstPromotion) + for (SmallPtrSet<GlobalVariable*, 8>::const_iterator I = + Eval.getInvariants().begin(), E = Eval.getInvariants().end(); + I != E; ++I) + (*I)->setConstant(true); } return EvalSuccess; diff --git a/test/Transforms/GlobalOpt/disable-global-ctor-const-promotion.ll b/test/Transforms/GlobalOpt/disable-global-ctor-const-promotion.ll new file mode 100644 index 00000000000..eeee3d30ebc --- /dev/null +++ b/test/Transforms/GlobalOpt/disable-global-ctor-const-promotion.ll @@ -0,0 +1,59 @@ +; Test -disable-global-ctor-const-promotion +; +; The global variable optimization will try to evaluate the constant +; global variable and remove the constructors. +; +; However, some legacy code will try to perform const_cast<>() and +; assign to the "constant" to avoid static initialization order fiasco. +; To workaround those old code, we would like to provide an option to +; disable this optimization. +; +; This test will check whether the -disable-global-ctor-const-promotion +; is working as expected or not. + +; RUN: opt < %s -globalopt -S -o - | FileCheck %s --check-prefix=CHECK-DEFAULT +; RUN: opt < %s -globalopt -disable-global-ctor-const-promotion -S -o - \ +; RUN: | FileCheck %s --check-prefix=CHECK-DISABLE + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%class.ConstantValue = type { i32 } + +@_ZL3one = internal global %class.ConstantValue zeroinitializer, align 4 +; CHECK-DEFAULT: @_ZL3one = internal constant %class.ConstantValue { i32 1 }, align 4 +; CHECK-DISABLE: @_ZL3one = internal global %class.ConstantValue { i32 1 }, align 4 + +@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] + +@_ZN13ConstantValueC1Ei = alias weak_odr void (%class.ConstantValue*, i32)* @_ZN13ConstantValueC2Ei + +define internal void @__cxx_global_var_init() section ".text.startup" { +entry: + call void @_ZN13ConstantValueC1Ei(%class.ConstantValue* @_ZL3one, i32 1) + %0 = call {}* @llvm.invariant.start(i64 4, i8* bitcast (%class.ConstantValue* @_ZL3one to i8*)) + ret void +} + +declare {}* @llvm.invariant.start(i64, i8* nocapture) nounwind + +define void @_Z3barv() nounwind uwtable { +entry: + call void @_Z3fooRK13ConstantValue(%class.ConstantValue* @_ZL3one) nounwind + ret void +} + +declare void @_Z3fooRK13ConstantValue(%class.ConstantValue*) nounwind + +define linkonce_odr void @_ZN13ConstantValueC2Ei(%class.ConstantValue* %this, i32 %i) unnamed_addr nounwind uwtable align 2 { +entry: + %value_ = getelementptr inbounds %class.ConstantValue* %this, i32 0, i32 0 + store i32 %i, i32* %value_, align 4 + ret void +} + +define internal void @_GLOBAL__I_a() section ".text.startup" { +entry: + call void @__cxx_global_var_init() + ret void +} |