aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLogan Chien <loganchien@google.com>2013-11-06 23:32:34 +0800
committerLogan Chien <tzuhsiang.chien@gmail.com>2013-12-22 22:11:18 +0800
commitd45abfe98e4bdaf24d79014a8a982d827ab2d2da (patch)
tree13e3396f32d4a0b0438f9132cf08f31ef6ba9851
parent6c70b33496e49d1f0cf37c5a9ca4a660ed07bf71 (diff)
downloadllvm-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.cpp16
-rw-r--r--test/Transforms/GlobalOpt/disable-global-ctor-const-promotion.ll59
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
+}