[clang] 0eff46f - [SystemZ] Fix handling of vectors and their exposure of the vector ABI.

Jonas Paulsson via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 27 11:24:21 PST 2023


Author: Jonas Paulsson
Date: 2023-01-27T20:24:09+01:00
New Revision: 0eff46f87f16772f93bdc584865e945162aff170

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

LOG: [SystemZ] Fix handling of vectors and their exposure of the vector ABI.

- Global vector variables expose the vector ABI through their alignments only
  if they are >=16 bytes in size.

- Vectors passed between functions expose the vector ABI only if they are
  <=16 bytes in size.

LLVM test suite builds with gcc/clang now give the same gnu attributes emitted.

Reviewed By: Ulrich Weigand

Differential Revision: https://reviews.llvm.org/D141409

Added: 
    clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03b.c
    clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08b.c
    clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09b.c
    clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17b.c

Modified: 
    clang/lib/CodeGen/TargetInfo.cpp
    clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index be1dbe8480c6e..a9119abad81d8 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -7418,18 +7418,28 @@ class SystemZABIInfo : public ABIInfo {
 };
 
 class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
+  ASTContext &Ctx;
+
+  const SystemZABIInfo &getABIInfo() const {
+    return static_cast<const SystemZABIInfo&>(TargetCodeGenInfo::getABIInfo());
+  }
+
   // These are used for speeding up the search for a visible vector ABI.
   mutable bool HasVisibleVecABIFlag = false;
   mutable std::set<const Type *> SeenTypes;
 
-  // Returns true (the first time) if Ty is or found to make use of a vector
-  // type (e.g. as a function argument).
-  bool isVectorTypeBased(const Type *Ty) const;
+  // Returns true (the first time) if Ty is, or is found to include, a vector
+  // type that exposes the vector ABI. This is any vector >=16 bytes which
+  // with vector support are aligned to only 8 bytes. When IsParam is true,
+  // the type belongs to a value as passed between functions. If it is a
+  // vector <=16 bytes it will be passed in a vector register (if supported).
+  bool isVectorTypeBased(const Type *Ty, bool IsParam) const;
 
 public:
   SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
       : TargetCodeGenInfo(
-            std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) {
+            std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),
+            Ctx(CGT.getContext()) {
     SwiftInfo =
         std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
   }
@@ -7439,9 +7449,9 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
   // indicating a visible vector ABI is added. Eventually this will result in
   // a GNU attribute indicating the vector ABI of the module.  Ty is the type
   // of a variable or function parameter that is globally visible.
-  void handleExternallyVisibleObjABI(const Type *Ty,
-                                     CodeGen::CodeGenModule &M) const {
-    if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty)) {
+  void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M,
+                                     bool IsParam) const {
+    if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) {
       M.getModule().addModuleFlag(llvm::Module::Warning,
                                   "s390x-visible-vector-ABI", 1);
       HasVisibleVecABIFlag = true;
@@ -7457,11 +7467,13 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
     // variable or function.
     if (const auto *VD = dyn_cast<VarDecl>(D)) {
       if (VD->isExternallyVisible())
-        handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M);
+        handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M,
+                                      /*IsParam*/false);
     }
     else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
       if (FD->isExternallyVisible())
-        handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M);
+        handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M,
+                                      /*IsParam*/false);
     }
   }
 
@@ -7571,17 +7583,18 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
 
     // If this is a C++ record, check the bases first.
     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
-      for (const auto &I : CXXRD->bases()) {
-        QualType Base = I.getType();
+      if (CXXRD->hasDefinition())
+        for (const auto &I : CXXRD->bases()) {
+          QualType Base = I.getType();
 
-        // Empty bases don't affect things either way.
-        if (isEmptyRecord(getContext(), Base, true))
-          continue;
+          // Empty bases don't affect things either way.
+          if (isEmptyRecord(getContext(), Base, true))
+            continue;
 
-        if (!Found.isNull())
-          return Ty;
-        Found = GetSingleElementType(Base);
-      }
+          if (!Found.isNull())
+            return Ty;
+          Found = GetSingleElementType(Base);
+        }
 
     // Check the fields.
     for (const auto *FD : RD->fields()) {
@@ -7635,7 +7648,8 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
   bool IsVector = false;
   CharUnits UnpaddedSize;
   CharUnits DirectAlign;
-  SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM());
+  SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(),
+                                      /*IsParam*/true);
   if (IsIndirect) {
     DirectTy = llvm::PointerType::getUnqual(DirectTy);
     UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);
@@ -7843,35 +7857,57 @@ void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
       // Check if a vararg vector argument is passed, in which case the
       // vector ABI becomes visible as the va_list could be passed on to
       // other functions.
-      SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM());
+      SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(),
+                                          /*IsParam*/true);
   }
 }
 
-bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty) const {
-  while (Ty->isPointerType() || Ty->isArrayType())
-    Ty = Ty->getPointeeOrArrayElementType();
+bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,
+                                                 bool IsParam) const {
   if (!SeenTypes.insert(Ty).second)
     return false;
-  if (Ty->isVectorType())
-    return true;
+
+  if (IsParam) {
+    // A narrow (<16 bytes) vector will as a parameter also expose the ABI as
+    // it will be passed in a vector register. A wide (>16 bytes) vector will
+    // be passed via "hidden" pointer where any extra alignment is not
+    // required (per GCC).
+    const Type *SingleEltTy =
+      getABIInfo().GetSingleElementType(QualType(Ty, 0)).getTypePtr();
+    bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() &&
+      Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty);
+    if (Ty->isVectorType() || SingleVecEltStruct)
+      return Ctx.getTypeSize(Ty) / 8 <= 16;
+  }
+
+  // Assume pointers are dereferenced.
+  while (Ty->isPointerType() || Ty->isArrayType())
+    Ty = Ty->getPointeeOrArrayElementType();
+
+  // Vectors >= 16 bytes expose the ABI through alignment requirements.
+  if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16)
+      return true;
+
   if (const auto *RecordTy = Ty->getAs<RecordType>()) {
     const RecordDecl *RD = RecordTy->getDecl();
     if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
       if (CXXRD->hasDefinition())
         for (const auto &I : CXXRD->bases())
-          if (isVectorTypeBased(I.getType().getTypePtr()))
+          if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false))
             return true;
     for (const auto *FD : RD->fields())
-      if (isVectorTypeBased(FD->getType().getTypePtr()))
+      if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false))
         return true;
   }
+
   if (const auto *FT = Ty->getAs<FunctionType>())
-    if (isVectorTypeBased(FT->getReturnType().getTypePtr()))
+    if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true))
       return true;
   if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())
     for (auto ParamType : Proto->getParamTypes())
-      if (isVectorTypeBased(ParamType.getTypePtr()))
+      if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true))
         return true;
+
   return false;
 }
 

diff  --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03b.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03b.c
new file mode 100644
index 0000000000000..6cf6c50be259f
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03b.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN:   | FileCheck  %s
+//
+// Test that the "s390x-visible-vector-ABI" module flag is emitted.
+
+// Call to external function with with narrow vector argument.
+
+typedef __attribute__((vector_size(8))) int v2i32;
+
+void bar(v2i32 arg);
+
+void foo() {
+  v2i32 Var = {0, 0};
+  bar(Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
+

diff  --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08b.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08b.c
new file mode 100644
index 0000000000000..7f99198b687ac
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08b.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN:   | FileCheck  %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Passing a single element struct containing a narrow (8 byte) vector element.
+
+typedef __attribute__((vector_size(8))) int v2i32;
+
+struct S {
+  v2i32 B;
+};
+
+void bar(struct S Arg);
+
+void foo() {
+  struct S Var = {{0, 0}};
+  bar(Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}

diff  --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09b.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09b.c
new file mode 100644
index 0000000000000..b4de233550079
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09b.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN:   | FileCheck  %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call to vararg function with a narrow (8 bytes) vector argument.
+
+typedef __attribute__((vector_size(8))) int v2i32;
+
+void bar(int N, ...);
+
+void foo() {
+  v2i32 Var = {0, 0};
+  bar(0, Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}

diff  --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17b.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17b.c
new file mode 100644
index 0000000000000..d75e3ec6edcc1
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17b.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN:   | FileCheck  %s
+//
+// Test that the "s390x-visible-vector-ABI" module flag is emitted.
+
+// Globally visible function pointer with narrow vector argument.
+
+typedef __attribute__((vector_size(8))) int v2i32;
+
+void (*bar)(v2i32 Arg);
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}

diff  --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c
index a18fe924dc2d9..54d7dc915cec2 100644
--- a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c
@@ -34,4 +34,20 @@ int fun1() {
   return foo(V)[0] + GlobVal + GlobExtVar;
 }
 
+// Globally visible vector variable less than 16 bytes in size.
+typedef __attribute__((vector_size(8))) int v2i32;
+v2i32 NarrowVecVar;
+
+// Global function taking narrow vector array and pointer.
+void bar(v2i32 VArr[4], v2i32 *Dst) { *Dst = VArr[3]; }
+
+// Wide vector parameters via "hidden" pointers.
+typedef __attribute__((vector_size(32))) int v8i32;
+v8i32 bar2(v8i32 Arg) { return Arg; }
+
+// Same but with a single element struct.
+struct SingleElStruct { v8i32 B; };
+struct SingleElStruct bar3(struct SingleElStruct Arg) { return Arg; }
+
+
 //CHECK-NOT: !{i32 2, !"s390x-visible-vector-ABI", i32 1}


        


More information about the cfe-commits mailing list