Author: Richard Smith Date: 2020-10-16T16:48:22-07:00 New Revision: d4aac67859640bdb7e8ed3123a00c3f200f89b9c
URL: https://github.com/llvm/llvm-project/commit/d4aac67859640bdb7e8ed3123a00c3f200f89b9c DIFF: https://github.com/llvm/llvm-project/commit/d4aac67859640bdb7e8ed3123a00c3f200f89b9c.diff LOG: Make the check for whether we should memset(0) an aggregate initialization a little smarter. Look through casts that preserve zero-ness when determining if an initializer is zero, so that we can handle cases like an {0} initializer whose corresponding field is a type other than 'int'. Added: Modified: clang/lib/CodeGen/CGExprAgg.cpp clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 625b9116ff25..bf7c1adb6810 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1372,11 +1372,109 @@ void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddress(), T)); } +/// Determine whether the given cast kind is known to always convert values +/// with all zero bits in their value representation to values with all zero +/// bits in their value representation. +static bool castPreservesZero(const CastExpr *CE) { + switch (CE->getCastKind()) { + // No-ops. + case CK_NoOp: + case CK_UserDefinedConversion: + case CK_ConstructorConversion: + case CK_BitCast: + case CK_ToUnion: + case CK_ToVoid: + // Conversions between (possibly-complex) integral, (possibly-complex) + // floating-point, and bool. + case CK_BooleanToSignedIntegral: + case CK_FloatingCast: + case CK_FloatingComplexCast: + case CK_FloatingComplexToBoolean: + case CK_FloatingComplexToIntegralComplex: + case CK_FloatingComplexToReal: + case CK_FloatingRealToComplex: + case CK_FloatingToBoolean: + case CK_FloatingToIntegral: + case CK_IntegralCast: + case CK_IntegralComplexCast: + case CK_IntegralComplexToBoolean: + case CK_IntegralComplexToFloatingComplex: + case CK_IntegralComplexToReal: + case CK_IntegralRealToComplex: + case CK_IntegralToBoolean: + case CK_IntegralToFloating: + // Reinterpreting integers as pointers and vice versa. + case CK_IntegralToPointer: + case CK_PointerToIntegral: + // Language extensions. + case CK_VectorSplat: + case CK_NonAtomicToAtomic: + case CK_AtomicToNonAtomic: + return true; + + case CK_BaseToDerivedMemberPointer: + case CK_DerivedToBaseMemberPointer: + case CK_MemberPointerToBoolean: + case CK_NullToMemberPointer: + case CK_ReinterpretMemberPointer: + // FIXME: ABI-dependent. + return false; + + case CK_AnyPointerToBlockPointerCast: + case CK_BlockPointerToObjCPointerCast: + case CK_CPointerToObjCPointerCast: + case CK_ObjCObjectLValueCast: + case CK_IntToOCLSampler: + case CK_ZeroToOCLOpaqueType: + // FIXME: Check these. + return false; + + case CK_FixedPointCast: + case CK_FixedPointToBoolean: + case CK_FixedPointToFloating: + case CK_FixedPointToIntegral: + case CK_FloatingToFixedPoint: + case CK_IntegralToFixedPoint: + // FIXME: Do all fixed-point types represent zero as all 0 bits? + return false; + + case CK_AddressSpaceConversion: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_Dynamic: + case CK_NullToPointer: + case CK_PointerToBoolean: + // FIXME: Preserves zeroes only if zero pointers and null pointers have the + // same representation in all involved address spaces. + return false; + + case CK_ARCConsumeObject: + case CK_ARCExtendBlockObject: + case CK_ARCProduceObject: + case CK_ARCReclaimReturnedObject: + case CK_CopyAndAutoreleaseBlockObject: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_BuiltinFnToFnPtr: + case CK_Dependent: + case CK_LValueBitCast: + case CK_LValueToRValue: + case CK_LValueToRValueBitCast: + case CK_UncheckedDerivedToBase: + return false; + } +} + /// isSimpleZero - If emitting this value will obviously just cause a store of /// zero to memory, return true. This can return false if uncertain, so it just /// handles simple cases. static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) { E = E->IgnoreParens(); + while (auto *CE = dyn_cast<CastExpr>(E)) { + if (!castPreservesZero(CE)) + break; + E = CE->getSubExpr()->IgnoreParens(); + } // 0 if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) diff --git a/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp index 3e9d936a16f8..fb7e82d929d6 100644 --- a/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ b/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -139,4 +139,35 @@ namespace ZeroInit { // CHECK-NOT } // CHECK: call {{.*}}memset Largeish largeish4() { return (Largeish){}; } + // CHECK: define {{.*}}@_ZN8ZeroInit9largeish5Ev( + // CHECK-NOT } + // CHECK: call {{.*}}memset + Largeish largeish5() { return {0, 0, 0}; } + + typedef __attribute__((ext_vector_type(4))) char CI4; + struct Conversions { + _Complex int a; + _Complex float b; + short c; + long double d; + CI4 e; + char f; + char g; + int *h; + long i; + }; + // CHECK: define {{.*}}@_ZN8ZeroInit11conversionsEv( + // CHECK-NOT } + // CHECK: call {{.*}}memset + Conversions conversions() { + return {0, + 0, + 0, + 0, + CI4(0), + static_cast<char>(0.0), + char(0 + 0i), + reinterpret_cast<int *>(0), + reinterpret_cast<long>((int *)nullptr)}; + } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits