Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -7418,18 +7418,21 @@ }; class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { + ASTContext &Ctx; + // These are used for speeding up the search for a visible vector ABI. mutable bool HasVisibleVecABIFlag = false; mutable std::set 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; + bool isVectorTypeBased(const Type *Ty, bool IsPassed) const; public: SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI) : TargetCodeGenInfo( - std::make_unique(CGT, HasVector, SoftFloatABI)) { + std::make_unique(CGT, HasVector, SoftFloatABI)), + Ctx(CGT.getContext()) { SwiftInfo = std::make_unique(CGT, /*SwiftErrorInRegister=*/false); } @@ -7438,10 +7441,13 @@ // a module e.g. defines an externally visible vector variable, a flag // 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. + // of a variable or function parameter that is globally visible. IsPassed + // is true when called with a type used for a parameter or return value, in + // which case narrow vectors (<16 bytes) also exposes the vector ABI. void handleExternallyVisibleObjABI(const Type *Ty, - CodeGen::CodeGenModule &M) const { - if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty)) { + CodeGen::CodeGenModule &M, + bool IsPassed = true) const { + if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsPassed)) { M.getModule().addModuleFlag(llvm::Module::Warning, "s390x-visible-vector-ABI", 1); HasVisibleVecABIFlag = true; @@ -7457,7 +7463,8 @@ // variable or function. if (const auto *VD = dyn_cast(D)) { if (VD->isExternallyVisible()) - handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M); + handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M, + /*IsPassed=*/false); } else if (const FunctionDecl *FD = dyn_cast(D)) { if (FD->isExternallyVisible()) @@ -7847,30 +7854,36 @@ } } -bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty) const { +bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, + bool IsPassed) const { while (Ty->isPointerType() || Ty->isArrayType()) Ty = Ty->getPointeeOrArrayElementType(); if (!SeenTypes.insert(Ty).second) return false; - if (Ty->isVectorType()) - return true; + if (Ty->isVectorType()) { + unsigned Bytes = Ctx.getTypeSize(Ty) / 8; + if (IsPassed && Bytes <= 16) + return true; + if (!IsPassed && Bytes >= 16) + return true; + } if (const auto *RecordTy = Ty->getAs()) { const RecordDecl *RD = RecordTy->getDecl(); if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) if (CXXRD->hasDefinition()) for (const auto &I : CXXRD->bases()) - if (isVectorTypeBased(I.getType().getTypePtr())) + if (isVectorTypeBased(I.getType().getTypePtr(), IsPassed)) return true; for (const auto *FD : RD->fields()) - if (isVectorTypeBased(FD->getType().getTypePtr())) + if (isVectorTypeBased(FD->getType().getTypePtr(), IsPassed)) return true; } if (const auto *FT = Ty->getAs()) - if (isVectorTypeBased(FT->getReturnType().getTypePtr())) + if (isVectorTypeBased(FT->getReturnType().getTypePtr(), true)) return true; if (const FunctionProtoType *Proto = Ty->getAs()) for (auto ParamType : Proto->getParamTypes()) - if (isVectorTypeBased(ParamType.getTypePtr())) + if (isVectorTypeBased(ParamType.getTypePtr(), true)) return true; return false; } Index: clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03b.c =================================================================== --- /dev/null +++ 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} + Index: clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17b.c =================================================================== --- /dev/null +++ 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(16))) int v2i32; + +void (*bar)(v2i32 Arg); + +//CHECK: !llvm.module.flags = !{!0, !1} +//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1} Index: clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c =================================================================== --- clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c +++ clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c @@ -34,4 +34,16 @@ 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; + +// Passing wide (>16 bytes) vector argument. +typedef __attribute__((vector_size(32))) int v8i32; +void bar2(v8i32 Arg); +void foo2() { + v8i32 Var = {0, 0, 0, 0, 0, 0, 0, 0}; + bar2(Var); +} + //CHECK-NOT: !{i32 2, !"s390x-visible-vector-ABI", i32 1}