Generate atomic api for atomic properties (x86 and x86_64
targets) when load/store results in multiple instructions.
// rdar://8808439


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128937 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index ac4e763..78305c6 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -262,6 +262,22 @@
         CGM.getObjCRuntime().GetGetStructFunction()) {
       GenerateObjCGetterBody(Ivar, true, false);
     }
+    else if (IsAtomic &&
+             (IVART->isScalarType() && !IVART->isRealFloatingType()) &&
+             Triple.getArch() == llvm::Triple::x86 &&
+             (getContext().getTypeSizeInChars(IVART) 
+              > CharUnits::fromQuantity(4)) &&
+             CGM.getObjCRuntime().GetGetStructFunction()) {
+      GenerateObjCGetterBody(Ivar, true, false);
+    }
+    else if (IsAtomic &&
+             (IVART->isScalarType() && !IVART->isRealFloatingType()) &&
+             Triple.getArch() == llvm::Triple::x86_64 &&
+             (getContext().getTypeSizeInChars(IVART) 
+              > CharUnits::fromQuantity(8)) &&
+             CGM.getObjCRuntime().GetGetStructFunction()) {
+      GenerateObjCGetterBody(Ivar, true, false);
+    }
     else if (IVART->isAnyComplexType()) {
       LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 
                                     Ivar, 0);
@@ -283,6 +299,21 @@
                                           PID->getGetterCXXConstructor(),
                                           0);
           EmitReturnStmt(*Stmt);
+        } else if (IsAtomic &&
+                   !IVART->isAnyComplexType() &&
+                   Triple.getArch() == llvm::Triple::x86 &&
+                   (getContext().getTypeSizeInChars(IVART) 
+                    > CharUnits::fromQuantity(4)) &&
+                   CGM.getObjCRuntime().GetGetStructFunction()) {
+          GenerateObjCGetterBody(Ivar, true, false);
+        }
+        else if (IsAtomic &&
+                 !IVART->isAnyComplexType() &&
+                 Triple.getArch() == llvm::Triple::x86_64 &&
+                 (getContext().getTypeSizeInChars(IVART) 
+                  > CharUnits::fromQuantity(8)) &&
+                 CGM.getObjCRuntime().GetGetStructFunction()) {
+          GenerateObjCGetterBody(Ivar, true, false);
         }
         else {
           LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 
@@ -358,7 +389,8 @@
   ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
   assert(OMD && "Invalid call to generate setter (empty method)");
   StartObjCMethod(OMD, IMP->getClassInterface());
-
+  const llvm::Triple &Triple = getContext().Target.getTriple();
+  QualType IVART = Ivar->getType();
   bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy;
   bool IsAtomic =
     !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
@@ -414,18 +446,21 @@
                                    FunctionType::ExtInfo()),
              SetPropertyFn,
              ReturnValueSlot(), Args);
-  } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) &&
-             !Ivar->getType()->isAnyComplexType() &&
-             IndirectObjCSetterArg(*CurFnInfo)
+  } else if (IsAtomic && hasAggregateLLVMType(IVART) &&
+             !IVART->isAnyComplexType() &&
+             ((Triple.getArch() == llvm::Triple::x86 &&
+              (getContext().getTypeSizeInChars(IVART)
+               > CharUnits::fromQuantity(4))) ||
+              (Triple.getArch() == llvm::Triple::x86_64 &&
+              (getContext().getTypeSizeInChars(IVART)
+               > CharUnits::fromQuantity(8))))
              && CGM.getObjCRuntime().GetSetStructFunction()) {
-    // objc_copyStruct (&structIvar, &Arg, 
-    //                  sizeof (struct something), true, false);
+          // objc_copyStruct (&structIvar, &Arg, 
+          //                  sizeof (struct something), true, false);
     GenerateObjCAtomicSetterBody(OMD, Ivar);
   } else if (PID->getSetterCXXAssignment()) {
     EmitIgnoredExpr(PID->getSetterCXXAssignment());
   } else {
-    const llvm::Triple &Triple = getContext().Target.getTriple();
-    QualType IVART = Ivar->getType();
     if (IsAtomic &&
         IVART->isScalarType() &&
         (Triple.getArch() == llvm::Triple::arm ||
@@ -435,6 +470,22 @@
         CGM.getObjCRuntime().GetGetStructFunction()) {
       GenerateObjCAtomicSetterBody(OMD, Ivar);
     }
+    else if (IsAtomic &&
+             (IVART->isScalarType() && !IVART->isRealFloatingType()) &&
+             Triple.getArch() == llvm::Triple::x86 &&
+             (getContext().getTypeSizeInChars(IVART)
+              > CharUnits::fromQuantity(4)) &&
+             CGM.getObjCRuntime().GetGetStructFunction()) {
+      GenerateObjCAtomicSetterBody(OMD, Ivar);
+    }
+    else if (IsAtomic &&
+             (IVART->isScalarType() && !IVART->isRealFloatingType()) &&
+             Triple.getArch() == llvm::Triple::x86_64 &&
+             (getContext().getTypeSizeInChars(IVART)
+              > CharUnits::fromQuantity(8)) &&
+             CGM.getObjCRuntime().GetGetStructFunction()) {
+      GenerateObjCAtomicSetterBody(OMD, Ivar);
+    }
     else {
       // FIXME: Find a clean way to avoid AST node creation.
       SourceLocation Loc = PD->getLocation();