[llvm] d65a700 - OpaquePtr: Add helpers for sret to mirror byval

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 06:57:34 PDT 2020


Author: Matt Arsenault
Date: 2020-09-24T09:57:28-04:00
New Revision: d65a7003c435de22b8e30dca292160fea822d887

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

LOG: OpaquePtr: Add helpers for sret to mirror byval

Sret should really have a type parameter like byval does.

Added: 
    

Modified: 
    llvm/include/llvm/IR/Argument.h
    llvm/include/llvm/IR/Function.h
    llvm/lib/Analysis/Lint.cpp
    llvm/lib/IR/Function.cpp
    llvm/lib/IR/Value.cpp
    llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
    llvm/test/CodeGen/X86/vectorcall.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/Argument.h b/llvm/include/llvm/IR/Argument.h
index 2dd7c6cbc8b8..f59a498dc75d 100644
--- a/llvm/include/llvm/IR/Argument.h
+++ b/llvm/include/llvm/IR/Argument.h
@@ -83,8 +83,8 @@ class Argument final : public Value {
   /// in-memory ABI size copied to the stack for the call. Otherwise, return 0.
   uint64_t getPassPointeeByValueCopySize(const DataLayout &DL) const;
 
-  /// Return true if this argument has the byval, inalloca, preallocated, or
-  /// byref attribute. These attributes represent arguments being passed by
+  /// Return true if this argument has the byval, sret, inalloca, preallocated,
+  /// or byref attribute. These attributes represent arguments being passed by
   /// value (which may or may not involve a stack copy)
   bool hasPointeeInMemoryValueAttr() const;
 
@@ -103,6 +103,9 @@ class Argument final : public Value {
   /// If this is a byval argument, return its type.
   Type *getParamByValType() const;
 
+  /// If this is an sret argument, return its type.
+  Type *getParamStructRetType() const;
+
   /// If this is a byref argument, return its type.
   Type *getParamByRefType() const;
 

diff  --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index 85c0fe0cc89c..00803ccf6271 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -472,6 +472,12 @@ class Function : public GlobalObject, public ilist_node<Function> {
     return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType();
   }
 
+  /// Extract the sret type for a parameter.
+  Type *getParamStructRetType(unsigned ArgNo) const {
+    // FIXME: Add type to attribute like byval
+    return (arg_begin() + ArgNo)->getType()->getPointerElementType();
+  }
+
   /// Extract the byref type for a parameter.
   Type *getParamByRefType(unsigned ArgNo) const {
     return AttributeSets.getParamByRefType(ArgNo);

diff  --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 75b8f31c8a31..1f3970e00c74 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -250,7 +250,7 @@ void Lint::visitCallBase(CallBase &I) {
 
         // Check that an sret argument points to valid memory.
         if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) {
-          Type *Ty = cast<PointerType>(Formal->getType())->getElementType();
+          Type *Ty = Formal->getParamStructRetType();
           visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty),
                                DL->getABITypeAlign(Ty), Ty,
                                MemRef::Read | MemRef::Write);

diff  --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index ec1000cb3f3a..16cf1bd8a117 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -140,12 +140,13 @@ bool Argument::hasPointeeInMemoryValueAttr() const {
     return false;
   AttributeList Attrs = getParent()->getAttributes();
   return Attrs.hasParamAttribute(getArgNo(), Attribute::ByVal) ||
+         Attrs.hasParamAttribute(getArgNo(), Attribute::StructRet) ||
          Attrs.hasParamAttribute(getArgNo(), Attribute::InAlloca) ||
          Attrs.hasParamAttribute(getArgNo(), Attribute::Preallocated) ||
          Attrs.hasParamAttribute(getArgNo(), Attribute::ByRef);
 }
 
-/// For a byval, inalloca, or preallocated parameter, get the in-memory
+/// For a byval, sret, inalloca, or preallocated parameter, get the in-memory
 /// parameter type.
 static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
   // FIXME: All the type carrying attributes are mutually exclusive, so there
@@ -157,10 +158,11 @@ static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
   if (Type *PreAllocTy = ParamAttrs.getPreallocatedType())
     return PreAllocTy;
 
-  // FIXME: inalloca always depends on pointee element type. It's also possible
-  // for byval to miss it.
+  // FIXME: sret and inalloca always depends on pointee element type. It's also
+  // possible for byval to miss it.
   if (ParamAttrs.hasAttribute(Attribute::InAlloca) ||
       ParamAttrs.hasAttribute(Attribute::ByVal) ||
+      ParamAttrs.hasAttribute(Attribute::StructRet) ||
       ParamAttrs.hasAttribute(Attribute::Preallocated))
     return cast<PointerType>(ArgTy)->getElementType();
 
@@ -196,6 +198,11 @@ Type *Argument::getParamByValType() const {
   return getParent()->getParamByValType(getArgNo());
 }
 
+Type *Argument::getParamStructRetType() const {
+  assert(getType()->isPointerTy() && "Only pointers have sret types");
+  return getParent()->getParamStructRetType(getArgNo());
+}
+
 Type *Argument::getParamByRefType() const {
   assert(getType()->isPointerTy() && "Only pointers have byval types");
   return getParent()->getParamByRefType(getArgNo());

diff  --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index 1ef33605cb51..545404fc9ba0 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -804,7 +804,7 @@ Align Value::getPointerAlignment(const DataLayout &DL) const {
     const MaybeAlign Alignment = A->getParamAlign();
     if (!Alignment && A->hasStructRetAttr()) {
       // An sret parameter has at least the ABI alignment of the return type.
-      Type *EltTy = cast<PointerType>(A->getType())->getElementType();
+      Type *EltTy = A->getParamStructRetType();
       if (EltTy->isSized())
         return DL.getABITypeAlign(EltTy);
     }

diff  --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 9011e36619d9..0d66092a7035 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -813,7 +813,7 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpy, Value *cpyDest,
       if (!A->hasStructRetAttr())
         return false;
 
-      Type *StructTy = cast<PointerType>(A->getType())->getElementType();
+      Type *StructTy = A->getParamStructRetType();
       if (!StructTy->isSized()) {
         // The call may never return and hence the copy-instruction may never
         // be executed, and therefore it's not safe to say "the destination

diff  --git a/llvm/test/CodeGen/X86/vectorcall.ll b/llvm/test/CodeGen/X86/vectorcall.ll
index da474d028888..4a375acc4b97 100644
--- a/llvm/test/CodeGen/X86/vectorcall.ll
+++ b/llvm/test/CodeGen/X86/vectorcall.ll
@@ -172,7 +172,8 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture r
 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1)
 
 define x86_vectorcallcc void @test_mixed_7(%struct.HVA5* noalias sret %agg.result) {
-; CHECK-LABEL: test_mixed_7
+; X86-LABEL: test_mixed_7@@4
+; X64-LABEL: test_mixed_7@@8
 ; X64:         mov{{[ql]}}	%rcx, %rax
 ; CHECK:       movaps	%xmm{{[0-9]}}, 64(%{{rcx|eax}})
 ; CHECK:       movaps	%xmm{{[0-9]}}, 48(%{{rcx|eax}})


        


More information about the llvm-commits mailing list