[llvm] [RFC][Attributor] change argument privatization to size-based type selection (PR #181716)

Jameson Nash via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 16 10:21:16 PST 2026


https://github.com/vtjnash created https://github.com/llvm/llvm-project/pull/181716

WARNING: for feedback only on approach and design goals, not yet human-edited to meet quality standards.

The current Attributor design assumes that AllocaInst getAllocatedType has semantic meaning. This is fairly safe currently, based on its use of isDenselyPacked to conservatively reject cases where the semantics of the type would be obviously unsound, but it is suboptimal and also contradictory to the design of Attributor's fixed-point use analysis to be taking this information instead from the definition site. It is also one of very few remaining uses of getAllocatedType in the optimization passes. Once all are gone, we can delete this non-semantic accessor, just like typed-pointers and typed-GEP are being deleted for that same reason, and simplify the IR.

There is probably a few options here, depending on what matters to the ABI and the intent of the pass from the original authors: the simplest option is what I've asked Claude to do here, just pick some reasonable size type that maps adequately to the size and alignment of the object on the current platform. Alternatively, we could use PtrUseAnalysis (with my bugfixes in https://github.com/llvm/llvm-project/pull/179726) to collect all uses of the pointer and then compute an estimated fixed-point partitioning of that information globally (essentially estimating what SROA, where PtrUseAnalysis originally came from, will be able to do once the argument values are split, plus IPO handling)–the benefit of this approach being that several other passes (GlobalOpt and GPU targets) already do, or need to do, that same memory access analysis.

tl;dr: Replace type-based privatization with size-based approach that selects optimal types based on data size, alignment, and target capabilities. Uses integers for small data, vectors for medium sizes, and aligned arrays for larger data.

>From 9713fb0c9d5a4720135d51a6e05c796bed4d315c Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash+github at gmail.com>
Date: Mon, 16 Feb 2026 17:58:35 +0000
Subject: [PATCH] [Attributor] Optimize argument privatization with size-based
 type selection

WARNING: for feedback only, not yet human-edited to meet quality standards.

The current Attributor design assumes that getAllocatedType has semantic
meaning. This is fairly safe currently, based on its use of
isDenselyPacked to conservatively reject cases where the semantics of
the type would be obviously unsound, but it is suboptimal and also
contraditory to the design of Attributor's fixed-point use analysis to
be taking this information instead from the definition site. There is
probably a few options here, depending on what matters to the ABI: the
simplest option is what I've asked Claude to do here, just pick a
reasonable size type that maps adequately to the size of the object on
the current platform. Alternatively, we could use PtrUseAnalysis (with
my bugfixes in https://github.com/llvm/llvm-project/pull/179726) to
collect all uses of the pointer and then compute and estimated
fixed-point partitioning of that information globally (essentially
estimating what SROA, where PtrUseAnalysis originally came from, will be
able to do once the argment values are split, plus IPO handling).

Summary of plan: replace type-based privatization with size-based
approach that selects optimal types based on data size, alignment, and
target capabilities. Uses integers for small data, vectors for medium
sizes, and aligned arrays for larger data.

Co-Authored-By: Claude Sonnet 4.5 <noreply at anthropic.com>
---
 llvm/include/llvm/Transforms/IPO/Attributor.h |   6 +-
 .../Transforms/IPO/AttributorAttributes.cpp   | 393 ++++++++----------
 .../ArgumentPromotion/X86/attributes.ll       |  74 +++-
 .../X86/min-legal-vector-width.ll             | 130 +++---
 .../Attributor/ArgumentPromotion/array.ll     |  20 +-
 .../Attributor/ArgumentPromotion/attrs.ll     |  25 +-
 .../Attributor/ArgumentPromotion/byval-2.ll   |  20 +-
 .../Attributor/ArgumentPromotion/byval.ll     |  36 +-
 .../Attributor/ArgumentPromotion/fp80.ll      |  10 +-
 .../Attributor/ArgumentPromotion/tail.ll      |  32 +-
 .../IPConstantProp/2009-09-24-byval-ptr.ll    |  98 ++---
 llvm/test/Transforms/Attributor/nofpclass.ll  |  55 ++-
 .../Attributor/value-simplify-pointer-info.ll |  44 +-
 .../Transforms/Attributor/value-simplify.ll   | 157 +++----
 14 files changed, 515 insertions(+), 585 deletions(-)

diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index f2657a338ba76..3808bcd1c2d67 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -4650,10 +4650,10 @@ struct AAPrivatizablePtr
   /// See AbstractAttribute::requiresCallersForArgOrFunction
   static bool requiresCallersForArgOrFunction() { return true; }
 
-  /// Return the type we can choose for a private copy of the underlying
-  /// value. std::nullopt means it is not clear yet, nullptr means there is
+  /// Return the size we can choose for a private copy of the underlying
+  /// value. std::nullopt means it is not clear yet, zero means there is
   /// none.
-  virtual std::optional<Type *> getPrivatizableType() const = 0;
+  virtual std::optional<TypeSize> getPrivatizableSize() const = 0;
 
   /// Create an abstract attribute view for the position \p IRP.
   LLVM_ABI static AAPrivatizablePtr &createForPosition(const IRPosition &IRP,
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index b80a514b68246..17b9b930862df 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -225,45 +225,6 @@ static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
   return !HeaderOnly || BB == C->getHeader();
 }
 
-/// Checks if a type could have padding bytes.
-static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
-  // There is no size information, so be conservative.
-  if (!Ty->isSized())
-    return false;
-
-  // If the alloc size is not equal to the storage size, then there are padding
-  // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
-  if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
-    return false;
-
-  // FIXME: This isn't the right way to check for padding in vectors with
-  // non-byte-size elements.
-  if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
-    return isDenselyPacked(SeqTy->getElementType(), DL);
-
-  // For array types, check for padding within members.
-  if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
-    return isDenselyPacked(SeqTy->getElementType(), DL);
-
-  if (!isa<StructType>(Ty))
-    return true;
-
-  // Check for padding within and between elements of a struct.
-  StructType *StructTy = cast<StructType>(Ty);
-  const StructLayout *Layout = DL.getStructLayout(StructTy);
-  uint64_t StartPos = 0;
-  for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
-    Type *ElTy = StructTy->getElementType(I);
-    if (!isDenselyPacked(ElTy, DL))
-      return false;
-    if (StartPos != Layout->getElementOffsetInBits(I))
-      return false;
-    StartPos += DL.getTypeAllocSizeInBits(ElTy);
-  }
-
-  return true;
-}
-
 /// Get pointer operand of memory accessing instruction. If \p I is
 /// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
 /// is set to false and the instruction is volatile, return nullptr.
@@ -7290,34 +7251,35 @@ ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
 namespace {
 struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
   AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
-      : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
+      : AAPrivatizablePtr(IRP, A), PrivatizableSize(std::nullopt) {}
 
   ChangeStatus indicatePessimisticFixpoint() override {
     AAPrivatizablePtr::indicatePessimisticFixpoint();
-    PrivatizableType = nullptr;
+    PrivatizableSize = TypeSize::getFixed(0);
     return ChangeStatus::CHANGED;
   }
 
-  /// Identify the type we can chose for a private copy of the underlying
-  /// argument. std::nullopt means it is not clear yet, nullptr means there is
+  /// Identify the size we can chose for a private copy of the underlying
+  /// argument. std::nullopt means it is not clear yet, zero means there is
   /// none.
-  virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
-
-  /// Return a privatizable type that encloses both T0 and T1.
-  /// TODO: This is merely a stub for now as we should manage a mapping as well.
-  std::optional<Type *> combineTypes(std::optional<Type *> T0,
-                                     std::optional<Type *> T1) {
-    if (!T0)
-      return T1;
-    if (!T1)
-      return T0;
-    if (T0 == T1)
-      return T0;
-    return nullptr;
+  virtual std::optional<TypeSize> identifyPrivatizableSize(Attributor &A) = 0;
+
+  /// Return a privatizable size that encloses both S0 and S1.
+  std::optional<TypeSize> combineSizes(std::optional<TypeSize> S0,
+                                       std::optional<TypeSize> S1) {
+    if (!S0)
+      return S1;
+    if (!S1)
+      return S0;
+    // Both sizes must be known and must match (including scalability)
+    if (*S0 == *S1)
+      return S0;
+    // Sizes don't match - cannot privatize
+    return TypeSize::getFixed(0);
   }
 
-  std::optional<Type *> getPrivatizableType() const override {
-    return PrivatizableType;
+  std::optional<TypeSize> getPrivatizableSize() const override {
+    return PrivatizableSize;
   }
 
   const std::string getAsStr(Attributor *A) const override {
@@ -7325,7 +7287,8 @@ struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
   }
 
 protected:
-  std::optional<Type *> PrivatizableType;
+  std::optional<TypeSize> PrivatizableSize;
+  Type *PrivatizableType = nullptr;
 };
 
 // TODO: Do this for call site arguments (probably also other values) as well.
@@ -7334,8 +7297,9 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
   AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
       : AAPrivatizablePtrImpl(IRP, A) {}
 
-  /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
-  std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
+  /// See AAPrivatizablePtrImpl::identifyPrivatizableSize(...)
+  std::optional<TypeSize> identifyPrivatizableSize(Attributor &A) override {
+    const DataLayout &DL = A.getDataLayout();
     // If this is a byval argument and we know all the call sites (so we can
     // rewrite them), there is no need to check them explicitly.
     bool UsedAssumedInformation = false;
@@ -7344,18 +7308,19 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
                /* IgnoreSubsumingPositions */ true);
     if (!Attrs.empty() &&
         A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
-                               true, UsedAssumedInformation))
-      return Attrs[0].getValueAsType();
+                               true, UsedAssumedInformation)) {
+      Type *ByValTy = Attrs[0].getValueAsType();
+      if (ByValTy->isSized())
+        return DL.getTypeAllocSize(ByValTy);
+      return TypeSize::getFixed(0);
+    }
 
-    std::optional<Type *> Ty;
+    std::optional<TypeSize> Size;
     unsigned ArgNo = getIRPosition().getCallSiteArgNo();
 
-    // Make sure the associated call site argument has the same type at all call
+    // Make sure the associated call site argument has the same size at all call
     // sites and it is an allocation we know is safe to privatize, for now that
     // means we only allow alloca instructions.
-    // TODO: We can additionally analyze the accesses in the callee to  create
-    //       the type from that information instead. That is a little more
-    //       involved and will be done in a follow up patch.
     auto CallSiteCheck = [&](AbstractCallSite ACS) {
       IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
       // Check if a coresponding argument was found or if it is one not
@@ -7363,96 +7328,76 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
       if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
         return false;
 
-      // Check that all call sites agree on a type.
+      // Check that all call sites agree on a size.
       auto *PrivCSArgAA =
           A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
       if (!PrivCSArgAA)
         return false;
-      std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
+      std::optional<TypeSize> CSSize = PrivCSArgAA->getPrivatizableSize();
 
       LLVM_DEBUG({
-        dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
-        if (CSTy && *CSTy)
-          (*CSTy)->print(dbgs());
-        else if (CSTy)
-          dbgs() << "<nullptr>";
+        dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSSize: ";
+        if (CSSize && !CSSize->isZero())
+          dbgs() << *CSSize;
+        else if (CSSize)
+          dbgs() << "<zero>";
         else
           dbgs() << "<none>";
       });
 
-      Ty = combineTypes(Ty, CSTy);
+      Size = combineSizes(Size, CSSize);
 
       LLVM_DEBUG({
-        dbgs() << " : New Type: ";
-        if (Ty && *Ty)
-          (*Ty)->print(dbgs());
-        else if (Ty)
-          dbgs() << "<nullptr>";
+        dbgs() << " : New Size: ";
+        if (Size && !Size->isZero())
+          dbgs() << *Size;
+        else if (Size)
+          dbgs() << "<zero>";
         else
           dbgs() << "<none>";
         dbgs() << "\n";
       });
 
-      return !Ty || *Ty;
+      return !Size || !Size->isZero();
     };
 
     if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
                                 UsedAssumedInformation))
-      return nullptr;
-    return Ty;
+      return TypeSize::getFixed(0);
+    return Size;
   }
 
   /// See AbstractAttribute::updateImpl(...).
   ChangeStatus updateImpl(Attributor &A) override {
-    PrivatizableType = identifyPrivatizableType(A);
-    if (!PrivatizableType)
+    PrivatizableSize = identifyPrivatizableSize(A);
+    if (!PrivatizableSize)
       return ChangeStatus::UNCHANGED;
-    if (!*PrivatizableType)
+    if (PrivatizableSize->isZero())
       return indicatePessimisticFixpoint();
 
-    // The dependence is optional so we don't give up once we give up on the
-    // alignment.
-    A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
-                        DepClassTy::OPTIONAL);
-
-    // Avoid arguments with padding for now.
-    if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&
-        !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
-      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
+    // Reject scalable vectors for now
+    if (PrivatizableSize->isScalable()) {
+      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Scalable size not supported\n");
       return indicatePessimisticFixpoint();
     }
 
-    // Collect the types that will replace the privatizable type in the function
-    // signature.
-    SmallVector<Type *, 16> ReplacementTypes;
-    identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
+    // Get alignment information for choosing optimal type
+    const auto *AlignAA =
+        A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
+                            DepClassTy::OPTIONAL);
+    Align Alignment = AlignAA ? AlignAA->getAssumedAlign() : Align(1);
 
-    // Verify callee and caller agree on how the promoted argument would be
-    // passed.
+    // Get TTI for target-specific type selection
     Function &Fn = *getIRPosition().getAnchorScope();
     const auto *TTI =
         A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
-    if (!TTI) {
-      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
-                        << Fn.getName() << "\n");
-      return indicatePessimisticFixpoint();
-    }
 
-    auto CallSiteCheck = [&](AbstractCallSite ACS) {
-      CallBase *CB = ACS.getInstruction();
-      return TTI->areTypesABICompatible(
-          CB->getCaller(),
-          dyn_cast_if_present<Function>(CB->getCalledOperand()),
-          ReplacementTypes);
-    };
-    bool UsedAssumedInformation = false;
-    if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
-                                UsedAssumedInformation)) {
-      LLVM_DEBUG(
-          dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
-                 << Fn.getName() << "\n");
-      return indicatePessimisticFixpoint();
-    }
+    // Choose an optimal type to represent the privatizable data
+    const DataLayout &DL = A.getDataLayout();
+    PrivatizableType = getPrivatizableReplacementType(
+        PrivatizableSize->getFixedValue(), Alignment, DL,
+        getAnchorValue().getContext(), TTI);
+    SmallVector<Type *, 1> ReplacementTypes = {PrivatizableType};
 
     // Register a rewrite of the argument.
     Argument *Arg = getAssociatedArgument();
@@ -7462,6 +7407,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
     }
 
     unsigned ArgNo = Arg->getArgNo();
+    bool UsedAssumedInformation = false;
 
     // Helper to check if for the given call site the associated argument is
     // passed to a callback where the privatization would be different.
@@ -7494,10 +7440,10 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
           const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
               *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
           if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
-            auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
-            if (!CBArgPrivTy)
+            auto CBArgPrivSize = CBArgPrivAA->getPrivatizableSize();
+            if (!CBArgPrivSize)
               continue;
-            if (*CBArgPrivTy == PrivatizableType)
+            if (*CBArgPrivSize == PrivatizableSize)
               continue;
           }
 
@@ -7541,10 +7487,10 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
             *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
             DepClassTy::REQUIRED);
         if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
-          auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
-          if (!DCArgPrivTy)
+          auto DCArgPrivSize = DCArgPrivAA->getPrivatizableSize();
+          if (!DCArgPrivSize)
             return true;
-          if (*DCArgPrivTy == PrivatizableType)
+          if (*DCArgPrivSize == PrivatizableSize)
             return true;
         }
       }
@@ -7580,101 +7526,84 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
     return ChangeStatus::UNCHANGED;
   }
 
-  /// Given a type to private \p PrivType, collect the constituates (which are
-  /// used) in \p ReplacementTypes.
-  static void
-  identifyReplacementTypes(Type *PrivType,
-                           SmallVectorImpl<Type *> &ReplacementTypes) {
-    // TODO: For now we expand the privatization type to the fullest which can
-    //       lead to dead arguments that need to be removed later.
-    assert(PrivType && "Expected privatizable type!");
-
-    // Traverse the type, extract constituate types on the outermost level.
-    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
-      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
-        ReplacementTypes.push_back(PrivStructType->getElementType(u));
-    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
-      ReplacementTypes.append(PrivArrayType->getNumElements(),
-                              PrivArrayType->getElementType());
-    } else {
-      ReplacementTypes.push_back(PrivType);
+  /// Choose an optimal type to represent \p Size bytes of data.
+  /// Strategy:
+  /// 1. Up to pointer size: use IntegerType
+  /// 2. Up to vector register size: use vector of integers
+  /// 3. Otherwise: use array of integers sized to alignment
+  static Type *getPrivatizableReplacementType(uint64_t Size, Align Alignment,
+                                               const DataLayout &DL,
+                                               LLVMContext &Ctx,
+                                               const TargetTransformInfo *TTI) {
+    // Strategy 1: If size fits in pointer, use integer type
+    uint64_t PointerSizeInBits = DL.getPointerSizeInBits();
+    if (Size * 8 <= PointerSizeInBits)
+      return IntegerType::get(Ctx, Size * 8);
+
+    // Strategy 2: Try to use a vector type up to the vector register size
+    if (TTI) {
+      // Check for common vector widths (128-bit, 256-bit, 512-bit)
+      for (unsigned VectorBits : {128, 256, 512}) {
+        if (Size * 8 <= VectorBits) {
+          // Use a vector of i64 or smaller elements
+          uint64_t ElementBits = std::min(uint64_t(64), PointerSizeInBits);
+          unsigned NumElements = (Size * 8 + ElementBits - 1) / ElementBits;
+
+          // Verify this vector size is reasonable for the target
+          Type *ElementTy = IntegerType::get(Ctx, ElementBits);
+          auto VecTy = FixedVectorType::get(ElementTy, NumElements);
+
+          // Check if the vector type makes sense (not larger than requested)
+          if (DL.getTypeStoreSize(VecTy) >= Size &&
+              DL.getTypeStoreSize(VecTy) <= (Size * 3) / 2) // Max 50% overhead
+            return VecTy;
+        }
+      }
     }
+
+    // Strategy 3: Use array of integers sized to alignment
+    uint64_t AlignmentBytes = Alignment.value();
+    // Use alignment-sized integers, but cap at pointer size
+    uint64_t ElementSize = std::min(AlignmentBytes, PointerSizeInBits / 8);
+    // Ensure element size is a power of 2 and at least 1 byte
+    ElementSize = std::max(uint64_t(1), llvm::bit_floor(ElementSize));
+
+    Type *ElementTy = IntegerType::get(Ctx, ElementSize * 8);
+    uint64_t NumElements = (Size + ElementSize - 1) / ElementSize;
+
+    return ArrayType::get(ElementTy, NumElements);
   }
 
-  /// Initialize \p Base according to the type \p PrivType at position \p IP.
-  /// The values needed are taken from the arguments of \p F starting at
-  /// position \p ArgNo.
-  static void createInitialization(Type *PrivType, Value &Base, Function &F,
+  /// Initialize \p Base with the replacement value argument at position \p ArgNo.
+  /// Stores the value argument into the alloca.
+  static void createInitialization(Type *ReplacementTy, Value &Base, Function &F,
                                    unsigned ArgNo, BasicBlock::iterator IP) {
-    assert(PrivType && "Expected privatizable type!");
-
-    IRBuilder<NoFolder> IRB(IP->getParent(), IP);
-    const DataLayout &DL = F.getDataLayout();
-
-    // Traverse the type, build GEPs and stores.
-    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
-      const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
-      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
-        Value *Ptr =
-            constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);
-        new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
-      }
-    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
-      Type *PointeeTy = PrivArrayType->getElementType();
-      uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
-      for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
-        Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);
-        new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
-      }
-    } else {
-      new StoreInst(F.getArg(ArgNo), &Base, IP);
-    }
+    assert(ReplacementTy && "Expected valid replacement type!");
+
+    // The argument is a value - store it into the alloca
+    new StoreInst(F.getArg(ArgNo), &Base, IP);
   }
 
-  /// Extract values from \p Base according to the type \p PrivType at the
-  /// call position \p ACS. The values are appended to \p ReplacementValues.
-  void createReplacementValues(Align Alignment, Type *PrivType,
+  /// Extract the replacement value from \p Base at the call position \p ACS.
+  /// Creates a load of the value and appends it to \p ReplacementValues.
+  void createReplacementValues(Align Alignment, Type *ReplacementTy,
                                AbstractCallSite ACS, Value *Base,
                                SmallVectorImpl<Value *> &ReplacementValues) {
     assert(Base && "Expected base value!");
-    assert(PrivType && "Expected privatizable type!");
+    assert(ReplacementTy && "Expected valid replacement type!");
     Instruction *IP = ACS.getInstruction();
 
-    IRBuilder<NoFolder> IRB(IP);
-    const DataLayout &DL = IP->getDataLayout();
-
-    // Traverse the type, build GEPs and loads.
-    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
-      const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
-      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
-        Type *PointeeTy = PrivStructType->getElementType(u);
-        Value *Ptr =
-            constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);
-        LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
-        L->setAlignment(Alignment);
-        ReplacementValues.push_back(L);
-      }
-    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
-      Type *PointeeTy = PrivArrayType->getElementType();
-      uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
-      for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
-        Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);
-        LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
-        L->setAlignment(Alignment);
-        ReplacementValues.push_back(L);
-      }
-    } else {
-      LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());
-      L->setAlignment(Alignment);
-      ReplacementValues.push_back(L);
-    }
+    // Load the replacement type value
+    LoadInst *L = new LoadInst(ReplacementTy, Base, "", IP->getIterator());
+    L->setAlignment(Alignment);
+    ReplacementValues.push_back(L);
   }
 
   /// See AbstractAttribute::manifest(...)
   ChangeStatus manifest(Attributor &A) override {
-    if (!PrivatizableType)
+    if (!PrivatizableSize)
       return ChangeStatus::UNCHANGED;
-    assert(*PrivatizableType && "Expected privatizable type!");
+    assert(!PrivatizableSize->isZero() && "Expected non-zero privatizable size!");
 
     // Collect all tail calls in the function as we cannot allow new allocas to
     // escape into tail recursion.
@@ -7698,8 +7627,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
         A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
 
     // Callback to repair the associated function. A new alloca is placed at the
-    // beginning and initialized with the values passed through arguments. The
-    // new alloca replaces the use of the old pointer argument.
+    // beginning and initialized with the replacement value passed as an argument.
+    Type *RepTy = PrivatizableType;
     Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =
         [=](const Attributor::ArgumentReplacementInfo &ARI,
             Function &ReplacementFn, Function::arg_iterator ArgIt) {
@@ -7707,9 +7636,9 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
           BasicBlock::iterator IP = EntryBB.getFirstInsertionPt();
           const DataLayout &DL = IP->getDataLayout();
           unsigned AS = DL.getAllocaAddrSpace();
-          Instruction *AI = new AllocaInst(*PrivatizableType, AS,
+          Instruction *AI = new AllocaInst(RepTy, AS,
                                            Arg->getName() + ".priv", IP);
-          createInitialization(*PrivatizableType, *AI, ReplacementFn,
+          createInitialization(RepTy, *AI, ReplacementFn,
                                ArgIt->getArgNo(), IP);
 
           if (AI->getType() != Arg->getType())
@@ -7721,9 +7650,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
             CI->setTailCall(false);
         };
 
-    // Callback to repair a call site of the associated function. The elements
-    // of the privatizable type are loaded prior to the call and passed to the
-    // new function version.
+    // Callback to repair a call site of the associated function. The replacement
+    // value is loaded prior to the call and passed to the new function version.
     Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =
         [=](const Attributor::ArgumentReplacementInfo &ARI,
             AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
@@ -7731,15 +7659,14 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
           // natural alignment is assumed.
           createReplacementValues(
               AlignAA ? AlignAA->getAssumedAlign() : Align(0),
-              *PrivatizableType, ACS,
+              RepTy, ACS,
               ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
               NewArgOperands);
         };
 
-    // Collect the types that will replace the privatizable type in the function
+    // The replacement type replaces the privatizable pointer in the function
     // signature.
-    SmallVector<Type *, 16> ReplacementTypes;
-    identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
+    SmallVector<Type *, 1> ReplacementTypes = {RepTy};
 
     // Register a rewrite of the argument.
     if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
@@ -7770,29 +7697,35 @@ struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
                      "updateImpl will not be called");
   }
 
-  /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
-  std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
+  /// See AAPrivatizablePtrImpl::identifyPrivatizableSize(...)
+  std::optional<TypeSize> identifyPrivatizableSize(Attributor &A) override {
+    const DataLayout &DL = A.getDataLayout();
     Value *Obj = getUnderlyingObject(&getAssociatedValue());
     if (!Obj) {
       LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
-      return nullptr;
+      return TypeSize::getFixed(0);
     }
 
-    if (auto *AI = dyn_cast<AllocaInst>(Obj))
-      if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
-        if (CI->isOne())
-          return AI->getAllocatedType();
+    if (auto *AI = dyn_cast<AllocaInst>(Obj)) {
+      if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
+        if (CI->isOne()) {
+          std::optional<TypeSize> Size = AI->getAllocationSize(DL);
+          if (Size)
+            return *Size;
+        }
+      }
+    }
     if (auto *Arg = dyn_cast<Argument>(Obj)) {
       auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
           *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
       if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
-        return PrivArgAA->getPrivatizableType();
+        return PrivArgAA->getPrivatizableSize();
     }
 
     LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
                          "alloca nor privatizable argument: "
                       << *Obj << "!\n");
-    return nullptr;
+    return TypeSize::getFixed(0);
   }
 
   /// See AbstractAttribute::trackStatistics()
@@ -7814,10 +7747,10 @@ struct AAPrivatizablePtrCallSiteArgument final
 
   /// See AbstractAttribute::updateImpl(...).
   ChangeStatus updateImpl(Attributor &A) override {
-    PrivatizableType = identifyPrivatizableType(A);
-    if (!PrivatizableType)
+    PrivatizableSize = identifyPrivatizableSize(A);
+    if (!PrivatizableSize)
       return ChangeStatus::UNCHANGED;
-    if (!*PrivatizableType)
+    if (PrivatizableSize->isZero())
       return indicatePessimisticFixpoint();
 
     const IRPosition &IRP = getIRPosition();
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
index 73231cc4524fe..829d504be47b0 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
@@ -7,13 +7,25 @@
 target triple = "x86_64-unknown-linux-gnu"
 
 define internal fastcc void @no_promote_avx2(ptr %arg, ptr readonly %arg1) #0 {
-; CHECK: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
-; CHECK-LABEL: define {{[^@]+}}@no_promote_avx2
-; CHECK-SAME: (ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[ARG:%.*]], ptr noalias nofree noundef nonnull readonly align 32 captures(none) dereferenceable(32) [[ARG1:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP:%.*]] = load <4 x i64>, ptr [[ARG1]], align 32
-; CHECK-NEXT:    store <4 x i64> [[TMP]], ptr [[ARG]], align 32
-; CHECK-NEXT:    ret void
+; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
+; TUNIT-LABEL: define {{[^@]+}}@no_promote_avx2
+; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+; TUNIT-NEXT:  bb:
+; TUNIT-NEXT:    [[ARG1_PRIV:%.*]] = alloca <4 x i64>, align 32
+; TUNIT-NEXT:    store <4 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 32
+; TUNIT-NEXT:    [[TMP:%.*]] = load <4 x i64>, ptr [[ARG1_PRIV]], align 32
+; TUNIT-NEXT:    store <4 x i64> [[TMP]], ptr [[ARG]], align 32
+; TUNIT-NEXT:    ret void
+;
+; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
+; CGSCC-LABEL: define {{[^@]+}}@no_promote_avx2
+; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+; CGSCC-NEXT:  bb:
+; CGSCC-NEXT:    [[ARG1_PRIV:%.*]] = alloca <4 x i64>, align 32
+; CGSCC-NEXT:    store <4 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 32
+; CGSCC-NEXT:    [[TMP:%.*]] = load <4 x i64>, ptr [[ARG1_PRIV]], align 32, !invariant.load [[META0:![0-9]+]]
+; CGSCC-NEXT:    store <4 x i64> [[TMP]], ptr [[ARG]], align 32
+; CGSCC-NEXT:    ret void
 ;
 bb:
   %tmp = load <4 x i64>, ptr %arg1
@@ -29,7 +41,8 @@ define void @no_promote(ptr %arg) #1 {
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <4 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <4 x i64>, align 32
 ; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR3:[0-9]+]]
-; TUNIT-NEXT:    call fastcc void @no_promote_avx2(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[TMP2]], ptr noalias nofree noundef nonnull readonly align 32 captures(none) dereferenceable(32) [[TMP]]) #[[ATTR4:[0-9]+]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <4 x i64>, ptr [[TMP]], align 32
+; TUNIT-NEXT:    call fastcc void @no_promote_avx2(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[TMP2]], <4 x i64> [[TMP0]]) #[[ATTR4:[0-9]+]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <4 x i64>, ptr [[TMP2]], align 32
 ; TUNIT-NEXT:    store <4 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
@@ -41,7 +54,8 @@ define void @no_promote(ptr %arg) #1 {
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <4 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <4 x i64>, align 32
 ; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR3:[0-9]+]]
-; CGSCC-NEXT:    call fastcc void @no_promote_avx2(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[TMP2]], ptr noalias nofree noundef nonnull readonly align 32 captures(none) dereferenceable(32) [[TMP]]) #[[ATTR4:[0-9]+]]
+; CGSCC-NEXT:    [[TMP0:%.*]] = load <4 x i64>, ptr [[TMP]], align 32
+; CGSCC-NEXT:    call fastcc void @no_promote_avx2(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[TMP2]], <4 x i64> [[TMP0]]) #[[ATTR4:[0-9]+]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <4 x i64>, ptr [[TMP2]], align 32
 ; CGSCC-NEXT:    store <4 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -57,15 +71,25 @@ bb:
 }
 
 define internal fastcc void @promote_avx2(ptr %arg, ptr readonly %arg1) #0 {
-; CHECK: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
-; CHECK-LABEL: define {{[^@]+}}@promote_avx2
-; CHECK-SAME: (ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[ARG1_PRIV:%.*]] = alloca <4 x i64>, align 32
-; CHECK-NEXT:    store <4 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 32
-; CHECK-NEXT:    [[TMP:%.*]] = load <4 x i64>, ptr [[ARG1_PRIV]], align 32
-; CHECK-NEXT:    store <4 x i64> [[TMP]], ptr [[ARG]], align 32
-; CHECK-NEXT:    ret void
+; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
+; TUNIT-LABEL: define {{[^@]+}}@promote_avx2
+; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) #[[ATTR0]] {
+; TUNIT-NEXT:  bb:
+; TUNIT-NEXT:    [[ARG1_PRIV:%.*]] = alloca <4 x i64>, align 32
+; TUNIT-NEXT:    store <4 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 32
+; TUNIT-NEXT:    [[TMP:%.*]] = load <4 x i64>, ptr [[ARG1_PRIV]], align 32
+; TUNIT-NEXT:    store <4 x i64> [[TMP]], ptr [[ARG]], align 32
+; TUNIT-NEXT:    ret void
+;
+; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
+; CGSCC-LABEL: define {{[^@]+}}@promote_avx2
+; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) #[[ATTR0]] {
+; CGSCC-NEXT:  bb:
+; CGSCC-NEXT:    [[ARG1_PRIV:%.*]] = alloca <4 x i64>, align 32
+; CGSCC-NEXT:    store <4 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 32
+; CGSCC-NEXT:    [[TMP:%.*]] = load <4 x i64>, ptr [[ARG1_PRIV]], align 32, !invariant.load [[META0]]
+; CGSCC-NEXT:    store <4 x i64> [[TMP]], ptr [[ARG]], align 32
+; CGSCC-NEXT:    ret void
 ;
 bb:
   %tmp = load <4 x i64>, ptr %arg1
@@ -117,15 +141,19 @@ attributes #0 = { inlinehint norecurse nounwind uwtable "target-features"="+avx2
 attributes #1 = { nounwind uwtable }
 attributes #2 = { argmemonly nounwind }
 ;.
+; CGSCC: attributes #[[ATTR0]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "target-features"="+avx2" }
+; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) uwtable }
+; CGSCC: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
+; CGSCC: attributes #[[ATTR3]] = { nofree willreturn memory(write) }
+; CGSCC: attributes #[[ATTR4]] = { nofree nounwind willreturn }
+;.
 ; TUNIT: attributes #[[ATTR0]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "target-features"="+avx2" }
 ; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable }
 ; TUNIT: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
 ; TUNIT: attributes #[[ATTR3]] = { nofree willreturn memory(write) }
 ; TUNIT: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn }
 ;.
-; CGSCC: attributes #[[ATTR0]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "target-features"="+avx2" }
-; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) uwtable }
-; CGSCC: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
-; CGSCC: attributes #[[ATTR3]] = { nofree willreturn memory(write) }
-; CGSCC: attributes #[[ATTR4]] = { nofree nounwind willreturn }
+; CGSCC: [[META0]] = !{}
 ;.
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
index fffe50fde1e50..5b6c6e3c67fce 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
@@ -43,9 +43,9 @@ define void @avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr %arg)
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5:[0-9]+]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4:[0-9]+]]
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6:[0-9]+]]
+; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5:[0-9]+]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
@@ -56,9 +56,9 @@ define void @avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr %arg)
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5:[0-9]+]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4:[0-9]+]]
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6:[0-9]+]]
+; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5:[0-9]+]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -110,9 +110,9 @@ define void @avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr %arg)
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
@@ -123,9 +123,9 @@ define void @avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr %arg)
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -177,9 +177,9 @@ define void @avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr %arg)
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
@@ -190,9 +190,9 @@ define void @avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr %arg)
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -244,9 +244,9 @@ define void @avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr %arg)
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
@@ -257,9 +257,9 @@ define void @avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr %arg)
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -279,17 +279,21 @@ define internal fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal5
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256
-; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[ARG1:%.*]]) #[[ATTR1]] {
+; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR1]] {
 ; TUNIT-NEXT:  bb:
-; TUNIT-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1]], align 64
+; TUNIT-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
+; TUNIT-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
+; TUNIT-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1_PRIV]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP]], ptr [[ARG]], align 64
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256
-; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[ARG1:%.*]]) #[[ATTR1]] {
+; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR1]] {
 ; CGSCC-NEXT:  bb:
-; CGSCC-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1]], align 64, !invariant.load [[META0]]
+; CGSCC-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
+; CGSCC-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
+; CGSCC-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1_PRIV]], align 64, !invariant.load [[META0]]
 ; CGSCC-NEXT:    store <8 x i64> [[TMP]], ptr [[ARG]], align 64
 ; CGSCC-NEXT:    ret void
 ;
@@ -303,24 +307,26 @@ define void @avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr %arg)
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256
-; TUNIT-SAME: (ptr nofree writeonly captures(none) [[ARG:%.*]]) #[[ATTR2:[0-9]+]] {
+; TUNIT-SAME: (ptr nofree writeonly captures(none) [[ARG:%.*]]) #[[ATTR1]] {
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
-; TUNIT-NEXT:    call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[TMP]]) #[[ATTR6]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
+; TUNIT-NEXT:    call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 2 captures(none) dereferenceable(64) [[ARG:%.*]]) #[[ATTR2:[0-9]+]] {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 2 captures(none) dereferenceable(64) [[ARG:%.*]]) #[[ATTR1]] {
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
-; CGSCC-NEXT:    call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[TMP]]) #[[ATTR6]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
+; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
+; CGSCC-NEXT:    call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -340,17 +346,21 @@ define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal2
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256
-; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[ARG1:%.*]]) #[[ATTR2]] {
+; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR1]] {
 ; TUNIT-NEXT:  bb:
-; TUNIT-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1]], align 64
+; TUNIT-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
+; TUNIT-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
+; TUNIT-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1_PRIV]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP]], ptr [[ARG]], align 64
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256
-; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[ARG1:%.*]]) #[[ATTR2]] {
+; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR1]] {
 ; CGSCC-NEXT:  bb:
-; CGSCC-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1]], align 64, !invariant.load [[META0]]
+; CGSCC-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
+; CGSCC-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
+; CGSCC-NEXT:    [[TMP:%.*]] = load <8 x i64>, ptr [[ARG1_PRIV]], align 64, !invariant.load [[META0]]
 ; CGSCC-NEXT:    store <8 x i64> [[TMP]], ptr [[ARG]], align 64
 ; CGSCC-NEXT:    ret void
 ;
@@ -368,8 +378,9 @@ define void @avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr %arg)
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
-; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[TMP]]) #[[ATTR6]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
+; TUNIT-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
@@ -380,8 +391,9 @@ define void @avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr %arg)
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
-; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(64) [[TMP]]) #[[ATTR6]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
+; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
+; CGSCC-NEXT:    call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -401,7 +413,7 @@ define internal fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_p
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256
-; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] {
+; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] {
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
@@ -411,7 +423,7 @@ define internal fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_p
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256
-; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] {
+; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] {
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
@@ -429,26 +441,26 @@ define void @avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr %arg) #4 {
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256
-; TUNIT-SAME: (ptr nofree writeonly captures(none) [[ARG:%.*]]) #[[ATTR3]] {
+; TUNIT-SAME: (ptr nofree writeonly captures(none) [[ARG:%.*]]) #[[ATTR2]] {
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; TUNIT-NEXT:    call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; TUNIT-NEXT:    call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 2 captures(none) dereferenceable(64) [[ARG:%.*]]) #[[ATTR3]] {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 2 captures(none) dereferenceable(64) [[ARG:%.*]]) #[[ATTR2]] {
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; CGSCC-NEXT:    call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; CGSCC-NEXT:    call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -468,7 +480,7 @@ define internal fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_p
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256
-; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR3]] {
+; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR2]] {
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
@@ -478,7 +490,7 @@ define internal fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_p
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256
-; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR3]] {
+; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) #[[ATTR2]] {
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[ARG1_PRIV:%.*]] = alloca <8 x i64>, align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP0]], ptr [[ARG1_PRIV]], align 64
@@ -496,26 +508,26 @@ define void @avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr %arg) #3 {
 ;
 ; TUNIT: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; TUNIT-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256
-; TUNIT-SAME: (ptr nofree writeonly captures(none) [[ARG:%.*]]) #[[ATTR3]] {
+; TUNIT-SAME: (ptr nofree writeonly captures(none) [[ARG:%.*]]) #[[ATTR2]] {
 ; TUNIT-NEXT:  bb:
 ; TUNIT-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; TUNIT-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; TUNIT-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 32 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; TUNIT-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; TUNIT-NEXT:    call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; TUNIT-NEXT:    call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; TUNIT-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
 ; CGSCC-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256
-; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 2 captures(none) dereferenceable(64) [[ARG:%.*]]) #[[ATTR3]] {
+; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 2 captures(none) dereferenceable(64) [[ARG:%.*]]) #[[ATTR2]] {
 ; CGSCC-NEXT:  bb:
 ; CGSCC-NEXT:    [[TMP:%.*]] = alloca <8 x i64>, align 32
 ; CGSCC-NEXT:    [[TMP2:%.*]] = alloca <8 x i64>, align 32
-; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR5]]
+; CGSCC-NEXT:    call void @llvm.memset.p0.i64(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP]], i8 noundef 0, i64 noundef 32, i1 noundef false) #[[ATTR4]]
 ; CGSCC-NEXT:    [[TMP0:%.*]] = load <8 x i64>, ptr [[TMP]], align 64
-; CGSCC-NEXT:    call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR6]]
+; CGSCC-NEXT:    call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(ptr noalias nofree noundef nonnull writeonly align 64 captures(none) dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) #[[ATTR5]]
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load <8 x i64>, ptr [[TMP2]], align 64
 ; CGSCC-NEXT:    store <8 x i64> [[TMP4]], ptr [[ARG]], align 2
 ; CGSCC-NEXT:    ret void
@@ -542,19 +554,17 @@ attributes #5 = { argmemonly nounwind }
 ;.
 ; CGSCC: attributes #[[ATTR0]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="512" "target-features"="+avx512vl" }
 ; CGSCC: attributes #[[ATTR1]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx512vl" }
-; CGSCC: attributes #[[ATTR2]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="256" "prefer-vector-width"="256" "target-features"="+avx512vl" }
-; CGSCC: attributes #[[ATTR3]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx2" }
-; CGSCC: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
-; CGSCC: attributes #[[ATTR5]] = { nofree willreturn memory(write) }
-; CGSCC: attributes #[[ATTR6]] = { nofree nounwind willreturn }
+; CGSCC: attributes #[[ATTR2]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx2" }
+; CGSCC: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
+; CGSCC: attributes #[[ATTR4]] = { nofree willreturn memory(write) }
+; CGSCC: attributes #[[ATTR5]] = { nofree nounwind willreturn }
 ;.
 ; TUNIT: attributes #[[ATTR0]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="512" "target-features"="+avx512vl" }
 ; TUNIT: attributes #[[ATTR1]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx512vl" }
-; TUNIT: attributes #[[ATTR2]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="256" "prefer-vector-width"="256" "target-features"="+avx512vl" }
-; TUNIT: attributes #[[ATTR3]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx2" }
-; TUNIT: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
-; TUNIT: attributes #[[ATTR5]] = { nofree willreturn memory(write) }
-; TUNIT: attributes #[[ATTR6]] = { nofree nosync nounwind willreturn }
+; TUNIT: attributes #[[ATTR2]] = { inlinehint mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable "min-legal-vector-width"="512" "prefer-vector-width"="256" "target-features"="+avx2" }
+; TUNIT: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
+; TUNIT: attributes #[[ATTR4]] = { nofree willreturn memory(write) }
+; TUNIT: attributes #[[ATTR5]] = { nofree nosync nounwind willreturn }
 ;.
 ; CGSCC: [[META0]] = !{}
 ;.
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/array.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/array.ll
index 81497d8d2bb8e..03a04a2588200 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/array.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/array.ll
@@ -10,17 +10,13 @@ define void @caller() {
 ; TUNIT-LABEL: define {{[^@]+}}@caller() {
 ; TUNIT-NEXT:  entry:
 ; TUNIT-NEXT:    [[LEFT:%.*]] = alloca [3 x i32], align 4
-; TUNIT-NEXT:    [[TMP0:%.*]] = load i32, ptr [[LEFT]], align 4
-; TUNIT-NEXT:    [[LEFT_B4:%.*]] = getelementptr i8, ptr [[LEFT]], i64 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[LEFT_B4]], align 4
-; TUNIT-NEXT:    [[LEFT_B8:%.*]] = getelementptr i8, ptr [[LEFT]], i64 8
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[LEFT_B8]], align 4
-; TUNIT-NEXT:    call void @callee(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]])
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[LEFT]], align 4
+; TUNIT-NEXT:    call void @callee(<2 x i64> [[TMP0]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@caller() {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    call void @callee(i32 undef, i32 undef, i32 undef)
+; CGSCC-NEXT:    call void @callee(<2 x i64> undef)
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -32,14 +28,10 @@ entry:
 define internal void @callee(ptr noalias %arg) {
 ; CHECK: Function Attrs: memory(readwrite, argmem: none)
 ; CHECK-LABEL: define {{[^@]+}}@callee
-; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: (<2 x i64> [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[ARG_PRIV:%.*]] = alloca [3 x i32], align 4
-; CHECK-NEXT:    store i32 [[TMP0]], ptr [[ARG_PRIV]], align 4
-; CHECK-NEXT:    [[ARG_PRIV_B4:%.*]] = getelementptr i8, ptr [[ARG_PRIV]], i64 4
-; CHECK-NEXT:    store i32 [[TMP1]], ptr [[ARG_PRIV_B4]], align 4
-; CHECK-NEXT:    [[ARG_PRIV_B8:%.*]] = getelementptr i8, ptr [[ARG_PRIV]], i64 8
-; CHECK-NEXT:    store i32 [[TMP2]], ptr [[ARG_PRIV_B8]], align 4
+; CHECK-NEXT:    [[ARG_PRIV:%.*]] = alloca <2 x i64>, align 16
+; CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[ARG_PRIV]], align 16
 ; CHECK-NEXT:    call void @use(ptr noalias nofree noundef nonnull readonly align 4 captures(none) dereferenceable(12) [[ARG_PRIV]])
 ; CHECK-NEXT:    ret void
 ;
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
index f8e0543ce2596..11dd792e77283 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
@@ -9,14 +9,12 @@ define internal i32 @f(ptr byval(%struct.ss) %b, ptr byval(i32) %X, i32 %i) noun
 ;
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define {{[^@]+}}@f
-; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: (<2 x i64> [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[X_PRIV:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    store i32 [[TMP2]], ptr [[X_PRIV]], align 4
-; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
-; CHECK-NEXT:    store i32 [[TMP0]], ptr [[B_PRIV]], align 4
-; CHECK-NEXT:    [[B_PRIV_B4:%.*]] = getelementptr i8, ptr [[B_PRIV]], i64 4
-; CHECK-NEXT:    store i64 [[TMP1]], ptr [[B_PRIV_B4]], align 4
+; CHECK-NEXT:    store i32 [[TMP1]], ptr [[X_PRIV]], align 4
+; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca <2 x i64>, align 16
+; CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[B_PRIV]], align 16
 ; CHECK-NEXT:    [[VAL1:%.*]] = load i32, ptr [[B_PRIV]], align 8
 ; CHECK-NEXT:    [[VAL2:%.*]] = add i32 [[VAL1]], 1
 ; CHECK-NEXT:    store i32 [[VAL2]], ptr [[B_PRIV]], align 8
@@ -47,11 +45,9 @@ define i32 @test(ptr %X) {
 ; TUNIT-NEXT:    [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
 ; TUNIT-NEXT:    store i32 1, ptr [[S]], align 8
 ; TUNIT-NEXT:    [[VAL4:%.*]] = getelementptr [[STRUCT_SS]], ptr [[S]], i32 0, i32 1
-; TUNIT-NEXT:    [[TMP0:%.*]] = load i32, ptr [[S]], align 8
-; TUNIT-NEXT:    [[S_B4:%.*]] = getelementptr i8, ptr [[S]], i64 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr [[S_B4]], align 8
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[X]], align 4
-; TUNIT-NEXT:    [[C:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]]) #[[ATTR2:[0-9]+]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[S]], align 8
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[X]], align 4
+; TUNIT-NEXT:    [[C:%.*]] = call i32 @f(<2 x i64> [[TMP0]], i32 [[TMP1]]) #[[ATTR2:[0-9]+]]
 ; TUNIT-NEXT:    ret i32 [[C]]
 ;
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
@@ -59,9 +55,12 @@ define i32 @test(ptr %X) {
 ; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[X:%.*]]) #[[ATTR1:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
+; CGSCC-NEXT:    store i32 1, ptr [[S]], align 8
 ; CGSCC-NEXT:    [[VAL4:%.*]] = getelementptr [[STRUCT_SS]], ptr [[S]], i32 0, i32 1
-; CGSCC-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X]], align 4
-; CGSCC-NEXT:    [[C:%.*]] = call i32 @f(i32 noundef 1, i64 noundef 2, i32 [[TMP0]]) #[[ATTR2:[0-9]+]]
+; CGSCC-NEXT:    store i64 2, ptr [[VAL4]], align 4
+; CGSCC-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[S]], align 8
+; CGSCC-NEXT:    [[TMP1:%.*]] = load i32, ptr [[X]], align 4
+; CGSCC-NEXT:    [[C:%.*]] = call i32 @f(<2 x i64> [[TMP0]], i32 [[TMP1]]) #[[ATTR2:[0-9]+]]
 ; CGSCC-NEXT:    ret i32 [[C]]
 ;
 entry:
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll
index 82626e58d26dd..cc6516aea3f53 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll
@@ -7,14 +7,12 @@
 define internal void @f(ptr byval(%struct.ss)  %b, ptr byval(i32) %X) nounwind  {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define {{[^@]+}}@f
-; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: (<2 x i64> [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[X_PRIV:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    store i32 [[TMP2]], ptr [[X_PRIV]], align 4
-; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
-; CHECK-NEXT:    store i32 [[TMP0]], ptr [[B_PRIV]], align 4
-; CHECK-NEXT:    [[B_PRIV_B4:%.*]] = getelementptr i8, ptr [[B_PRIV]], i64 4
-; CHECK-NEXT:    store i64 [[TMP1]], ptr [[B_PRIV_B4]], align 4
+; CHECK-NEXT:    store i32 [[TMP1]], ptr [[X_PRIV]], align 4
+; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca <2 x i64>, align 16
+; CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[B_PRIV]], align 16
 ; CHECK-NEXT:    [[VAL1:%.*]] = load i32, ptr [[B_PRIV]], align 8
 ; CHECK-NEXT:    [[VAL2:%.*]] = add i32 [[VAL1]], 1
 ; CHECK-NEXT:    store i32 [[VAL2]], ptr [[B_PRIV]], align 8
@@ -39,11 +37,9 @@ define i32 @test(ptr %X) {
 ; TUNIT-NEXT:    [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
 ; TUNIT-NEXT:    store i32 1, ptr [[S]], align 8
 ; TUNIT-NEXT:    [[VAL4:%.*]] = getelementptr [[STRUCT_SS]], ptr [[S]], i32 0, i32 1
-; TUNIT-NEXT:    [[TMP0:%.*]] = load i32, ptr [[S]], align 8
-; TUNIT-NEXT:    [[S_B4:%.*]] = getelementptr i8, ptr [[S]], i64 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr [[S_B4]], align 8
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[X]], align 4
-; TUNIT-NEXT:    call void @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]]) #[[ATTR2:[0-9]+]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[S]], align 8
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[X]], align 4
+; TUNIT-NEXT:    call void @f(<2 x i64> [[TMP0]], i32 [[TMP1]]) #[[ATTR2:[0-9]+]]
 ; TUNIT-NEXT:    ret i32 0
 ;
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
@@ -51,7 +47,9 @@ define i32 @test(ptr %X) {
 ; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[X:%.*]]) #[[ATTR1:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8
+; CGSCC-NEXT:    store i32 1, ptr [[S]], align 8
 ; CGSCC-NEXT:    [[VAL4:%.*]] = getelementptr [[STRUCT_SS]], ptr [[S]], i32 0, i32 1
+; CGSCC-NEXT:    store i64 2, ptr [[VAL4]], align 4
 ; CGSCC-NEXT:    ret i32 0
 ;
 entry:
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
index 516b80b1e237b..f4e9ab5e0955d 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
@@ -9,12 +9,10 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1
 define internal i32 @f(ptr byval(%struct.ss)  %b) nounwind  {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define {{[^@]+}}@f
-; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: (<2 x i64> [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4
-; CHECK-NEXT:    store i32 [[TMP0]], ptr [[B_PRIV]], align 4
-; CHECK-NEXT:    [[B_PRIV_B4:%.*]] = getelementptr i8, ptr [[B_PRIV]], i64 4
-; CHECK-NEXT:    store i64 [[TMP1]], ptr [[B_PRIV_B4]], align 4
+; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca <2 x i64>, align 16
+; CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[B_PRIV]], align 16
 ; CHECK-NEXT:    [[VAL1:%.*]] = load i32, ptr [[B_PRIV]], align 8
 ; CHECK-NEXT:    [[VAL2:%.*]] = add i32 [[VAL1]], 1
 ; CHECK-NEXT:    store i32 [[VAL2]], ptr [[B_PRIV]], align 8
@@ -31,12 +29,10 @@ entry:
 define internal i32 @g(ptr byval(%struct.ss) align 32 %b) nounwind {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define {{[^@]+}}@g
-; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] {
+; CHECK-SAME: (<2 x i64> [[TMP0:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4
-; CHECK-NEXT:    store i32 [[TMP0]], ptr [[B_PRIV]], align 4
-; CHECK-NEXT:    [[B_PRIV_B4:%.*]] = getelementptr i8, ptr [[B_PRIV]], i64 4
-; CHECK-NEXT:    store i64 [[TMP1]], ptr [[B_PRIV_B4]], align 4
+; CHECK-NEXT:    [[B_PRIV:%.*]] = alloca <2 x i64>, align 16
+; CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[B_PRIV]], align 16
 ; CHECK-NEXT:    [[VAL1:%.*]] = load i32, ptr [[B_PRIV]], align 32
 ; CHECK-NEXT:    [[VAL2:%.*]] = add i32 [[VAL1]], 1
 ; CHECK-NEXT:    store i32 [[VAL2]], ptr [[B_PRIV]], align 32
@@ -58,14 +54,10 @@ define i32 @main() nounwind  {
 ; TUNIT-NEXT:    [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4
 ; TUNIT-NEXT:    store i32 1, ptr [[S]], align 32
 ; TUNIT-NEXT:    [[VAL4:%.*]] = getelementptr [[STRUCT_SS]], ptr [[S]], i32 0, i32 1
-; TUNIT-NEXT:    [[TMP0:%.*]] = load i32, ptr [[S]], align 8
-; TUNIT-NEXT:    [[S_B4:%.*]] = getelementptr i8, ptr [[S]], i64 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr [[S_B4]], align 8
-; TUNIT-NEXT:    [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) #[[ATTR1:[0-9]+]]
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[S]], align 32
-; TUNIT-NEXT:    [[S_B41:%.*]] = getelementptr i8, ptr [[S]], i64 4
-; TUNIT-NEXT:    [[TMP3:%.*]] = load i64, ptr [[S_B41]], align 32
-; TUNIT-NEXT:    [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) #[[ATTR1]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[S]], align 8
+; TUNIT-NEXT:    [[C0:%.*]] = call i32 @f(<2 x i64> [[TMP0]]) #[[ATTR1:[0-9]+]]
+; TUNIT-NEXT:    [[TMP1:%.*]] = load <2 x i64>, ptr [[S]], align 32
+; TUNIT-NEXT:    [[C1:%.*]] = call i32 @g(<2 x i64> [[TMP1]]) #[[ATTR1]]
 ; TUNIT-NEXT:    [[A:%.*]] = add i32 [[C0]], [[C1]]
 ; TUNIT-NEXT:    ret i32 [[A]]
 ;
@@ -74,9 +66,13 @@ define i32 @main() nounwind  {
 ; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
 ; CGSCC-NEXT:    [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4
+; CGSCC-NEXT:    store i32 1, ptr [[S]], align 32
 ; CGSCC-NEXT:    [[VAL4:%.*]] = getelementptr [[STRUCT_SS]], ptr [[S]], i32 0, i32 1
-; CGSCC-NEXT:    [[C0:%.*]] = call i32 @f(i32 noundef 1, i64 noundef 2) #[[ATTR2:[0-9]+]]
-; CGSCC-NEXT:    [[C1:%.*]] = call i32 @g(i32 noundef 1, i64 noundef 2) #[[ATTR2]]
+; CGSCC-NEXT:    store i64 2, ptr [[VAL4]], align 4
+; CGSCC-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[S]], align 32
+; CGSCC-NEXT:    [[C0:%.*]] = call i32 @f(<2 x i64> [[TMP0]]) #[[ATTR2:[0-9]+]]
+; CGSCC-NEXT:    [[TMP1:%.*]] = load <2 x i64>, ptr [[S]], align 32
+; CGSCC-NEXT:    [[C1:%.*]] = call i32 @g(<2 x i64> [[TMP1]]) #[[ATTR2]]
 ; CGSCC-NEXT:    [[A:%.*]] = add i32 [[C0]], [[C1]]
 ; CGSCC-NEXT:    ret i32 [[A]]
 ;
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
index 274181fa8b9ef..6db7503e2ca94 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
@@ -78,17 +78,15 @@ define internal i64 @AccessPaddingOfStruct(ptr byval(%struct.Foo) %a) {
 define internal i64 @CaptureAStruct(ptr byval(%struct.Foo) %a) {
 ; CGSCC: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@CaptureAStruct
-; CGSCC-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] {
+; CGSCC-SAME: (<2 x i64> [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    [[A_PRIV:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
-; CGSCC-NEXT:    store i32 [[TMP0]], ptr [[A_PRIV]], align 4
-; CGSCC-NEXT:    [[A_PRIV_B8:%.*]] = getelementptr i8, ptr [[A_PRIV]], i64 8
-; CGSCC-NEXT:    store i64 [[TMP1]], ptr [[A_PRIV_B8]], align 8
+; CGSCC-NEXT:    [[A_PRIV:%.*]] = alloca <2 x i64>, align 16
+; CGSCC-NEXT:    store <2 x i64> [[TMP0]], ptr [[A_PRIV]], align 16
 ; CGSCC-NEXT:    [[A_PTR:%.*]] = alloca ptr, align 8
 ; CGSCC-NEXT:    br label [[LOOP:%.*]]
 ; CGSCC:       loop:
 ; CGSCC-NEXT:    [[PHI:%.*]] = phi ptr [ null, [[ENTRY:%.*]] ], [ [[A_PRIV]], [[LOOP]] ]
-; CGSCC-NEXT:    [[TMP2:%.*]] = phi ptr [ [[A_PRIV]], [[ENTRY]] ], [ [[TMP2]], [[LOOP]] ]
+; CGSCC-NEXT:    [[TMP1:%.*]] = phi ptr [ [[A_PRIV]], [[ENTRY]] ], [ [[TMP1]], [[LOOP]] ]
 ; CGSCC-NEXT:    br label [[LOOP]]
 ;
 entry:
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll
index 00e44ea53797d..b9c2110428833 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll
@@ -12,22 +12,18 @@ declare ptr @foo(ptr)
 define internal void @bar(ptr byval(%pair) %Data) {
 ; TUNIT: Function Attrs: memory(readwrite, argmem: none)
 ; TUNIT-LABEL: define {{[^@]+}}@bar
-; TUNIT-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
-; TUNIT-NEXT:    [[DATA_PRIV:%.*]] = alloca [[PAIR:%.*]], align 8
-; TUNIT-NEXT:    store i32 [[TMP0]], ptr [[DATA_PRIV]], align 4
-; TUNIT-NEXT:    [[DATA_PRIV_B4:%.*]] = getelementptr i8, ptr [[DATA_PRIV]], i64 4
-; TUNIT-NEXT:    store i32 [[TMP1]], ptr [[DATA_PRIV_B4]], align 4
-; TUNIT-NEXT:    [[TMP3:%.*]] = call ptr @foo(ptr nonnull dereferenceable(8) [[DATA_PRIV]])
+; TUNIT-SAME: (i64 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+; TUNIT-NEXT:    [[DATA_PRIV:%.*]] = alloca i64, align 8
+; TUNIT-NEXT:    store i64 [[TMP0]], ptr [[DATA_PRIV]], align 8
+; TUNIT-NEXT:    [[TMP2:%.*]] = call ptr @foo(ptr nonnull dereferenceable(8) [[DATA_PRIV]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC: Function Attrs: memory(readwrite, argmem: none)
 ; CGSCC-LABEL: define {{[^@]+}}@bar
-; CGSCC-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
-; CGSCC-NEXT:    [[DATA_PRIV:%.*]] = alloca [[PAIR:%.*]], align 8
-; CGSCC-NEXT:    store i32 [[TMP0]], ptr [[DATA_PRIV]], align 4
-; CGSCC-NEXT:    [[DATA_PRIV_B4:%.*]] = getelementptr i8, ptr [[DATA_PRIV]], i64 4
-; CGSCC-NEXT:    store i32 [[TMP1]], ptr [[DATA_PRIV_B4]], align 4
-; CGSCC-NEXT:    [[TMP3:%.*]] = call ptr @foo(ptr noundef nonnull dereferenceable(8) [[DATA_PRIV]])
+; CGSCC-SAME: (i64 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+; CGSCC-NEXT:    [[DATA_PRIV:%.*]] = alloca i64, align 8
+; CGSCC-NEXT:    store i64 [[TMP0]], ptr [[DATA_PRIV]], align 8
+; CGSCC-NEXT:    [[TMP2:%.*]] = call ptr @foo(ptr noundef nonnull dereferenceable(8) [[DATA_PRIV]])
 ; CGSCC-NEXT:    ret void
 ;
   tail call ptr @foo(ptr %Data)
@@ -37,18 +33,14 @@ define internal void @bar(ptr byval(%pair) %Data) {
 define void @zed(ptr byval(%pair) %Data) {
 ; TUNIT-LABEL: define {{[^@]+}}@zed
 ; TUNIT-SAME: (ptr noalias nonnull readonly byval([[PAIR:%.*]]) captures(none) dereferenceable(8) [[DATA:%.*]]) {
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[DATA]], align 1
-; TUNIT-NEXT:    [[DATA_B4:%.*]] = getelementptr i8, ptr [[DATA]], i64 4
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DATA_B4]], align 1
-; TUNIT-NEXT:    call void @bar(i32 [[TMP1]], i32 [[TMP2]])
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr [[DATA]], align 1
+; TUNIT-NEXT:    call void @bar(i64 [[TMP1]])
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define {{[^@]+}}@zed
 ; CGSCC-SAME: (ptr noalias nofree noundef nonnull readonly byval([[PAIR:%.*]]) captures(none) dereferenceable(8) [[DATA:%.*]]) {
-; CGSCC-NEXT:    [[TMP1:%.*]] = load i32, ptr [[DATA]], align 1
-; CGSCC-NEXT:    [[DATA_B4:%.*]] = getelementptr i8, ptr [[DATA]], i64 4
-; CGSCC-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DATA_B4]], align 1
-; CGSCC-NEXT:    call void @bar(i32 [[TMP1]], i32 [[TMP2]])
+; CGSCC-NEXT:    [[TMP1:%.*]] = load i64, ptr [[DATA]], align 1
+; CGSCC-NEXT:    call void @bar(i64 [[TMP1]])
 ; CGSCC-NEXT:    ret void
 ;
   call void @bar(ptr byval(%pair) %Data)
diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
index 249119a77a4d0..c1c4c49de15b3 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll
@@ -14,14 +14,12 @@ declare void @use(i8)
 define internal void @vfu1(ptr byval(%struct.MYstr) align 4 %u) nounwind {
 ; CHECK: Function Attrs: nounwind memory(readwrite, argmem: none)
 ; CHECK-LABEL: define {{[^@]+}}@vfu1
-; CHECK-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-SAME: (i64 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8
-; CHECK-NEXT:    store i8 [[TMP0]], ptr [[U_PRIV]], align 1
-; CHECK-NEXT:    [[U_PRIV_B4:%.*]] = getelementptr i8, ptr [[U_PRIV]], i64 4
-; CHECK-NEXT:    store i32 [[TMP1]], ptr [[U_PRIV_B4]], align 4
-; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], ptr [[U_PRIV]], i32 0, i32 1
-; CHECK-NEXT:    store i32 99, ptr [[TMP2]], align 4
+; CHECK-NEXT:    [[U_PRIV:%.*]] = alloca i64, align 8
+; CHECK-NEXT:    store i64 [[TMP0]], ptr [[U_PRIV]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], ptr [[U_PRIV]], i32 0, i32 1
+; CHECK-NEXT:    store i32 99, ptr [[TMP1]], align 4
 ; CHECK-NEXT:    store i8 97, ptr [[U_PRIV]], align 8
 ; CHECK-NEXT:    [[L:%.*]] = load i8, ptr [[U_PRIV]], align 8
 ; CHECK-NEXT:    call void @use(i8 [[L]])
@@ -45,18 +43,16 @@ return:                                           ; preds = %entry
 define internal i32 @vfu2(ptr byval(%struct.MYstr) align 4 %u) nounwind readonly {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define {{[^@]+}}@vfu2
-; CHECK-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-SAME: (i64 [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8
-; CHECK-NEXT:    store i8 [[TMP0]], ptr [[U_PRIV]], align 1
-; CHECK-NEXT:    [[U_PRIV_B4:%.*]] = getelementptr i8, ptr [[U_PRIV]], i64 4
-; CHECK-NEXT:    store i32 [[TMP1]], ptr [[U_PRIV_B4]], align 4
-; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], ptr [[U_PRIV]], i32 0, i32 1
-; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT:    [[TMP4:%.*]] = load i8, ptr [[U_PRIV]], align 8
-; CHECK-NEXT:    [[TMP5:%.*]] = zext i8 [[TMP4]] to i32
-; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[TMP5]], [[TMP3]]
-; CHECK-NEXT:    ret i32 [[TMP6]]
+; CHECK-NEXT:    [[U_PRIV:%.*]] = alloca i64, align 8
+; CHECK-NEXT:    store i64 [[TMP0]], ptr [[U_PRIV]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], ptr [[U_PRIV]], i32 0, i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4, !invariant.load [[META0:![0-9]+]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load i8, ptr [[U_PRIV]], align 8, !invariant.load [[META0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP2]]
+; CHECK-NEXT:    ret i32 [[TMP5]]
 ;
 entry:
   %0 = getelementptr %struct.MYstr, ptr %u, i32 0, i32 1 ; <ptr> [#uses=1]
@@ -73,28 +69,20 @@ define i32 @unions() nounwind {
 ; TUNIT-LABEL: define {{[^@]+}}@unions
 ; TUNIT-SAME: () #[[ATTR2:[0-9]+]] {
 ; TUNIT-NEXT:  entry:
-; TUNIT-NEXT:    [[TMP0:%.*]] = load i8, ptr @mystr, align 8
-; TUNIT-NEXT:    [[MYSTR_B41:%.*]] = getelementptr i8, ptr @mystr, i64 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[MYSTR_B41]], align 8
-; TUNIT-NEXT:    call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR2]]
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i8, ptr @mystr, align 8
-; TUNIT-NEXT:    [[MYSTR_B4:%.*]] = getelementptr i8, ptr @mystr, i64 4
-; TUNIT-NEXT:    [[TMP3:%.*]] = load i32, ptr [[MYSTR_B4]], align 8
-; TUNIT-NEXT:    [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR3:[0-9]+]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load i64, ptr @mystr, align 8
+; TUNIT-NEXT:    call void @vfu1(i64 [[TMP0]]) #[[ATTR2]]
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr @mystr, align 8
+; TUNIT-NEXT:    [[RESULT:%.*]] = call i32 @vfu2(i64 [[TMP1]]) #[[ATTR3:[0-9]+]]
 ; TUNIT-NEXT:    ret i32 [[RESULT]]
 ;
 ; CGSCC: Function Attrs: nounwind
 ; CGSCC-LABEL: define {{[^@]+}}@unions
 ; CGSCC-SAME: () #[[ATTR2:[0-9]+]] {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    [[TMP0:%.*]] = load i8, ptr @mystr, align 8
-; CGSCC-NEXT:    [[MYSTR_B4:%.*]] = getelementptr i8, ptr @mystr, i64 4
-; CGSCC-NEXT:    [[TMP1:%.*]] = load i32, ptr [[MYSTR_B4]], align 8
-; CGSCC-NEXT:    call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR2]]
-; CGSCC-NEXT:    [[TMP2:%.*]] = load i8, ptr @mystr, align 8
-; CGSCC-NEXT:    [[MYSTR_B41:%.*]] = getelementptr i8, ptr @mystr, i64 4
-; CGSCC-NEXT:    [[TMP3:%.*]] = load i32, ptr [[MYSTR_B41]], align 8
-; CGSCC-NEXT:    [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR2]]
+; CGSCC-NEXT:    [[TMP0:%.*]] = load i64, ptr @mystr, align 8
+; CGSCC-NEXT:    call void @vfu1(i64 [[TMP0]]) #[[ATTR2]]
+; CGSCC-NEXT:    [[TMP1:%.*]] = load i64, ptr @mystr, align 8
+; CGSCC-NEXT:    [[RESULT:%.*]] = call i32 @vfu2(i64 [[TMP1]]) #[[ATTR2]]
 ; CGSCC-NEXT:    ret i32 [[RESULT]]
 ;
 entry:
@@ -106,20 +94,18 @@ entry:
 define internal i32 @vfu2_v2(ptr byval(%struct.MYstr) align 4 %u) nounwind readonly {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define {{[^@]+}}@vfu2_v2
-; CHECK-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1]] {
+; CHECK-SAME: (i64 [[TMP0:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8
-; CHECK-NEXT:    store i8 [[TMP0]], ptr [[U_PRIV]], align 1
-; CHECK-NEXT:    [[U_PRIV_B4:%.*]] = getelementptr i8, ptr [[U_PRIV]], i64 4
-; CHECK-NEXT:    store i32 [[TMP1]], ptr [[U_PRIV_B4]], align 4
-; CHECK-NEXT:    [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], ptr [[U_PRIV]], i32 0, i32 1
+; CHECK-NEXT:    [[U_PRIV:%.*]] = alloca i64, align 8
+; CHECK-NEXT:    store i64 [[TMP0]], ptr [[U_PRIV]], align 4
+; CHECK-NEXT:    [[Z:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], ptr [[U_PRIV]], i32 0, i32 1
 ; CHECK-NEXT:    store i32 99, ptr [[Z]], align 4
-; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], ptr [[U_PRIV]], i32 0, i32 1
-; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-; CHECK-NEXT:    [[TMP4:%.*]] = load i8, ptr [[U_PRIV]], align 8
-; CHECK-NEXT:    [[TMP5:%.*]] = zext i8 [[TMP4]] to i32
-; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[TMP5]], [[TMP3]]
-; CHECK-NEXT:    ret i32 [[TMP6]]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr [[STRUCT_MYSTR]], ptr [[U_PRIV]], i32 0, i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = load i8, ptr [[U_PRIV]], align 8
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i8 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP2]]
+; CHECK-NEXT:    ret i32 [[TMP5]]
 ;
 entry:
   %z = getelementptr %struct.MYstr, ptr %u, i32 0, i32 1
@@ -138,22 +124,18 @@ define i32 @unions_v2() nounwind {
 ; TUNIT-LABEL: define {{[^@]+}}@unions_v2
 ; TUNIT-SAME: () #[[ATTR2]] {
 ; TUNIT-NEXT:  entry:
-; TUNIT-NEXT:    [[TMP0:%.*]] = load i8, ptr @mystr, align 8
-; TUNIT-NEXT:    [[MYSTR_B41:%.*]] = getelementptr i8, ptr @mystr, i64 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[MYSTR_B41]], align 8
-; TUNIT-NEXT:    call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR2]]
-; TUNIT-NEXT:    [[TMP2:%.*]] = load i8, ptr @mystr, align 8
-; TUNIT-NEXT:    [[MYSTR_B4:%.*]] = getelementptr i8, ptr @mystr, i64 4
-; TUNIT-NEXT:    [[TMP3:%.*]] = load i32, ptr [[MYSTR_B4]], align 8
-; TUNIT-NEXT:    [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR3]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load i64, ptr @mystr, align 8
+; TUNIT-NEXT:    call void @vfu1(i64 [[TMP0]]) #[[ATTR2]]
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr @mystr, align 8
+; TUNIT-NEXT:    [[RESULT:%.*]] = call i32 @vfu2_v2(i64 [[TMP1]]) #[[ATTR3]]
 ; TUNIT-NEXT:    ret i32 [[RESULT]]
 ;
 ; CGSCC: Function Attrs: nounwind
 ; CGSCC-LABEL: define {{[^@]+}}@unions_v2
 ; CGSCC-SAME: () #[[ATTR2]] {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    call void @vfu1(i8 noundef 0, i32 noundef 0) #[[ATTR2]]
-; CGSCC-NEXT:    [[RESULT:%.*]] = call i32 @vfu2_v2(i8 noundef 0, i32 noundef 0) #[[ATTR2]]
+; CGSCC-NEXT:    call void @vfu1(i64 noundef 0) #[[ATTR2]]
+; CGSCC-NEXT:    [[RESULT:%.*]] = call i32 @vfu2_v2(i64 noundef 0) #[[ATTR2]]
 ; CGSCC-NEXT:    ret i32 [[RESULT]]
 ;
 entry:
@@ -171,3 +153,7 @@ entry:
 ; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
 ; CGSCC: attributes #[[ATTR2]] = { nounwind }
 ;.
+; TUNIT: [[META0]] = !{}
+;.
+; CGSCC: [[META0]] = !{}
+;.
diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll
index 18adaf437f938..f7851d963865e 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -2464,9 +2464,9 @@ define float @user(float %arg) {
 define internal float @through_memory0(ptr %ptr.arg) {
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define internal float @through_memory0
-; CGSCC-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
-; CGSCC-NEXT:    store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
+; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR3]] {
+; CGSCC-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca i32, align 4
+; CGSCC-NEXT:    store i32 [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
 ; CGSCC-NEXT:    [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4, !invariant.load [[META0]]
 ; CGSCC-NEXT:    ret float [[LOAD]]
 ;
@@ -2478,18 +2478,18 @@ define internal float @through_memory0(ptr %ptr.arg) {
 define internal float @through_memory1(ptr %ptr.arg) {
 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; TUNIT-LABEL: define internal float @through_memory1
-; TUNIT-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] {
-; TUNIT-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
-; TUNIT-NEXT:    store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
+; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR3]] {
+; TUNIT-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca i32, align 4
+; TUNIT-NEXT:    store i32 [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
 ; TUNIT-NEXT:    [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4
 ; TUNIT-NEXT:    [[CALL:%.*]] = call float @llvm.arithmetic.fence.f32(float [[LOAD]]) #[[ATTR26]]
 ; TUNIT-NEXT:    ret float [[CALL]]
 ;
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define internal float @through_memory1
-; CGSCC-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
-; CGSCC-NEXT:    store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
+; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR3]] {
+; CGSCC-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca i32, align 4
+; CGSCC-NEXT:    store i32 [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
 ; CGSCC-NEXT:    [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4, !invariant.load [[META0]]
 ; CGSCC-NEXT:    [[CALL:%.*]] = call float @llvm.arithmetic.fence.f32(float [[LOAD]]) #[[ATTR23]]
 ; CGSCC-NEXT:    ret float [[CALL]]
@@ -2503,9 +2503,9 @@ define internal float @through_memory1(ptr %ptr.arg) {
 define internal float @through_memory2(ptr %ptr.arg) {
 ; CHECK: Function Attrs: memory(readwrite, argmem: none)
 ; CHECK-LABEL: define internal float @through_memory2
-; CHECK-SAME: (float [[TMP0:%.*]]) #[[ATTR15:[0-9]+]] {
-; CHECK-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
-; CHECK-NEXT:    store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR15:[0-9]+]] {
+; CHECK-NEXT:    [[PTR_ARG_PRIV:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    store i32 [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
 ; CHECK-NEXT:    [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4, !invariant.load [[META0]]
 ; CHECK-NEXT:    [[CALL:%.*]] = call float @extern.f32(float [[LOAD]])
 ; CHECK-NEXT:    ret float [[CALL]]
@@ -2528,7 +2528,8 @@ define float @call_through_memory0(float nofpclass(nan) %val) {
 ; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR4]] {
 ; CGSCC-NEXT:    [[ALLOCA:%.*]] = alloca float, align 4
 ; CGSCC-NEXT:    store float [[VAL]], ptr [[ALLOCA]], align 4
-; CGSCC-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory0(float nofpclass(nan) [[VAL]]) #[[ATTR23]]
+; CGSCC-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ALLOCA]], align 4
+; CGSCC-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory0(i32 [[TMP1]]) #[[ATTR23]]
 ; CGSCC-NEXT:    ret float [[THROUGH_MEMORY]]
 ;
   %alloca = alloca float
@@ -2543,8 +2544,8 @@ define float @call_through_memory1(float nofpclass(nan) %val) {
 ; TUNIT-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR3]] {
 ; TUNIT-NEXT:    [[ALLOCA:%.*]] = alloca float, align 4
 ; TUNIT-NEXT:    store float [[VAL]], ptr [[ALLOCA]], align 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load float, ptr [[ALLOCA]], align 4
-; TUNIT-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory1(float [[TMP1]]) #[[ATTR25]]
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ALLOCA]], align 4
+; TUNIT-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory1(i32 [[TMP1]]) #[[ATTR25]]
 ; TUNIT-NEXT:    ret float [[THROUGH_MEMORY]]
 ;
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
@@ -2552,7 +2553,8 @@ define float @call_through_memory1(float nofpclass(nan) %val) {
 ; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR4]] {
 ; CGSCC-NEXT:    [[ALLOCA:%.*]] = alloca float, align 4
 ; CGSCC-NEXT:    store float [[VAL]], ptr [[ALLOCA]], align 4
-; CGSCC-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory1(float nofpclass(nan) [[VAL]]) #[[ATTR23]]
+; CGSCC-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ALLOCA]], align 4
+; CGSCC-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory1(i32 [[TMP1]]) #[[ATTR23]]
 ; CGSCC-NEXT:    ret float [[THROUGH_MEMORY]]
 ;
   %alloca = alloca float
@@ -2562,20 +2564,13 @@ define float @call_through_memory1(float nofpclass(nan) %val) {
 }
 
 define float @call_through_memory2(float nofpclass(nan) %val) {
-; TUNIT-LABEL: define float @call_through_memory2
-; TUNIT-SAME: (float nofpclass(nan) [[VAL:%.*]]) {
-; TUNIT-NEXT:    [[ALLOCA:%.*]] = alloca float, align 4
-; TUNIT-NEXT:    store float [[VAL]], ptr [[ALLOCA]], align 4
-; TUNIT-NEXT:    [[TMP1:%.*]] = load float, ptr [[ALLOCA]], align 4
-; TUNIT-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory2(float [[TMP1]])
-; TUNIT-NEXT:    ret float [[THROUGH_MEMORY]]
-;
-; CGSCC-LABEL: define float @call_through_memory2
-; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) {
-; CGSCC-NEXT:    [[ALLOCA:%.*]] = alloca float, align 4
-; CGSCC-NEXT:    store float [[VAL]], ptr [[ALLOCA]], align 4
-; CGSCC-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory2(float nofpclass(nan) [[VAL]])
-; CGSCC-NEXT:    ret float [[THROUGH_MEMORY]]
+; CHECK-LABEL: define float @call_through_memory2
+; CHECK-SAME: (float nofpclass(nan) [[VAL:%.*]]) {
+; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca float, align 4
+; CHECK-NEXT:    store float [[VAL]], ptr [[ALLOCA]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ALLOCA]], align 4
+; CHECK-NEXT:    [[THROUGH_MEMORY:%.*]] = call float @through_memory2(i32 [[TMP1]])
+; CHECK-NEXT:    ret float [[THROUGH_MEMORY]]
 ;
   %alloca = alloca float
   store float %val, ptr %alloca
diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
index 3e07fe42261e9..ef5848a806593 100644
--- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
@@ -2654,12 +2654,8 @@ define dso_local void @test_nested_memory(ptr %dst, ptr %src) {
 ; TUNIT-NEXT:    [[SRC2:%.*]] = getelementptr inbounds i8, ptr [[CALL_H2S]], i64 8
 ; TUNIT-NEXT:    store ptr [[SRC]], ptr [[SRC2]], align 8
 ; TUNIT-NEXT:    store ptr [[CALL_H2S]], ptr getelementptr inbounds ([[STRUCT_STY]], ptr @global, i64 0, i32 2), align 8
-; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[LOCAL]], align 8
-; TUNIT-NEXT:    [[LOCAL_B8:%.*]] = getelementptr i8, ptr [[LOCAL]], i64 8
-; TUNIT-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[LOCAL_B8]], align 8
-; TUNIT-NEXT:    [[LOCAL_B16:%.*]] = getelementptr i8, ptr [[LOCAL]], i64 16
-; TUNIT-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[LOCAL_B16]], align 8
-; TUNIT-NEXT:    call fastcc void @nested_memory_callee(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]]) #[[ATTR21:[0-9]+]]
+; TUNIT-NEXT:    [[TMP0:%.*]] = load <3 x i64>, ptr [[LOCAL]], align 8
+; TUNIT-NEXT:    call fastcc void @nested_memory_callee(<3 x i64> [[TMP0]]) #[[ATTR21:[0-9]+]]
 ; TUNIT-NEXT:    ret void
 ;
 ; CGSCC-LABEL: define dso_local void @test_nested_memory(
@@ -2667,12 +2663,14 @@ define dso_local void @test_nested_memory(ptr %dst, ptr %src) {
 ; CGSCC-NEXT:  [[ENTRY:.*:]]
 ; CGSCC-NEXT:    [[LOCAL:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
 ; CGSCC-NEXT:    [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[LOCAL]], i64 0, i32 2
+; CGSCC-NEXT:    store ptr @global, ptr [[INNER]], align 8
 ; CGSCC-NEXT:    [[CALL:%.*]] = call noalias dereferenceable_or_null(24) ptr @malloc(i64 noundef 24)
 ; CGSCC-NEXT:    store ptr [[DST]], ptr [[CALL]], align 8
 ; CGSCC-NEXT:    [[SRC2:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8
 ; CGSCC-NEXT:    store ptr [[SRC]], ptr [[SRC2]], align 8
 ; CGSCC-NEXT:    store ptr [[CALL]], ptr getelementptr inbounds ([[STRUCT_STY]], ptr @global, i64 0, i32 2), align 8
-; CGSCC-NEXT:    call fastcc void @nested_memory_callee(ptr nofree align 4294967296 undef, ptr nofree align 4294967296 undef, ptr nofree noundef nonnull align 8 dereferenceable(24) @global) #[[ATTR24:[0-9]+]]
+; CGSCC-NEXT:    [[TMP0:%.*]] = load <3 x i64>, ptr [[LOCAL]], align 8
+; CGSCC-NEXT:    call fastcc void @nested_memory_callee(<3 x i64> [[TMP0]]) #[[ATTR24:[0-9]+]]
 ; CGSCC-NEXT:    ret void
 ;
 entry:
@@ -2689,17 +2687,13 @@ entry:
 }
 
 define internal fastcc void @nested_memory_callee(ptr nocapture readonly %S) nofree norecurse nounwind uwtable {
-; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn uwtable
+; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none) uwtable
 ; TUNIT-LABEL: define internal fastcc void @nested_memory_callee(
-; TUNIT-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR11:[0-9]+]] {
+; TUNIT-SAME: <3 x i64> [[TMP0:%.*]]) #[[ATTR11:[0-9]+]] {
 ; TUNIT-NEXT:  [[ENTRY:.*:]]
-; TUNIT-NEXT:    [[S_PRIV:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
-; TUNIT-NEXT:    store ptr [[TMP0]], ptr [[S_PRIV]], align 8
-; TUNIT-NEXT:    [[S_PRIV_B8:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 8
-; TUNIT-NEXT:    store ptr [[TMP1]], ptr [[S_PRIV_B8]], align 8
-; TUNIT-NEXT:    [[S_PRIV_B16:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 16
-; TUNIT-NEXT:    store ptr [[TMP2]], ptr [[S_PRIV_B16]], align 8
-; TUNIT-NEXT:    [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[S_PRIV]], i64 0, i32 2
+; TUNIT-NEXT:    [[S_PRIV:%.*]] = alloca <3 x i64>, align 32
+; TUNIT-NEXT:    store <3 x i64> [[TMP0]], ptr [[S_PRIV]], align 32
+; TUNIT-NEXT:    [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY:%.*]], ptr [[S_PRIV]], i64 0, i32 2
 ; TUNIT-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[INNER]], align 8, !invariant.load [[META32:![0-9]+]]
 ; TUNIT-NEXT:    [[INNER1:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[TMP3]], i64 0, i32 2
 ; TUNIT-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[INNER1]], align 8, !invariant.load [[META32]]
@@ -2711,17 +2705,13 @@ define internal fastcc void @nested_memory_callee(ptr nocapture readonly %S) nof
 ; TUNIT-NEXT:    store float [[CONV]], ptr [[TMP7]], align 4
 ; TUNIT-NEXT:    ret void
 ;
-; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn uwtable
+; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none) uwtable
 ; CGSCC-LABEL: define internal fastcc void @nested_memory_callee(
-; CGSCC-SAME: ptr nofree [[TMP0:%.*]], ptr nofree [[TMP1:%.*]], ptr nofree [[TMP2:%.*]]) #[[ATTR12:[0-9]+]] {
+; CGSCC-SAME: <3 x i64> [[TMP0:%.*]]) #[[ATTR12:[0-9]+]] {
 ; CGSCC-NEXT:  [[ENTRY:.*:]]
-; CGSCC-NEXT:    [[S_PRIV:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
-; CGSCC-NEXT:    store ptr [[TMP0]], ptr [[S_PRIV]], align 8
-; CGSCC-NEXT:    [[S_PRIV_B8:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 8
-; CGSCC-NEXT:    store ptr [[TMP1]], ptr [[S_PRIV_B8]], align 8
-; CGSCC-NEXT:    [[S_PRIV_B16:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 16
-; CGSCC-NEXT:    store ptr [[TMP2]], ptr [[S_PRIV_B16]], align 8
-; CGSCC-NEXT:    [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[S_PRIV]], i64 0, i32 2
+; CGSCC-NEXT:    [[S_PRIV:%.*]] = alloca <3 x i64>, align 32
+; CGSCC-NEXT:    store <3 x i64> [[TMP0]], ptr [[S_PRIV]], align 32
+; CGSCC-NEXT:    [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY:%.*]], ptr [[S_PRIV]], i64 0, i32 2
 ; CGSCC-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[INNER]], align 8, !invariant.load [[META32:![0-9]+]]
 ; CGSCC-NEXT:    [[INNER1:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[TMP3]], i64 0, i32 2
 ; CGSCC-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[INNER1]], align 8, !invariant.load [[META32]]
@@ -3630,7 +3620,7 @@ declare void @llvm.assume(i1 noundef)
 ; TUNIT: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" }
 ; TUNIT: attributes #[[ATTR9:[0-9]+]] = { allockind("free") "alloc-family"="malloc" }
 ; TUNIT: attributes #[[ATTR10:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
-; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn uwtable }
+; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none) uwtable }
 ; TUNIT: attributes #[[ATTR12]] = { nofree nosync nounwind memory(argmem: readwrite) }
 ; TUNIT: attributes #[[ATTR13]] = { nofree norecurse nosync nounwind memory(none) }
 ; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind }
@@ -3656,7 +3646,7 @@ declare void @llvm.assume(i1 noundef)
 ; CGSCC: attributes #[[ATTR9:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" }
 ; CGSCC: attributes #[[ATTR10:[0-9]+]] = { allockind("free") "alloc-family"="malloc" }
 ; CGSCC: attributes #[[ATTR11:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
-; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree norecurse nosync nounwind willreturn uwtable }
+; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none) uwtable }
 ; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
 ; CGSCC: attributes #[[ATTR14]] = { nofree nosync nounwind memory(argmem: readwrite) }
 ; CGSCC: attributes #[[ATTR15]] = { nofree nosync nounwind memory(none) }
diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
index beceab7ce9ed7..983753e8433ef 100644
--- a/llvm/test/Transforms/Attributor/value-simplify.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify.ll
@@ -117,11 +117,11 @@ define i32 @test2_1(i1 %c) {
 ; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3:[0-9]+]] {
 ; CGSCC-NEXT:    br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
 ; CGSCC:       if.true:
-; CGSCC-NEXT:    [[CALL:%.*]] = tail call i32 @return0() #[[ATTR12:[0-9]+]]
+; CGSCC-NEXT:    [[CALL:%.*]] = tail call i32 @return0() #[[ATTR13:[0-9]+]]
 ; CGSCC-NEXT:    [[RET0:%.*]] = add i32 [[CALL]], 1
 ; CGSCC-NEXT:    br label [[END:%.*]]
 ; CGSCC:       if.false:
-; CGSCC-NEXT:    [[RET1:%.*]] = tail call i32 @return1() #[[ATTR12]]
+; CGSCC-NEXT:    [[RET1:%.*]] = tail call i32 @return1() #[[ATTR13]]
 ; CGSCC-NEXT:    br label [[END]]
 ; CGSCC:       end:
 ; CGSCC-NEXT:    [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ [[RET1]], [[IF_FALSE]] ]
@@ -153,7 +153,7 @@ define i32 @test2_2(i1 %c) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test2_2
 ; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[RET:%.*]] = tail call noundef i32 @test2_1(i1 noundef [[C]]) #[[ATTR12]]
+; CGSCC-NEXT:    [[RET:%.*]] = tail call noundef i32 @test2_1(i1 noundef [[C]]) #[[ATTR13]]
 ; CGSCC-NEXT:    ret i32 [[RET]]
 ;
   %ret = tail call i32 @test2_1(i1 %c)
@@ -180,7 +180,7 @@ define void @test3(i1 %c) {
 ; CGSCC:       if.true:
 ; CGSCC-NEXT:    br label [[END:%.*]]
 ; CGSCC:       if.false:
-; CGSCC-NEXT:    [[RET1:%.*]] = tail call i32 @return1() #[[ATTR13:[0-9]+]]
+; CGSCC-NEXT:    [[RET1:%.*]] = tail call i32 @return1() #[[ATTR14:[0-9]+]]
 ; CGSCC-NEXT:    br label [[END]]
 ; CGSCC:       end:
 ; CGSCC-NEXT:    [[R:%.*]] = phi i32 [ 1, [[IF_TRUE]] ], [ [[RET1]], [[IF_FALSE]] ]
@@ -311,7 +311,7 @@ define i1 @ipccp2() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@ipccp2
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[R:%.*]] = call noundef i1 @ipccp2i() #[[ATTR12]]
+; CGSCC-NEXT:    [[R:%.*]] = call noundef i1 @ipccp2i() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i1 [[R]]
 ;
   %r = call i1 @ipccp2i(i1 true)
@@ -345,7 +345,7 @@ define i1 @ipccp2b() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@ipccp2b
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[R:%.*]] = call noundef i1 @ipccp2ib() #[[ATTR12]]
+; CGSCC-NEXT:    [[R:%.*]] = call noundef i1 @ipccp2ib() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i1 [[R]]
 ;
   %r = call i1 @ipccp2ib(i1 true)
@@ -380,7 +380,7 @@ define i32 @ipccp3() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@ipccp3
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[R:%.*]] = call noundef i32 @ipccp3i() #[[ATTR12]]
+; CGSCC-NEXT:    [[R:%.*]] = call noundef i32 @ipccp3i() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i32 [[R]]
 ;
   %r = call i32 @ipccp3i(i32 7)
@@ -409,7 +409,7 @@ define internal i32 @ipccp4ib(i32 %a) {
 ; CGSCC-SAME: () #[[ATTR3]] {
 ; CGSCC-NEXT:    br label [[T:%.*]]
 ; CGSCC:       t:
-; CGSCC-NEXT:    [[R:%.*]] = call noundef i32 @ipccp4ia(i1 noundef true) #[[ATTR12]]
+; CGSCC-NEXT:    [[R:%.*]] = call noundef i32 @ipccp4ia(i1 noundef true) #[[ATTR13]]
 ; CGSCC-NEXT:    ret i32 [[R]]
 ; CGSCC:       f:
 ; CGSCC-NEXT:    unreachable
@@ -440,7 +440,7 @@ define i32 @ipccp4(i1 %c) {
 ; CGSCC:       t:
 ; CGSCC-NEXT:    br label [[F]]
 ; CGSCC:       f:
-; CGSCC-NEXT:    [[R:%.*]] = call noundef i32 @ipccp4ib() #[[ATTR12]]
+; CGSCC-NEXT:    [[R:%.*]] = call noundef i32 @ipccp4ib() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i32 [[R]]
 ;
   br i1 %c, label %t, label %f
@@ -477,7 +477,7 @@ define ptr @complicated_args_inalloca(ptr %arg) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@complicated_args_inalloca
 ; CGSCC-SAME: (ptr nofree noundef nonnull readnone dereferenceable(4) [[ARG:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[CALL:%.*]] = call noalias noundef nonnull dereferenceable(4) ptr @test_inalloca(ptr noalias nofree noundef nonnull writeonly inalloca(i32) dereferenceable(4) [[ARG]]) #[[ATTR12]]
+; CGSCC-NEXT:    [[CALL:%.*]] = call noalias noundef nonnull dereferenceable(4) ptr @test_inalloca(ptr noalias nofree noundef nonnull writeonly inalloca(i32) dereferenceable(4) [[ARG]]) #[[ATTR13]]
 ; CGSCC-NEXT:    ret ptr [[CALL]]
 ;
   %call = call ptr @test_inalloca(ptr inalloca(i32) %arg)
@@ -508,8 +508,8 @@ define ptr @complicated_args_preallocated() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
 ; CGSCC-LABEL: define {{[^@]+}}@complicated_args_preallocated
 ; CGSCC-SAME: () #[[ATTR4:[0-9]+]] {
-; CGSCC-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR13]]
-; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @test_preallocated(ptr nofree noundef writeonly preallocated(i32) null) #[[ATTR14:[0-9]+]] [ "preallocated"(token [[C]]) ]
+; CGSCC-NEXT:    [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR14]]
+; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @test_preallocated(ptr nofree noundef writeonly preallocated(i32) null) #[[ATTR15:[0-9]+]] [ "preallocated"(token [[C]]) ]
 ; CGSCC-NEXT:    unreachable
 ;
   %c = call token @llvm.call.preallocated.setup(i32 1)
@@ -547,7 +547,7 @@ define void @complicated_args_sret(ptr %b) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: write)
 ; CGSCC-LABEL: define {{[^@]+}}@complicated_args_sret
 ; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B:%.*]]) #[[ATTR6:[0-9]+]] {
-; CGSCC-NEXT:    call void @test_sret(ptr nofree noundef writeonly sret([[STRUCT_X:%.*]]) dereferenceable_or_null(8) null, ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B]]) #[[ATTR15:[0-9]+]]
+; CGSCC-NEXT:    call void @test_sret(ptr nofree noundef writeonly sret([[STRUCT_X:%.*]]) dereferenceable_or_null(8) null, ptr nofree noundef nonnull writeonly align 8 captures(none) dereferenceable(8) [[B]]) #[[ATTR16:[0-9]+]]
 ; CGSCC-NEXT:    ret void
 ;
   call void @test_sret(ptr sret(%struct.X) null, ptr %b)
@@ -571,7 +571,7 @@ define ptr @complicated_args_nest() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@complicated_args_nest
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[CALL:%.*]] = call noalias noundef align 4294967296 ptr @test_nest(ptr nofree noundef readnone null) #[[ATTR12]]
+; CGSCC-NEXT:    [[CALL:%.*]] = call noalias noundef align 4294967296 ptr @test_nest(ptr nofree noundef readnone null) #[[ATTR13]]
 ; CGSCC-NEXT:    ret ptr [[CALL]]
 ;
   %call = call ptr @test_nest(ptr null)
@@ -580,19 +580,19 @@ define ptr @complicated_args_nest() {
 
 @S = external global %struct.X
 define internal void @test_byval(ptr byval(%struct.X) %a) {
-; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
+; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; TUNIT-LABEL: define {{[^@]+}}@test_byval
-; TUNIT-SAME: (ptr [[TMP0:%.*]]) #[[ATTR4]] {
-; TUNIT-NEXT:    [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8
-; TUNIT-NEXT:    store ptr [[TMP0]], ptr [[A_PRIV]], align 8
+; TUNIT-SAME: (i64 [[TMP0:%.*]]) #[[ATTR2]] {
+; TUNIT-NEXT:    [[A_PRIV:%.*]] = alloca i64, align 8
+; TUNIT-NEXT:    store i64 [[TMP0]], ptr [[A_PRIV]], align 8
 ; TUNIT-NEXT:    store ptr null, ptr [[A_PRIV]], align 8
 ; TUNIT-NEXT:    ret void
 ;
-; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
+; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test_byval
-; CGSCC-SAME: (ptr nofree [[TMP0:%.*]]) #[[ATTR5]] {
-; CGSCC-NEXT:    [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8
-; CGSCC-NEXT:    store ptr [[TMP0]], ptr [[A_PRIV]], align 8
+; CGSCC-SAME: (i64 [[TMP0:%.*]]) #[[ATTR1]] {
+; CGSCC-NEXT:    [[A_PRIV:%.*]] = alloca i64, align 8
+; CGSCC-NEXT:    store i64 [[TMP0]], ptr [[A_PRIV]], align 8
 ; CGSCC-NEXT:    store ptr null, ptr [[A_PRIV]], align 8
 ; CGSCC-NEXT:    ret void
 ;
@@ -603,15 +603,13 @@ define void @complicated_args_byval() {
 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
 ; TUNIT-LABEL: define {{[^@]+}}@complicated_args_byval
 ; TUNIT-SAME: () #[[ATTR5:[0-9]+]] {
-; TUNIT-NEXT:    [[TMP1:%.*]] = load ptr, ptr @S, align 8
-; TUNIT-NEXT:    call void @test_byval(ptr [[TMP1]]) #[[ATTR11]]
+; TUNIT-NEXT:    [[TMP1:%.*]] = load i64, ptr @S, align 8
+; TUNIT-NEXT:    call void @test_byval(i64 [[TMP1]]) #[[ATTR11]]
 ; TUNIT-NEXT:    ret void
 ;
-; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
+; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
 ; CGSCC-LABEL: define {{[^@]+}}@complicated_args_byval
-; CGSCC-SAME: () #[[ATTR4]] {
-; CGSCC-NEXT:    [[TMP1:%.*]] = load ptr, ptr @S, align 8
-; CGSCC-NEXT:    call void @test_byval(ptr nofree writeonly [[TMP1]]) #[[ATTR15]]
+; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {
 ; CGSCC-NEXT:    ret void
 ;
   call void @test_byval(ptr byval(%struct.X) @S)
@@ -621,13 +619,23 @@ define void @complicated_args_byval() {
 declare void @sync()
 ; Make sure we *do not* load @S here!
 define internal ptr @test_byval2(ptr byval(%struct.X) %a) {
-; CHECK-LABEL: define {{[^@]+}}@test_byval2
-; CHECK-SAME: (ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8
-; CHECK-NEXT:    store ptr [[TMP0]], ptr [[A_PRIV]], align 8
-; CHECK-NEXT:    call void @sync()
-; CHECK-NEXT:    [[L:%.*]] = load ptr, ptr [[A_PRIV]], align 8
-; CHECK-NEXT:    ret ptr [[L]]
+; TUNIT: Function Attrs: memory(readwrite, argmem: none)
+; TUNIT-LABEL: define {{[^@]+}}@test_byval2
+; TUNIT-SAME: (i64 [[TMP0:%.*]]) #[[ATTR1]] {
+; TUNIT-NEXT:    [[A_PRIV:%.*]] = alloca i64, align 8
+; TUNIT-NEXT:    store i64 [[TMP0]], ptr [[A_PRIV]], align 8
+; TUNIT-NEXT:    call void @sync()
+; TUNIT-NEXT:    [[L:%.*]] = load ptr, ptr [[A_PRIV]], align 8, !invariant.load [[META0:![0-9]+]]
+; TUNIT-NEXT:    ret ptr [[L]]
+;
+; CGSCC: Function Attrs: memory(readwrite, argmem: none)
+; CGSCC-LABEL: define {{[^@]+}}@test_byval2
+; CGSCC-SAME: (i64 [[TMP0:%.*]]) #[[ATTR2]] {
+; CGSCC-NEXT:    [[A_PRIV:%.*]] = alloca i64, align 8
+; CGSCC-NEXT:    store i64 [[TMP0]], ptr [[A_PRIV]], align 8
+; CGSCC-NEXT:    call void @sync()
+; CGSCC-NEXT:    [[L:%.*]] = load ptr, ptr [[A_PRIV]], align 8, !invariant.load [[META0:![0-9]+]]
+; CGSCC-NEXT:    ret ptr [[L]]
 ;
   call void @sync()
   %l = load ptr, ptr %a
@@ -636,8 +644,8 @@ define internal ptr @test_byval2(ptr byval(%struct.X) %a) {
 define ptr @complicated_args_byval2() {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval2() {
-; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr @S, align 8
-; CHECK-NEXT:    [[C:%.*]] = call ptr @test_byval2(ptr [[TMP1]])
+; CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr @S, align 8
+; CHECK-NEXT:    [[C:%.*]] = call ptr @test_byval2(i64 [[TMP1]])
 ; CHECK-NEXT:    ret ptr [[C]]
 ;
   %c = call ptr @test_byval2(ptr byval(%struct.X) @S)
@@ -727,7 +735,7 @@ define i8 @caller0() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@caller0
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[C]]
 ;
   %c = call i8 @callee(i8 undef)
@@ -742,7 +750,7 @@ define i8 @caller1() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@caller1
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[C]]
 ;
   %c = call i8 @callee(i8 undef)
@@ -757,7 +765,7 @@ define i8 @caller2() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@caller2
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[C]]
 ;
   %c = call i8 @callee(i8 undef)
@@ -772,7 +780,7 @@ define i8 @caller_middle() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@caller_middle
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[C]]
 ;
   %c = call i8 @callee(i8 42)
@@ -787,7 +795,7 @@ define i8 @caller3() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@caller3
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[C]]
 ;
   %c = call i8 @callee(i8 undef)
@@ -802,7 +810,7 @@ define i8 @caller4() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@caller4
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i8 @callee() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[C]]
 ;
   %c = call i8 @callee(i8 undef)
@@ -827,8 +835,8 @@ define void @user_as3() {
 ;
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
 ; CGSCC-LABEL: define {{[^@]+}}@user_as3
-; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {
-; CGSCC-NEXT:    [[CALL:%.*]] = call fastcc align 4 ptr addrspace(3) @const_ptr_return_as3() #[[ATTR12]]
+; CGSCC-SAME: () #[[ATTR8:[0-9]+]] {
+; CGSCC-NEXT:    [[CALL:%.*]] = call fastcc align 4 ptr addrspace(3) @const_ptr_return_as3() #[[ATTR13]]
 ; CGSCC-NEXT:    store i32 0, ptr addrspace(3) [[CALL]], align 4
 ; CGSCC-NEXT:    ret void
 ;
@@ -845,8 +853,8 @@ define void @user() {
 ;
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
 ; CGSCC-LABEL: define {{[^@]+}}@user
-; CGSCC-SAME: () #[[ATTR7]] {
-; CGSCC-NEXT:    [[CALL:%.*]] = call fastcc align 4 ptr @const_ptr_return() #[[ATTR12]]
+; CGSCC-SAME: () #[[ATTR8]] {
+; CGSCC-NEXT:    [[CALL:%.*]] = call fastcc align 4 ptr @const_ptr_return() #[[ATTR13]]
 ; CGSCC-NEXT:    store i32 0, ptr [[CALL]], align 4
 ; CGSCC-NEXT:    ret void
 ;
@@ -865,7 +873,7 @@ define i1 @test_merge_with_undef_values_ptr(i1 %c) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test_merge_with_undef_values_ptr
 ; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[R1:%.*]] = call i1 @undef_then_null(i1 [[C]]) #[[ATTR12]]
+; CGSCC-NEXT:    [[R1:%.*]] = call i1 @undef_then_null(i1 [[C]]) #[[ATTR13]]
 ; CGSCC-NEXT:    ret i1 [[R1]]
 ;
   %r1 = call i1 @undef_then_null(i1 %c, ptr undef, ptr undef)
@@ -902,7 +910,7 @@ define i1 @test_merge_with_undef_values(i1 %c) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test_merge_with_undef_values
 ; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[R1:%.*]] = call i1 @undef_then_1(i1 [[C]]) #[[ATTR12]]
+; CGSCC-NEXT:    [[R1:%.*]] = call i1 @undef_then_1(i1 [[C]]) #[[ATTR13]]
 ; CGSCC-NEXT:    ret i1 [[R1]]
 ;
   %r1 = call i1 @undef_then_1(i1 %c, i32 undef, i32 undef)
@@ -940,7 +948,7 @@ define i32 @test_select(i32 %c) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test_select
 ; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[CALL:%.*]] = call noundef i32 @select() #[[ATTR12]]
+; CGSCC-NEXT:    [[CALL:%.*]] = call noundef i32 @select() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i32 [[CALL]]
 ;
   %call = call i32 @select(i1 1, i32 42, i32 %c)
@@ -1090,7 +1098,7 @@ define i1 @test_cmp_null_after_cast() {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test_cmp_null_after_cast
 ; CGSCC-SAME: () #[[ATTR3]] {
-; CGSCC-NEXT:    [[C:%.*]] = call noundef i1 @cmp_null_after_cast() #[[ATTR12]]
+; CGSCC-NEXT:    [[C:%.*]] = call noundef i1 @cmp_null_after_cast() #[[ATTR13]]
 ; CGSCC-NEXT:    ret i1 [[C]]
 ;
   %c = call i1 @cmp_null_after_cast(i32 0, i8 0)
@@ -1209,7 +1217,7 @@ define i1 @test_liveness(i1 %c) {
 ; CGSCC-NEXT:    br label [[F]]
 ; CGSCC:       f:
 ; CGSCC-NEXT:    [[P:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[T]] ]
-; CGSCC-NEXT:    [[RC1:%.*]] = call noundef i1 @ret(i1 noundef [[P]]) #[[ATTR12]]
+; CGSCC-NEXT:    [[RC1:%.*]] = call noundef i1 @ret(i1 noundef [[P]]) #[[ATTR13]]
 ; CGSCC-NEXT:    ret i1 [[RC1]]
 ;
 entry:
@@ -1281,7 +1289,7 @@ define internal i8 @memcpy_uses_store(i8 %arg) {
 ; CGSCC-NEXT:    [[SRC:%.*]] = alloca i8, align 1
 ; CGSCC-NEXT:    [[DST:%.*]] = alloca i8, align 1
 ; CGSCC-NEXT:    store i8 [[ARG]], ptr [[SRC]], align 1
-; CGSCC-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[DST]], ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[SRC]], i32 noundef 1, i1 noundef false) #[[ATTR16:[0-9]+]]
+; CGSCC-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[DST]], ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[SRC]], i32 noundef 1, i1 noundef false) #[[ATTR17:[0-9]+]]
 ; CGSCC-NEXT:    [[L:%.*]] = load i8, ptr [[DST]], align 1
 ; CGSCC-NEXT:    ret i8 [[L]]
 ;
@@ -1303,7 +1311,7 @@ define i8 @memcpy_uses_store_caller(i8 %arg) {
 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@memcpy_uses_store_caller
 ; CGSCC-SAME: (i8 [[ARG:%.*]]) #[[ATTR3]] {
-; CGSCC-NEXT:    [[R:%.*]] = call i8 @memcpy_uses_store(i8 [[ARG]]) #[[ATTR12]]
+; CGSCC-NEXT:    [[R:%.*]] = call i8 @memcpy_uses_store(i8 [[ARG]]) #[[ATTR13]]
 ; CGSCC-NEXT:    ret i8 [[R]]
 ;
   %r = call i8 @memcpy_uses_store(i8 %arg)
@@ -1327,12 +1335,12 @@ define i32 @test_speculatable_expr() norecurse {
 ;
 ; CGSCC: Function Attrs: norecurse nosync memory(none)
 ; CGSCC-LABEL: define {{[^@]+}}@test_speculatable_expr
-; CGSCC-SAME: () #[[ATTR9:[0-9]+]] {
+; CGSCC-SAME: () #[[ATTR10:[0-9]+]] {
 ; CGSCC-NEXT:    [[STACK:%.*]] = alloca i32, align 4
-; CGSCC-NEXT:    [[SPEC_RESULT:%.*]] = call i32 @speculatable() #[[ATTR17:[0-9]+]]
+; CGSCC-NEXT:    [[SPEC_RESULT:%.*]] = call i32 @speculatable() #[[ATTR18:[0-9]+]]
 ; CGSCC-NEXT:    [[PLUS1:%.*]] = add i32 [[SPEC_RESULT]], 1
 ; CGSCC-NEXT:    store i32 [[PLUS1]], ptr [[STACK]], align 4
-; CGSCC-NEXT:    [[RSPEC:%.*]] = call i32 @ret_speculatable_expr(i32 [[PLUS1]]) #[[ATTR17]]
+; CGSCC-NEXT:    [[RSPEC:%.*]] = call i32 @ret_speculatable_expr(i32 [[PLUS1]]) #[[ATTR18]]
 ; CGSCC-NEXT:    ret i32 [[RSPEC]]
 ;
   %stack = alloca i32
@@ -1359,7 +1367,7 @@ define internal i32 @ret_speculatable_expr(ptr %mem, i32 %a2) {
 ; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
 ; CGSCC-NEXT:    [[MEM_PRIV:%.*]] = alloca i32, align 4
 ; CGSCC-NEXT:    store i32 [[TMP0]], ptr [[MEM_PRIV]], align 4
-; CGSCC-NEXT:    [[L:%.*]] = load i32, ptr [[MEM_PRIV]], align 4
+; CGSCC-NEXT:    [[L:%.*]] = load i32, ptr [[MEM_PRIV]], align 4, !invariant.load [[META0]]
 ; CGSCC-NEXT:    [[MUL:%.*]] = mul i32 [[L]], 13
 ; CGSCC-NEXT:    [[ADD:%.*]] = add i32 [[MUL]], 7
 ; CGSCC-NEXT:    ret i32 [[ADD]]
@@ -1436,7 +1444,7 @@ define internal void @indirect() {
 ;
 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
 ; CGSCC-LABEL: define {{[^@]+}}@indirect
-; CGSCC-SAME: () #[[ATTR10:[0-9]+]] {
+; CGSCC-SAME: () #[[ATTR11:[0-9]+]] {
 ; CGSCC-NEXT:    store i32 0, ptr @x, align 4
 ; CGSCC-NEXT:    ret void
 ;
@@ -1457,7 +1465,7 @@ define internal void @broker(ptr %ptr) {
 ; CGSCC-LABEL: define {{[^@]+}}@broker
 ; CGSCC-SAME: () #[[ATTR2]] {
 ; CGSCC-NEXT:  entry:
-; CGSCC-NEXT:    call void @indirect() #[[ATTR18:[0-9]+]]
+; CGSCC-NEXT:    call void @indirect() #[[ATTR19:[0-9]+]]
 ; CGSCC-NEXT:    call void @unknown()
 ; CGSCC-NEXT:    ret void
 ;
@@ -1696,16 +1704,21 @@ define i32 @readExtInitZeroInit() {
 ; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree nosync nounwind willreturn }
 ; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
 ; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: write) }
-; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree nosync nounwind willreturn memory(write) }
-; CGSCC: attributes #[[ATTR8:[0-9]+]] = { speculatable memory(none) }
-; CGSCC: attributes #[[ATTR9]] = { norecurse nosync memory(none) }
-; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
-; CGSCC: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
-; CGSCC: attributes #[[ATTR12]] = { nofree nosync willreturn }
-; CGSCC: attributes #[[ATTR13]] = { nofree willreturn }
-; CGSCC: attributes #[[ATTR14]] = { nofree nounwind willreturn }
-; CGSCC: attributes #[[ATTR15]] = { nofree nounwind willreturn memory(write) }
-; CGSCC: attributes #[[ATTR16]] = { nofree willreturn memory(readwrite) }
-; CGSCC: attributes #[[ATTR17]] = { nosync }
-; CGSCC: attributes #[[ATTR18]] = { nounwind }
+; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree nosync nounwind willreturn memory(read) }
+; CGSCC: attributes #[[ATTR8]] = { mustprogress nofree nosync nounwind willreturn memory(write) }
+; CGSCC: attributes #[[ATTR9:[0-9]+]] = { speculatable memory(none) }
+; CGSCC: attributes #[[ATTR10]] = { norecurse nosync memory(none) }
+; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
+; CGSCC: attributes #[[ATTR12:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
+; CGSCC: attributes #[[ATTR13]] = { nofree nosync willreturn }
+; CGSCC: attributes #[[ATTR14]] = { nofree willreturn }
+; CGSCC: attributes #[[ATTR15]] = { nofree nounwind willreturn }
+; CGSCC: attributes #[[ATTR16]] = { nofree nounwind willreturn memory(write) }
+; CGSCC: attributes #[[ATTR17]] = { nofree willreturn memory(readwrite) }
+; CGSCC: attributes #[[ATTR18]] = { nosync }
+; CGSCC: attributes #[[ATTR19]] = { nounwind }
+;.
+; TUNIT: [[META0]] = !{}
+;.
+; CGSCC: [[META0]] = !{}
 ;.



More information about the llvm-commits mailing list