ahatanak updated this revision to Diff 136895.
ahatanak added a comment.
Add a flag to OpaqeuValueExpr that indicates whether it is a unique reference
to its subexpression. If the flag is set, IRGen will avoid binding the OVE and
copying the result to the destination and instead just visit the OVE's
sub-expression.
The flag is set only when the PseudoObjectExpr is an assignment and the RHS is
an rvalue of a C++ class type, which is sufficient to fix the assertion failure
this patch is trying to fix.
https://reviews.llvm.org/D39562
Files:
include/clang/AST/Expr.h
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CodeGenFunction.h
lib/Sema/SemaPseudoObject.cpp
test/CodeGenObjCXX/property-dot-copy-elision.mm
test/CodeGenObjCXX/property-objects.mm
Index: test/CodeGenObjCXX/property-objects.mm
===================================================================
--- test/CodeGenObjCXX/property-objects.mm
+++ test/CodeGenObjCXX/property-objects.mm
@@ -72,7 +72,7 @@
// rdar://8379892
// CHECK-LABEL: define void @_Z1fP1A
-// CHECK: call void @_ZN1XC1Ev(%struct.X* [[LVTEMP:%[a-zA-Z0-9\.]+]])
+// CHECK: call void @_ZN1XC1Ev(%struct.X* [[LVTEMP:%.+]])
// CHECK: call void @_ZN1XC1ERKS_(%struct.X* [[AGGTMP:%[a-zA-Z0-9\.]+]], %struct.X* dereferenceable({{[0-9]+}}) [[LVTEMP]])
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.X*)*)({{.*}} %struct.X* [[AGGTMP]])
struct X {
Index: test/CodeGenObjCXX/property-dot-copy-elision.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/property-dot-copy-elision.mm
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++1z -fobjc-arc -o - %s | FileCheck %s
+
+struct S0 {
+ id f;
+};
+
+struct S1 {
+ S1();
+ S1(S0);
+ id f;
+};
+
+@interface C
+@property S1 f;
+@end
+@implementation C
+@end
+
+// CHECK-LABEL: define void @_Z5test0P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: %[[AGG_TMP_1:.*]] = alloca %[[STRUCT_S0:.*]], align
+// CHECK: call void @_ZN2S0C1Ev(%[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void @_ZN2S1C1E2S0(%[[STRUCT_S1]]* %[[AGG_TMP]], %[[STRUCT_S0]]* %[[AGG_TMP_1]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[AGG_TMP]])
+
+void test0(C *c) {
+ c.f = S0();
+}
+
+// CHECK: define void @_Z5test1P1C(
+// CHECK: %{{.*}} = alloca %
+// CHECK: %[[TEMP_LVALUE:.*]] = alloca %[[STRUCT_S1:.*]], align
+// CHECK: call void @_ZN2S1C1Ev(%[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_S1]]*)*)(i8* %{{.*}}, i8* %{{.*}}, %[[STRUCT_S1]]* %[[TEMP_LVALUE]])
+
+void test1(C *c) {
+ c.f = S1();
+}
Index: lib/Sema/SemaPseudoObject.cpp
===================================================================
--- lib/Sema/SemaPseudoObject.cpp
+++ lib/Sema/SemaPseudoObject.cpp
@@ -428,6 +428,9 @@
Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
OpaqueValueExpr *capturedRHS = capture(RHS);
+ if (capturedRHS->getType()->getAsCXXRecordDecl() && capturedRHS->isRValue())
+ capturedRHS->setIsUnique();
+
// In some very specific cases, semantic analysis of the RHS as an
// expression may require it to be rewritten. In these cases, we
// cannot safely keep the OVE around. Fortunately, we don't really
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2124,14 +2124,7 @@
/// getOpaqueLValueMapping - Given an opaque value expression (which
/// must be mapped to an l-value), return its mapping.
- const LValue &getOpaqueLValueMapping(const OpaqueValueExpr *e) {
- assert(OpaqueValueMapping::shouldBindAsLValue(e));
-
- llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
- it = OpaqueLValues.find(e);
- assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
- return it->second;
- }
+ LValue getOpaqueLValueMapping(const OpaqueValueExpr *e);
/// getOpaqueRValueMapping - Given an opaque value expression (which
/// must be mapped to an r-value), return its mapping.
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -606,7 +606,11 @@
}
void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
- EmitFinalDestCopy(e->getType(), CGF.getOpaqueLValueMapping(e));
+ // Avoid copying if OVE is a unique reference to its source expression.
+ if (e->isUnique())
+ Visit(e->getSourceExpr());
+ else
+ EmitFinalDestCopy(e->getType(), CGF.getOpaqueLValueMapping(e));
}
void
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -4170,6 +4170,18 @@
return getOpaqueLValueMapping(e);
}
+LValue CodeGenFunction::getOpaqueLValueMapping(const OpaqueValueExpr *e) {
+ assert(OpaqueValueMapping::shouldBindAsLValue(e));
+
+ if (e->isUnique())
+ return EmitLValue(e->getSourceExpr());
+
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
+ assert(it != OpaqueLValues.end() && "no mapping for opaque value!");
+ return it->second;
+}
+
RValue CodeGenFunction::EmitRValueForField(LValue LV,
const FieldDecl *FD,
SourceLocation Loc) {
@@ -4719,6 +4731,8 @@
// If this semantic expression is an opaque value, bind it
// to the result of its source expression.
if (const auto *ov = dyn_cast<OpaqueValueExpr>(semantic)) {
+ if (ov->isUnique())
+ continue;
// If this is the result expression, we may need to evaluate
// directly into the slot.
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -870,6 +870,10 @@
Expr *SourceExpr;
SourceLocation Loc;
+ /// This OVE is unique semantic reference to its source expressio if this bit
+ /// is set to true.
+ bool IsUnique = false;
+
public:
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
ExprObjectKind OK = OK_Ordinary,
@@ -925,6 +929,9 @@
/// place.
Expr *getSourceExpr() const { return SourceExpr; }
+ void setIsUnique() { IsUnique = true; }
+ bool isUnique() const { return IsUnique; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OpaqueValueExprClass;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits