[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-25 Thread Alex Lorenz via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL311772: [IRGen] Evaluate constant static variables 
referenced through member (authored by arphaman).

Changed prior to commit:
  https://reviews.llvm.org/D36876?vs=112360=112675#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D36876

Files:
  cfe/trunk/lib/CodeGen/CGExpr.cpp
  cfe/trunk/lib/CodeGen/CGExprAgg.cpp
  cfe/trunk/lib/CodeGen/CGExprComplex.cpp
  cfe/trunk/lib/CodeGen/CGExprScalar.cpp
  cfe/trunk/lib/CodeGen/CodeGenFunction.h
  cfe/trunk/test/CodeGenCXX/member-expr-references-variable.cpp

Index: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
===
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp
@@ -124,24 +124,7 @@
   }
 
   // l-values.
-  void VisitDeclRefExpr(DeclRefExpr *E) {
-// For aggregates, we should always be able to emit the variable
-// as an l-value unless it's a reference.  This is due to the fact
-// that we can't actually ever see a normal l2r conversion on an
-// aggregate in C++, and in C there's no language standard
-// actively preventing us from listing variables in the captures
-// list of a block.
-if (E->getDecl()->getType()->isReferenceType()) {
-  if (CodeGenFunction::ConstantEmission result
-= CGF.tryEmitAsConstant(E)) {
-EmitFinalDestCopy(E->getType(), result.getReferenceLValue(CGF, E));
-return;
-  }
-}
-
-EmitAggLoadOfLValue(E);
-  }
-
+  void VisitDeclRefExpr(DeclRefExpr *E) { EmitAggLoadOfLValue(E); }
   void VisitMemberExpr(MemberExpr *ME) { EmitAggLoadOfLValue(ME); }
   void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); }
   void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); }
Index: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
===
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp
@@ -120,18 +120,22 @@
 return Visit(E->getSubExpr());
   }
 
+  ComplexPairTy emitConstant(const CodeGenFunction::ConstantEmission ,
+ Expr *E) {
+assert(Constant && "not a constant");
+if (Constant.isReference())
+  return EmitLoadOfLValue(Constant.getReferenceLValue(CGF, E),
+  E->getExprLoc());
+
+llvm::Constant *pair = Constant.getValue();
+return ComplexPairTy(pair->getAggregateElement(0U),
+ pair->getAggregateElement(1U));
+  }
 
   // l-values.
   ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
-if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
-  if (result.isReference())
-return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
-E->getExprLoc());
-
-  llvm::Constant *pair = result.getValue();
-  return ComplexPairTy(pair->getAggregateElement(0U),
-   pair->getAggregateElement(1U));
-}
+if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
+  return emitConstant(Constant, E);
 return EmitLoadOfLValue(E);
   }
   ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -141,7 +145,14 @@
 return CGF.EmitObjCMessageExpr(E).getComplexVal();
   }
   ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
-  ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
+  ComplexPairTy VisitMemberExpr(MemberExpr *ME) {
+if (CodeGenFunction::ConstantEmission Constant =
+CGF.tryEmitAsConstant(ME)) {
+  CGF.EmitIgnoredExpr(ME->getBase());
+  return emitConstant(Constant, ME);
+}
+return EmitLoadOfLValue(ME);
+  }
   ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
 if (E->isGLValue())
   return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h
===
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h
@@ -3161,6 +3161,7 @@
   };
 
   ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
+  ConstantEmission tryEmitAsConstant(const MemberExpr *ME);
 
   RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
 AggValueSlot slot = AggValueSlot::ignored());
Index: cfe/trunk/lib/CodeGen/CGExpr.cpp
===
--- cfe/trunk/lib/CodeGen/CGExpr.cpp
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp
@@ -1339,6 +1339,25 @@
   return ConstantEmission::forValue(C);
 }
 
+static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction ,
+const MemberExpr *ME) {
+  if (auto *VD = dyn_cast(ME->getMemberDecl())) {
+// Try to emit static variable member expressions as DREs.
+return 

[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-23 Thread John McCall via Phabricator via cfe-commits
rjmccall accepted this revision.
rjmccall added a comment.
This revision is now accepted and ready to land.

Looks great, thanks.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-23 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 112360.
arphaman marked 2 inline comments as done.
arphaman added a comment.

- Create `tryEmitAsConstant` for MemberExprs and `emitConstant` helper for 
complex values as suggested by John.
- Remove dead constant emission code from CGExprAggregate.cpp
- Emit static variable member expressions as DREs when emitting Lvalues to 
ensure the IR is consistent between DREs and MEs that reference a constant 
static variables whose type is a reference to an aggregate


Repository:
  rL LLVM

https://reviews.llvm.org/D36876

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCXX/member-expr-references-variable.cpp

Index: test/CodeGenCXX/member-expr-references-variable.cpp
===
--- /dev/null
+++ test/CodeGenCXX/member-expr-references-variable.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Agg { const char * x; const char * y; constexpr Agg() : x(0), y(0) {} };
+
+struct Struct {
+   constexpr static const char *name = "foo";
+
+   constexpr static __complex float complexValue = 42.0;
+
+   static constexpr const Agg  = Agg();
+
+   Struct();
+   Struct(int x);
+};
+
+void use(int n, const char *c);
+
+Struct *getPtr();
+
+// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+
+void scalarStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::name);
+// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  Struct s;
+  use(2, s.name);
+// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(3, ptr->name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(4, ref.name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(5, Struct(2).name);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(6, getPtr()->name);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+}
+
+void use(int n, __complex float v);
+
+void complexStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce0:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce0]].{{.*}}, align 4
+// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>*
+// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4
+// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]])
+  Struct s;
+  use(2, s.complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce1:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce1]].{{.*}}, align 4
+// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>*
+// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4
+// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]])
+  use(3, ptr->complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce2:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce2]].{{.*}}, align 4
+// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>*
+// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4
+// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]])
+  use(4, ref.complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce3:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce3]].{{.*}}, align 4
+// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>*
+// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4
+// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]])
+  use(5, Struct(2).complexValue);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: store float 4.20e+01, float* %[[coerce4:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce4]].{{.*}}, align 4
+// CHECK: %[[cast4:.*]] = bitcast { float, float }* %[[coerce4]] to <2 x float>*
+// CHECK: %[[vector4:.*]] = load <2 x float>, <2 x float>* %[[cast4]], align 4
+// CHECK: call void @_Z3useiCf(i32 5, <2 x 

[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-23 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: lib/CodeGen/CGExprComplex.cpp:163
+else
+  CGF.EmitLValue(ME->getBase());
+return *Constant;

rjmccall wrote:
> rjmccall wrote:
> > There's an EmitIgnoredExpr you could use.
> > 
> > Also, I think it would be fine to add a generic tryEmitMemberExprAsConstant 
> > that takes a MemberExpr and does this DRE stuff behind the scenes; it's not 
> > at all different for the different emitters.
> Well, actually, now I see why it's different for the complex emitter, but I 
> think you could probably extract out a function that forms a complex pair 
> from a constant output without too much trouble.
> 
> Also, as long as you're working with this, I think it's likely that the Agg 
> emitter needs to handle this, too.  I'm not sure I accept the claim there 
> that constant r-value emission never applies to aggregates, but at the very 
> least you need to handle references just as the DRE case does.
It looks like that constant reference code in Agg emitter is dead, so I removed 
it. 

The static constant variables that were references to aggregates were still 
inconsistent between DREs and MEs, so I now try to emit MEs as DREs in 
CodeGenFunction's Lvalue emitter now.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-22 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/CodeGen/CGExprComplex.cpp:163
+else
+  CGF.EmitLValue(ME->getBase());
+return *Constant;

rjmccall wrote:
> There's an EmitIgnoredExpr you could use.
> 
> Also, I think it would be fine to add a generic tryEmitMemberExprAsConstant 
> that takes a MemberExpr and does this DRE stuff behind the scenes; it's not 
> at all different for the different emitters.
Well, actually, now I see why it's different for the complex emitter, but I 
think you could probably extract out a function that forms a complex pair from 
a constant output without too much trouble.

Also, as long as you're working with this, I think it's likely that the Agg 
emitter needs to handle this, too.  I'm not sure I accept the claim there that 
constant r-value emission never applies to aggregates, but at the very least 
you need to handle references just as the DRE case does.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-22 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/CodeGen/CGExprComplex.cpp:163
+else
+  CGF.EmitLValue(ME->getBase());
+return *Constant;

There's an EmitIgnoredExpr you could use.

Also, I think it would be fine to add a generic tryEmitMemberExprAsConstant 
that takes a MemberExpr and does this DRE stuff behind the scenes; it's not at 
all different for the different emitters.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-22 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 112149.
arphaman added a comment.

Revert most of the changes and use temporary DREs as suggested by John.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876

Files:
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprScalar.cpp
  test/CodeGenCXX/member-expr-references-variable.cpp

Index: test/CodeGenCXX/member-expr-references-variable.cpp
===
--- /dev/null
+++ test/CodeGenCXX/member-expr-references-variable.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Struct {
+   constexpr static const char *name = "foo";
+
+   constexpr static __complex float complexValue = 42.0;
+
+   Struct();
+   Struct(int x);
+};
+
+void use(int n, const char *c);
+
+Struct *getPtr();
+
+// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+
+void scalarStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::name);
+// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  Struct s;
+  use(2, s.name);
+// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(3, ptr->name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(4, ref.name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(5, Struct(2).name);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(6, getPtr()->name);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+}
+
+void use(int n, __complex float v);
+
+void complexStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce0:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce0]].{{.*}}, align 4
+// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>*
+// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4
+// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]])
+  Struct s;
+  use(2, s.complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce1:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce1]].{{.*}}, align 4
+// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>*
+// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4
+// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]])
+  use(3, ptr->complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce2:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce2]].{{.*}}, align 4
+// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>*
+// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4
+// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]])
+  use(4, ref.complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce3:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce3]].{{.*}}, align 4
+// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>*
+// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4
+// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]])
+  use(5, Struct(2).complexValue);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: store float 4.20e+01, float* %[[coerce4:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce4]].{{.*}}, align 4
+// CHECK: %[[cast4:.*]] = bitcast { float, float }* %[[coerce4]] to <2 x float>*
+// CHECK: %[[vector4:.*]] = load <2 x float>, <2 x float>* %[[cast4]], align 4
+// CHECK: call void @_Z3useiCf(i32 5, <2 x float> %[[vector4]])
+  use(6, getPtr()->complexValue);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: store float 4.20e+01, float* %[[coerce5:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce5]].{{.*}}, align 4
+// CHECK: %[[cast5:.*]] = bitcast { float, float }* %[[coerce5]] to <2 x float>*
+// CHECK: %[[vector5:.*]] = load <2 x float>, <2 x float>* %[[cast5]], align 4
+// CHECK: call void @_Z3useiCf(i32 6, <2 x float> %[[vector5]])
+}
Index: lib/CodeGen/CGExprScalar.cpp

[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-22 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: lib/CodeGen/CGExpr.cpp:1323
+  if (result.HasSideEffects && !AllowSideEffects) {
+assert(!isa(E) && "declrefs should not have side effects");
 return ConstantEmission();

rjmccall wrote:
> The side effects here are those associated with the initializer of the 
> referenced declaration, not the DRE itself.  Some expressions can be 
> constant-evaluated despite having side-effects because the side-effects occur 
> in an ignored operand, like the LHS of a comma or the base of a MemberExpr 
> that refers to a static member.
> 
> We can't allow side effects here because (1) we're not actually collecting 
> the side-effectful expressions to emit and (2) we'd need some permission from 
> the context to decide that we're allowed to do so anyway (with a lambda 
> capture, those side-effects have actually already been emitted, but I'm not 
> convinced that's always true).
> 
> On the other hand, I think we need to be able to emit MemberExprs to static 
> members as constants despite the presence of side-effects in their base 
> expressions, and I can't think of any reasonable way to do that except 
> actually making a temporary DeclRefExpr to try to constant-emit instead.
Thanks, I think I understand your explanation.

I will try using temporary a DRE instead when a static variable is used in a 
member expression. That means that the old integer field evaluation code will 
have to stay though.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-22 Thread John McCall via Phabricator via cfe-commits
rjmccall added inline comments.



Comment at: lib/CodeGen/CGExpr.cpp:1323
+  if (result.HasSideEffects && !AllowSideEffects) {
+assert(!isa(E) && "declrefs should not have side effects");
 return ConstantEmission();

The side effects here are those associated with the initializer of the 
referenced declaration, not the DRE itself.  Some expressions can be 
constant-evaluated despite having side-effects because the side-effects occur 
in an ignored operand, like the LHS of a comma or the base of a MemberExpr that 
refers to a static member.

We can't allow side effects here because (1) we're not actually collecting the 
side-effectful expressions to emit and (2) we'd need some permission from the 
context to decide that we're allowed to do so anyway (with a lambda capture, 
those side-effects have actually already been emitted, but I'm not convinced 
that's always true).

On the other hand, I think we need to be able to emit MemberExprs to static 
members as constants despite the presence of side-effects in their base 
expressions, and I can't think of any reasonable way to do that except actually 
making a temporary DeclRefExpr to try to constant-emit instead.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-21 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 111956.
arphaman marked an inline comment as done.
arphaman added a comment.

- Get rid of the `AllowSideEffects` argument.
- Get rid of the old integer field evaluation code.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCXX/member-expr-references-variable.cpp
  test/CodeGenCXX/temporaries.cpp

Index: test/CodeGenCXX/temporaries.cpp
===
--- test/CodeGenCXX/temporaries.cpp
+++ test/CodeGenCXX/temporaries.cpp
@@ -673,18 +673,20 @@
 vi4b w;
   };
   // CHECK: alloca
-  // CHECK: extractelement
-  // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE_
+  // CHECK: store i32 0, i32* @_ZGRN6Vector1rE_
   // CHECK: store i32* @_ZGRN6Vector1rE_, i32** @_ZN6Vector1rE,
   int & = S().v[1];
 
   // CHECK: alloca
-  // CHECK: extractelement
-  // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE_
+  // CHECK: store i32 0, i32* @_ZGRN6Vector1sE_
   // CHECK: store i32* @_ZGRN6Vector1sE_, i32** @_ZN6Vector1sE,
   int & = S().w[1];
-  // FIXME PR16204: The following code leads to an assertion in Sema.
-  //int & = S().w.y;
+
+  // CHECK: alloca
+  // CHECK: extractelement
+  // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector2s2E_
+  // CHECK: store i32* @_ZGRN6Vector2s2E_, i32** @_ZN6Vector2s2E,
+  int & = S().w.y;
 }
 
 namespace ImplicitTemporaryCleanup {
Index: test/CodeGenCXX/member-expr-references-variable.cpp
===
--- /dev/null
+++ test/CodeGenCXX/member-expr-references-variable.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Struct {
+   constexpr static const char *name = "foo";
+
+   constexpr static __complex float complexValue = 42.0;
+
+   Struct();
+   Struct(int x);
+};
+
+void use(int n, const char *c);
+
+Struct *getPtr();
+
+// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+
+void scalarStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::name);
+// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  Struct s;
+  use(2, s.name);
+// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(3, ptr->name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(4, ref.name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(5, Struct(2).name);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(6, getPtr()->name);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+}
+
+void use(int n, __complex float v);
+
+void complexStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce0:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce0]].{{.*}}, align 4
+// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>*
+// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4
+// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]])
+  Struct s;
+  use(2, s.complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce1:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce1]].{{.*}}, align 4
+// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>*
+// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4
+// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]])
+  use(3, ptr->complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce2:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce2]].{{.*}}, align 4
+// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>*
+// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4
+// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]])
+  use(4, ref.complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce3:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce3]].{{.*}}, align 4
+// CHECK: 

[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-21 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: lib/CodeGen/CGExprComplex.cpp:156
+auto Constant = tryEmitDeclRefOrMemberExprAsConstant(
+ME, ME->getMemberDecl(), /*AllowSideEffects=*/true);
+if (Constant) {

rsmith wrote:
> If we can (correctly) allow side-effects in the initializer here, why can we 
> not also do so when emitting a `DeclRefExpr`?
I think that DREs can't have side-effects in any case, so I think I can remove 
that argument.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-18 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added inline comments.



Comment at: lib/CodeGen/CGExprComplex.cpp:156
+auto Constant = tryEmitDeclRefOrMemberExprAsConstant(
+ME, ME->getMemberDecl(), /*AllowSideEffects=*/true);
+if (Constant) {

If we can (correctly) allow side-effects in the initializer here, why can we 
not also do so when emitting a `DeclRefExpr`?



Comment at: lib/CodeGen/CGExprScalar.cpp:1314-1321
+  } else {
+// Fields can evaluate to constants if their base can be evaluated.
+llvm::APSInt Value;
+if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects))
+  V = Builder.getInt(Value);
+else
+  V = nullptr;

Can we remove this and just use `tryEmit...` unconditionally?


Repository:
  rL LLVM

https://reviews.llvm.org/D36876



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36876: [IRGen] Evaluate constant static variables referenced through member expressions

2017-08-18 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman created this revision.

C++ allows us to reference static variables through member expressions. Prior 
to this patch, non-integer static variables that were referenced using a member 
expression were always emitted using lvalue loads. The old behaviour introduced 
an inconsistency between regular uses of static variables and member 
expressions uses, for example, the following program compiled and linked 
successfully:

  struct Foo {
 constexpr static const char *name = "foo";
  };
  int main() {
return Foo::name[0] == 'f';
  }

but this program failed to link because "Foo::name" wasn't found:

  struct Foo {
 constexpr static const char *name = "foo";
  };
  int main() {
Foo f;
return f.name[0] == 'f';
  }

This patch ensures that static variables referenced through member expressions 
are emitted in the same way as ordinary static variable references.

rdar://33942261


Repository:
  rL LLVM

https://reviews.llvm.org/D36876

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCXX/member-expr-references-variable.cpp

Index: test/CodeGenCXX/member-expr-references-variable.cpp
===
--- /dev/null
+++ test/CodeGenCXX/member-expr-references-variable.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Struct {
+   constexpr static const char *name = "foo";
+
+   constexpr static __complex float complexValue = 42.0;
+
+   Struct();
+   Struct(int x);
+};
+
+void use(int n, const char *c);
+
+Struct *getPtr();
+
+// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+
+void scalarStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::name);
+// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  Struct s;
+  use(2, s.name);
+// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(3, ptr->name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(4, ref.name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(5, Struct(2).name);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(6, getPtr()->name);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+}
+
+void use(int n, __complex float v);
+
+void complexStaticVariableInMemberExpr(Struct *ptr, Struct ) {
+  use(1, Struct::complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce0:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce0]].{{.*}}, align 4
+// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>*
+// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4
+// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]])
+  Struct s;
+  use(2, s.complexValue);
+// CHECK: store float 4.20e+01, float* %[[coerce1:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce1]].{{.*}}, align 4
+// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>*
+// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4
+// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]])
+  use(3, ptr->complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce2:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce2]].{{.*}}, align 4
+// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>*
+// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4
+// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]])
+  use(4, ref.complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.20e+01, float* %[[coerce3:.*]].{{.*}}, align 4
+// CHECK: store float 0.00e+00, float* %[[coerce3]].{{.*}}, align 4
+// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>*
+// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4
+// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]])
+  use(5, Struct(2).complexValue);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: store float 4.20e+01,