]> granicus.if.org Git - clang/commitdiff
Assign APValues by swapping from a temporary. Removes a bunch of unnecessary
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 10 Mar 2012 00:28:11 +0000 (00:28 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 10 Mar 2012 00:28:11 +0000 (00:28 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152455 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/APValue.h
lib/AST/APValue.cpp
lib/AST/ExprConstant.cpp

index b7e588fba4525901c8a02ac39ab79f37435a0f57..1b6e90cf4a8307ab8a03e4bd1cd24e5d9548f943 100644 (file)
@@ -135,9 +135,7 @@ public:
   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 @@ public:
     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 @@ public:
     ((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();
index 976629cea2daf5a18b940ffd96a1ac3aaba773e8..0b5b3b0a5e5fd7bf34e76ccc4463c59caad2ca35 100644 (file)
@@ -122,71 +122,68 @@ APValue::UnionData::~UnionData () {
   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 @@ void APValue::DestroyDataAndMakeUninit() {
   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';
index 5f9b0501b2871d26e7b7ece759462001b1667492..97c906c407f982d2720946998d16d63e0a58b7ce 100644 (file)
@@ -1518,7 +1518,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
     // 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 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
     }
   }
 
-  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;
 }