From: Richard Smith Date: Fri, 2 Mar 2012 03:16:32 +0000 (+0000) Subject: PR12145: Avoid emitting loads of constexpr variables in contexts where there X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a3cac5b76a5243d8fca812d3a276950b0cfc56b6;p=clang PR12145: Avoid emitting loads of constexpr variables in contexts where there is no odr-use of the variable. Go slightly beyond what the standard requires for variables of reference type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151879 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 125e431bff..f7ab880e6c 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -212,18 +212,21 @@ public: // l-values. Value *VisitDeclRefExpr(DeclRefExpr *E) { Expr::EvalResult Result; - if (!E->EvaluateAsRValue(Result, CGF.getContext())) - return EmitLoadOfLValue(E); + bool IsReferenceConstant = false; + QualType EvalTy = E->getType(); + if (!E->EvaluateAsRValue(Result, CGF.getContext())) { + // If this is a reference, try to determine what it is bound to. + if (!E->getDecl()->getType()->isReferenceType() || + !E->EvaluateAsLValue(Result, CGF.getContext())) + return EmitLoadOfLValue(E); + + IsReferenceConstant = true; + EvalTy = E->getDecl()->getType(); + } assert(!Result.HasSideEffects && "Constant declref with side-effect?!"); - llvm::Constant *C; - if (Result.Val.isInt()) - C = Builder.getInt(Result.Val.getInt()); - else if (Result.Val.isFloat()) - C = llvm::ConstantFP::get(VMContext, Result.Val.getFloat()); - else - return EmitLoadOfLValue(E); + llvm::Constant *C = CGF.CGM.EmitConstantValue(Result.Val, EvalTy, &CGF); // Make sure we emit a debug reference to the global variable. if (VarDecl *VD = dyn_cast(E->getDecl())) { @@ -233,6 +236,9 @@ public: CGF.EmitDeclRefExprDbgValue(E, C); } + if (IsReferenceConstant) + return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(C, E->getType())); + return C; } Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) { diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 5366d6d485..776a1e12dd 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -337,3 +337,30 @@ namespace VirtualBase { X x; // CHECK: call {{.*}}@_ZN11VirtualBase1XINS_1DEEC1Ev } + +// PR12145 +namespace Unreferenced { + int n; + constexpr int *p = &n; + // We must not emit a load of 'p' here, since it's not odr-used. + int q = *p; + // CHECK-NOT: _ZN12Unreferenced1pE + // CHECK: %0 = load i32* @_ZN12Unreferenced1nE + // CHECK-NEXT: store i32 %0, i32* @_ZN12Unreferenced1qE + // CHECK-NOT: _ZN12Unreferenced1pE + + // Technically, we are not required to substitute variables of reference types + // initialized by constant expressions, because the special case for odr-use + // of variables in [basic.def.odr]p2 only applies to objects. But we do so + // anyway. + + constexpr int &r = n; + // CHECK-NOT: _ZN12Unreferenced1rE + int s = r; + + const int t = 1; + const int &rt = t; + int f(int); + int u = f(rt); + // CHECK: call i32 @_ZN12Unreferenced1fEi(i32 1) +}