On Feb 16, 2012, at 11:31 PM, Richard Smith wrote: > Author: rsmith > Date: Fri Feb 17 01:31:37 2012 > New Revision: 150798 > > URL: http://llvm.org/viewvc/llvm-project?rev=150798&view=rev > Log: > The clang half of r150794: after the construction of a global or static const > variable ends, if the variable has a trivial destructor and no mutable > subobjects then emit an llvm.invariant.start call for it. globalopt knows to > make the variable const when evaluating this.
Hi Richard, We should only emit metadata like this when optimizations are enabled, not at -O0. -Chris > > Added: > cfe/trunk/test/CodeGenCXX/init-invariant.cpp > Modified: > cfe/trunk/lib/CodeGen/CGDeclCXX.cpp > > Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=150798&r1=150797&r2=150798&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Fri Feb 17 01:31:37 2012 > @@ -101,6 +101,19 @@ > CGF.EmitCXXGlobalDtorRegistration(function, argument); > } > > +/// Emit code to cause the variable at the given address to be considered as > +/// constant from this point onwards. > +static void EmitDeclInvariant(CodeGenFunction &CGF, llvm::Constant *Addr) { > + // Grab the llvm.invariant.start intrinsic. > + llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start; > + llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID); > + > + // Emit a call, with size -1 signifying the whole object. > + llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, -1), > + llvm::ConstantExpr::getBitCast(Addr, > CGF.Int8PtrTy)}; > + CGF.Builder.CreateCall(InvariantStart, Args); > +} > + > void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, > llvm::Constant *DeclPtr, > bool PerformInit) { > @@ -111,7 +124,10 @@ > if (!T->isReferenceType()) { > if (PerformInit) > EmitDeclInit(*this, D, DeclPtr); > - EmitDeclDestroy(*this, D, DeclPtr); > + if (CGM.isTypeConstant(D.getType(), true)) > + EmitDeclInvariant(*this, DeclPtr); > + else > + EmitDeclDestroy(*this, D, DeclPtr); > return; > } > > > Added: cfe/trunk/test/CodeGenCXX/init-invariant.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/init-invariant.cpp?rev=150798&view=auto > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/init-invariant.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/init-invariant.cpp Fri Feb 17 01:31:37 2012 > @@ -0,0 +1,60 @@ > +// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -o - | FileCheck %s > + > +// Check that we add an llvm.invariant.start to mark when a global becomes > +// read-only. If globalopt can fold the initializer, it will then mark the > +// variable as constant. > + > +struct A { > + A() : n(42) {} > + int n; > +}; > + > +// CHECK: @a = global {{.*}} zeroinitializer > +extern const A a = A(); > + > +struct B { > + B() : n(76) {} > + mutable int n; > +}; > + > +// CHECK: @b = global {{.*}} zeroinitializer > +extern const B b = B(); > + > +struct C { > + C() : n(81) {} > + ~C(); > + int n; > +}; > + > +// CHECK: @c = global {{.*}} zeroinitializer > +extern const C c = C(); > + > +int f() { return 5; } > +// CHECK: @d = global i32 0 > +extern const int d = f(); > + > +void e() { > + static const A a = A(); > +} > + > +// CHECK: define internal void @__cxx_global_var_init > +// CHECK: call void @_ZN1AC1Ev({{.*}}* @a) > +// CHECK-NEXT: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} > @a to i8*)) > + > +// CHECK: define internal void @__cxx_global_var_init > +// CHECK: call void @_ZN1BC1Ev({{.*}}* @b) > +// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} > @b to i8*)) > + > +// CHECK: define internal void @__cxx_global_var_init > +// CHECK: call void @_ZN1CC1Ev({{.*}}* @c) > +// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} > @c to i8*)) > + > +// CHECK: define internal void @__cxx_global_var_init > +// CHECK: call i32 @_Z1fv( > +// CHECK: store {{.*}}, i32* @d > +// CHECK: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} @d to > i8*)) > + > +// CHECK: define void @_Z1ev( > +// CHECK: call void @_ZN1AC1Ev(%struct.A* @_ZZ1evE1a) > +// CHECK: call {{.*}}@llvm.invariant.start(i64 -1, i8* bitcast ({{.*}} > @_ZZ1evE1a to i8*)) > +// CHECK-NOT: llvm.invariant.end > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
