Author: Timm Baeder
Date: 2025-09-05T10:29:43+02:00
New Revision: 46f2b35a98ec53dbf5999c92bace40555abe0d9d

URL: 
https://github.com/llvm/llvm-project/commit/46f2b35a98ec53dbf5999c92bace40555abe0d9d
DIFF: 
https://github.com/llvm/llvm-project/commit/46f2b35a98ec53dbf5999c92bace40555abe0d9d.diff

LOG: [clang][bytecode][NFC] Remove instance pointer from emitDestruction 
(#157040)

We only call this when we just pushed a new pointer to the stack, so try
to save the folling PopPtr op by removing the pointer inside
emitDestruction directly, e.g. by letting the Call op just remove it.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/lib/AST/ByteCode/Compiler.h
    clang/lib/AST/ByteCode/Descriptor.cpp
    clang/lib/AST/ByteCode/Record.cpp
    clang/lib/AST/ByteCode/Record.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 3f30e524ab179..d4e10b32c470c 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6284,26 +6284,21 @@ bool Compiler<Emitter>::compileDestructor(const 
CXXDestructorDecl *Dtor) {
     // First, destroy all fields.
     for (const Record::Field &Field : llvm::reverse(R->fields())) {
       const Descriptor *D = Field.Desc;
-      if (!D->isPrimitive() && !D->isPrimitiveArray()) {
-        if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
-          return false;
-        if (!this->emitDestruction(D, SourceInfo{}))
-          return false;
-        if (!this->emitPopPtr(SourceInfo{}))
-          return false;
-      }
+      if (D->hasTrivialDtor())
+        continue;
+      if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
+        return false;
+      if (!this->emitDestructionPop(D, SourceInfo{}))
+        return false;
     }
   }
 
   for (const Record::Base &Base : llvm::reverse(R->bases())) {
-    if (Base.R->isAnonymousUnion())
+    if (Base.R->hasTrivialDtor())
       continue;
-
     if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
       return false;
-    if (!this->emitRecordDestruction(Base.R, {}))
-      return false;
-    if (!this->emitPopPtr(SourceInfo{}))
+    if (!this->emitRecordDestructionPop(Base.R, {}))
       return false;
   }
 
@@ -7200,71 +7195,56 @@ bool Compiler<Emitter>::emitComplexComparison(const 
Expr *LHS, const Expr *RHS,
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).
 template <class Emitter>
-bool Compiler<Emitter>::emitRecordDestruction(const Record *R, SourceInfo Loc) 
{
+bool Compiler<Emitter>::emitRecordDestructionPop(const Record *R,
+                                                 SourceInfo Loc) {
   assert(R);
-  assert(!R->isAnonymousUnion());
+  assert(!R->hasTrivialDtor());
   const CXXDestructorDecl *Dtor = R->getDestructor();
-  if (!Dtor || Dtor->isTrivial())
-    return true;
-
   assert(Dtor);
   const Function *DtorFunc = getFunction(Dtor);
   if (!DtorFunc)
     return false;
   assert(DtorFunc->hasThisPointer());
   assert(DtorFunc->getNumParams() == 1);
-  if (!this->emitDupPtr(Loc))
-    return false;
   return this->emitCall(DtorFunc, 0, Loc);
 }
 /// When calling this, we have a pointer of the local-to-destroy
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).
 template <class Emitter>
-bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
-                                        SourceInfo Loc) {
+bool Compiler<Emitter>::emitDestructionPop(const Descriptor *Desc,
+                                           SourceInfo Loc) {
   assert(Desc);
-  assert(!Desc->isPrimitive());
-  assert(!Desc->isPrimitiveArray());
+  assert(!Desc->hasTrivialDtor());
 
   // Arrays.
   if (Desc->isArray()) {
     const Descriptor *ElemDesc = Desc->ElemDesc;
     assert(ElemDesc);
 
-    // Don't need to do anything for these.
-    if (ElemDesc->isPrimitiveArray())
-      return true;
+    unsigned N = Desc->getNumElems();
+    if (N == 0)
+      return this->emitPopPtr(Loc);
 
-    // If this is an array of record types, check if we need
-    // to call the element destructors at all. If not, try
-    // to save the work.
-    if (const Record *ElemRecord = ElemDesc->ElemRecord) {
-      if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
-          !Dtor || Dtor->isTrivial())
-        return true;
-    }
-
-    if (unsigned N = Desc->getNumElems()) {
-      for (ssize_t I = N - 1; I >= 0; --I) {
-        if (!this->emitConstUint64(I, Loc))
-          return false;
-        if (!this->emitArrayElemPtrUint64(Loc))
-          return false;
-        if (!this->emitDestruction(ElemDesc, Loc))
-          return false;
-        if (!this->emitPopPtr(Loc))
-          return false;
-      }
+    for (ssize_t I = N - 1; I >= 1; --I) {
+      if (!this->emitConstUint64(I, Loc))
+        return false;
+      if (!this->emitArrayElemPtrUint64(Loc))
+        return false;
+      if (!this->emitDestructionPop(ElemDesc, Loc))
+        return false;
     }
-    return true;
+    // Last iteration, removes the instance pointer from the stack.
+    if (!this->emitConstUint64(0, Loc))
+      return false;
+    if (!this->emitArrayElemPtrPopUint64(Loc))
+      return false;
+    return this->emitDestructionPop(ElemDesc, Loc);
   }
 
   assert(Desc->ElemRecord);
-  if (Desc->ElemRecord->isAnonymousUnion())
-    return true;
-
-  return this->emitRecordDestruction(Desc->ElemRecord, Loc);
+  assert(!Desc->ElemRecord->hasTrivialDtor());
+  return this->emitRecordDestructionPop(Desc->ElemRecord, Loc);
 }
 
 /// Create a dummy pointer for the given decl (or expr) and

diff  --git a/clang/lib/AST/ByteCode/Compiler.h 
b/clang/lib/AST/ByteCode/Compiler.h
index 475faee4d3fde..bb8c660427310 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -391,8 +391,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, 
bool>,
   bool emitComplexBoolCast(const Expr *E);
   bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
                              const BinaryOperator *E);
-  bool emitRecordDestruction(const Record *R, SourceInfo Loc);
-  bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
+  bool emitRecordDestructionPop(const Record *R, SourceInfo Loc);
+  bool emitDestructionPop(const Descriptor *Desc, SourceInfo Loc);
   bool emitDummyPtr(const DeclTy &D, const Expr *E);
   bool emitFloat(const APFloat &F, const Expr *E);
   unsigned collectBaseOffset(const QualType BaseType,
@@ -587,11 +587,9 @@ template <class Emitter> class LocalScope : public 
VariableScope<Emitter> {
       if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
         return false;
 
-      if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc()))
+      if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
         return false;
 
-      if (!this->Ctx->emitPopPtr(E))
-        return false;
       removeIfStoredOpaqueValue(Local);
     }
     return true;

diff  --git a/clang/lib/AST/ByteCode/Descriptor.cpp 
b/clang/lib/AST/ByteCode/Descriptor.cpp
index 647de56b28013..0a819599287ee 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -457,8 +457,7 @@ bool Descriptor::hasTrivialDtor() const {
 
   if (isRecord()) {
     assert(ElemRecord);
-    const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
-    return !Dtor || Dtor->isTrivial();
+    return ElemRecord->hasTrivialDtor();
   }
 
   if (!ElemDesc)

diff  --git a/clang/lib/AST/ByteCode/Record.cpp 
b/clang/lib/AST/ByteCode/Record.cpp
index c20ec184f34f4..ff5c82d244574 100644
--- a/clang/lib/AST/ByteCode/Record.cpp
+++ b/clang/lib/AST/ByteCode/Record.cpp
@@ -37,6 +37,13 @@ std::string Record::getName() const {
   return Ret;
 }
 
+bool Record::hasTrivialDtor() const {
+  if (isAnonymousUnion())
+    return true;
+  const CXXDestructorDecl *Dtor = getDestructor();
+  return !Dtor || Dtor->isTrivial();
+}
+
 const Record::Field *Record::getField(const FieldDecl *FD) const {
   auto It = FieldMap.find(FD->getFirstDecl());
   assert(It != FieldMap.end() && "Missing field");

diff  --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h
index 93ca43046180a..8245eeff2f20d 100644
--- a/clang/lib/AST/ByteCode/Record.h
+++ b/clang/lib/AST/ByteCode/Record.h
@@ -76,6 +76,10 @@ class Record final {
     return nullptr;
   }
 
+  /// Returns true for anonymous unions and records
+  /// with no destructor or for those with a trivial destructor.
+  bool hasTrivialDtor() const;
+
   using const_field_iter = FieldList::const_iterator;
   llvm::iterator_range<const_field_iter> fields() const {
     return llvm::make_range(Fields.begin(), Fields.end());


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

Reply via email to