[cfe-commits] r152455 - in /cfe/trunk: include/clang/AST/APValue.h lib/AST/APValue.cpp lib/AST/ExprConstant.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Mar 9 16:28:11 PST 2012


Author: rsmith
Date: Fri Mar  9 18:28:11 2012
New Revision: 152455

URL: http://llvm.org/viewvc/llvm-project?rev=152455&view=rev
Log:
Assign APValues by swapping from a temporary. Removes a bunch of unnecessary
copy-construction, which Daniel Dunbar reports as giving a 0.75% speedup on
403.gcc/combine.c. The performance differences on my constexpr torture tests
are below the noise floor.

Modified:
    cfe/trunk/include/clang/AST/APValue.h
    cfe/trunk/lib/AST/APValue.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp

Modified: cfe/trunk/include/clang/AST/APValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/APValue.h?rev=152455&r1=152454&r2=152455&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/APValue.h (original)
+++ cfe/trunk/include/clang/AST/APValue.h Fri Mar  9 18:28:11 2012
@@ -135,9 +135,7 @@
   APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
     MakeComplexFloat(); setComplexFloat(R, I);
   }
-  APValue(const APValue &RHS) : Kind(Uninitialized) {
-    *this = RHS;
-  }
+  APValue(const APValue &RHS);
   APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
       : Kind(Uninitialized) {
     MakeLValue(); setLValue(B, O, N, CallIndex);
@@ -170,6 +168,9 @@
     MakeUninit();
   }
 
+  /// \brief Swaps the contents of this and the given APValue.
+  void swap(APValue &RHS);
+
   ValueKind getKind() const { return Kind; }
   bool isUninit() const { return Kind == Uninitialized; }
   bool isInt() const { return Kind == Int; }
@@ -382,7 +383,11 @@
     ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr;
   }
 
-  const APValue &operator=(const APValue &RHS);
+  /// Assign by swapping from a copy of the RHS.
+  APValue &operator=(APValue RHS) {
+    swap(RHS);
+    return *this;
+  }
 
 private:
   void DestroyDataAndMakeUninit();

Modified: cfe/trunk/lib/AST/APValue.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/APValue.cpp?rev=152455&r1=152454&r2=152455&view=diff
==============================================================================
--- cfe/trunk/lib/AST/APValue.cpp (original)
+++ cfe/trunk/lib/AST/APValue.cpp Fri Mar  9 18:28:11 2012
@@ -122,71 +122,68 @@
   delete Value;
 }
 
-const APValue &APValue::operator=(const APValue &RHS) {
-  if (this == &RHS)
-    return *this;
-  if (Kind != RHS.Kind || Kind == Array || Kind == Struct ||
-      Kind == MemberPointer) {
-    MakeUninit();
-    if (RHS.isInt())
-      MakeInt();
-    else if (RHS.isFloat())
-      MakeFloat();
-    else if (RHS.isVector())
-      MakeVector();
-    else if (RHS.isComplexInt())
-      MakeComplexInt();
-    else if (RHS.isComplexFloat())
-      MakeComplexFloat();
-    else if (RHS.isLValue())
-      MakeLValue();
-    else if (RHS.isArray())
-      MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
-    else if (RHS.isStruct())
-      MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
-    else if (RHS.isUnion())
-      MakeUnion();
-    else if (RHS.isMemberPointer())
-      MakeMemberPointer(RHS.getMemberPointerDecl(),
-                        RHS.isMemberPointerToDerivedMember(),
-                        RHS.getMemberPointerPath());
-    else if (RHS.isAddrLabelDiff())
-      MakeAddrLabelDiff();
-  }
-  if (isInt())
+APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
+  switch (RHS.getKind()) {
+  case Uninitialized:
+    break;
+  case Int:
+    MakeInt();
     setInt(RHS.getInt());
-  else if (isFloat())
+    break;
+  case Float:
+    MakeFloat();
     setFloat(RHS.getFloat());
-  else if (isVector())
+    break;
+  case Vector:
+    MakeVector();
     setVector(((const Vec *)(const char *)RHS.Data)->Elts,
               RHS.getVectorLength());
-  else if (isComplexInt())
+    break;
+  case ComplexInt:
+    MakeComplexInt();
     setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
-  else if (isComplexFloat())
+    break;
+  case ComplexFloat:
+    MakeComplexFloat();
     setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
-  else if (isLValue()) {
+    break;
+  case LValue:
+    MakeLValue();
     if (RHS.hasLValuePath())
       setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
                 RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
     else
       setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
                 RHS.getLValueCallIndex());
-  } else if (isArray()) {
+    break;
+  case Array:
+    MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
     for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
       getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
     if (RHS.hasArrayFiller())
       getArrayFiller() = RHS.getArrayFiller();
-  } else if (isStruct()) {
+    break;
+  case Struct:
+    MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
     for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
       getStructBase(I) = RHS.getStructBase(I);
     for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
       getStructField(I) = RHS.getStructField(I);
-  } else if (isUnion()) {
+    break;
+  case Union:
+    MakeUnion();
     setUnion(RHS.getUnionField(), RHS.getUnionValue());
-  } else if (isAddrLabelDiff()) {
+    break;
+  case MemberPointer:
+    MakeMemberPointer(RHS.getMemberPointerDecl(),
+                      RHS.isMemberPointerToDerivedMember(),
+                      RHS.getMemberPointerPath());
+    break;
+  case AddrLabelDiff:
+    MakeAddrLabelDiff();
     setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());
+    break;
   }
-  return *this;
 }
 
 void APValue::DestroyDataAndMakeUninit() {
@@ -215,6 +212,14 @@
   Kind = Uninitialized;
 }
 
+void APValue::swap(APValue &RHS) {
+  std::swap(Kind, RHS.Kind);
+  char TmpData[MaxSize];
+  memcpy(TmpData, Data, MaxSize);
+  memcpy(Data, RHS.Data, MaxSize);
+  memcpy(RHS.Data, TmpData, MaxSize);
+}
+
 void APValue::dump() const {
   dump(llvm::errs());
   llvm::errs() << '\n';

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=152455&r1=152454&r2=152455&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Mar  9 18:28:11 2012
@@ -1518,7 +1518,7 @@
     // This object might be initialized later.
     return false;
 
-  const APValue *O = &Obj;
+  APValue *O = &Obj;
   // Walk the designator's path to find the subobject.
   for (unsigned I = 0, N = Sub.Entries.size(); I != N; ++I) {
     if (ObjType->isArrayType()) {
@@ -1616,7 +1616,13 @@
     }
   }
 
-  Obj = APValue(*O);
+  // This may look super-stupid, but it serves an important purpose: if we just
+  // swapped Obj and *O, we'd create an object which had itself as a subobject.
+  // To avoid the leak, we ensure that Tmp ends up owning the original complete
+  // object, which is destroyed by Tmp's destructor.
+  APValue Tmp;
+  O->swap(Tmp);
+  Obj.swap(Tmp);
   return true;
 }
 





More information about the cfe-commits mailing list