From 48c70c1664aa4512cb7e08352dd8eb33dde4807c Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 16 Oct 2020 13:18:52 -0700 Subject: [PATCH] Extend memset-to-zero optimization to C++11 aggregate functional casts Aggr{...}. We previously missed these cases due to not stepping over the additional AST nodes representing their syntactic form. --- clang/lib/CodeGen/CGExprAgg.cpp | 6 ++++-- .../cxx11-initializer-aggregate.cpp | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 43e23d986ae0..625b9116ff25 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1759,7 +1759,9 @@ void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) /// non-zero bytes that will be stored when outputting the initializer for the /// specified initializer expression. static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { - E = E->IgnoreParens(); + if (auto *MTE = dyn_cast(E)) + E = MTE->getSubExpr(); + E = E->IgnoreParenNoopCasts(CGF.getContext()); // 0 and 0.0 won't require any non-zero stores! if (isSimpleZero(E, CGF)) return CharUnits::Zero(); @@ -1808,7 +1810,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { } } - + // FIXME: This overestimates the number of non-zero bytes for bit-fields. CharUnits NumNonZeroBytes = CharUnits::Zero(); for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) NumNonZeroBytes += GetNumNonZeroBytesInInit(ILE->getInit(i), CGF); diff --git a/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp index 6b10efd34f92..3e9d936a16f8 100644 --- a/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ b/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++17 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s struct A { int a, b; int f(); }; @@ -118,4 +119,24 @@ namespace ZeroInit { // This variable must be initialized elementwise. Filler data_e1[1024] = {}; // CHECK: getelementptr inbounds {{.*}} @_ZN8ZeroInit7data_e1E + + struct Largeish { + long a, b, c; + }; + // CHECK: define {{.*}}@_ZN8ZeroInit9largeish1Ev( + // CHECK-NOT } + // CHECK: call {{.*}}memset + Largeish largeish1() { return {}; } + // CHECK: define {{.*}}@_ZN8ZeroInit9largeish2Ev( + // CHECK-NOT } + // CHECK: call {{.*}}memset + Largeish largeish2() { return Largeish(); } + // CHECK: define {{.*}}@_ZN8ZeroInit9largeish3Ev( + // CHECK-NOT } + // CHECK: call {{.*}}memset + Largeish largeish3() { return Largeish{}; } + // CHECK: define {{.*}}@_ZN8ZeroInit9largeish4Ev( + // CHECK-NOT } + // CHECK: call {{.*}}memset + Largeish largeish4() { return (Largeish){}; } }