[clang] d4aac67 - Make the check for whether we should memset(0) an aggregate
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 16 16:48:33 PDT 2020
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)};
+ }
}
More information about the cfe-commits
mailing list