Commit 57148e03 authored by Krzysztof Parzyszek's avatar Krzysztof Parzyszek
Browse files

[Hexagon] Fix ABI info for returning HVX vectors

parent 8c3d0d6a
Loading
Loading
Loading
Loading
+32 −32
Original line number Diff line number Diff line
@@ -7486,13 +7486,10 @@ void TCETargetCodeGenInfo::setTargetAttributes(
namespace {

class HexagonABIInfo : public ABIInfo {


public:
  HexagonABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}

private:

  ABIArgInfo classifyReturnType(QualType RetTy) const;
  ABIArgInfo classifyArgumentType(QualType RetTy) const;

@@ -7512,7 +7509,7 @@ public:
  }
};

}
} // namespace

void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const {
  if (!getCXXABI().classifyReturnType(FI))
@@ -7527,8 +7524,8 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const {
    if (const EnumType *EnumTy = Ty->getAs<EnumType>())
      Ty = EnumTy->getDecl()->getIntegerType();

    return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
                                          : ABIArgInfo::getDirect());
    return Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend(Ty)
                                         : ABIArgInfo::getDirect();
  }

  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
@@ -7539,53 +7536,56 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const {
    return ABIArgInfo::getIgnore();

  uint64_t Size = getContext().getTypeSize(Ty);
  if (Size > 64)
    return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
  if (Size <= 64) {
    // Pass in the smallest viable integer type.
  else if (Size > 32)
      return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext()));
  else if (Size > 16)
      return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
  else if (Size > 8)
      return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
  else
      return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
    if (!llvm::isPowerOf2_64(Size))
      Size = llvm::NextPowerOf2(Size);
    return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
  }
  return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
}

ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
  if (RetTy->isVoidType())
    return ABIArgInfo::getIgnore();

  const TargetInfo &T = CGT.getTarget();
  uint64_t Size = getContext().getTypeSize(RetTy);

  if (const auto *VecTy = RetTy->getAs<VectorType>()) {
    // HVX vectors are returned in vector registers or register pairs.
    if (T.hasFeature("hvx")) {
      assert(T.hasFeature("hvx-length64b") || T.hasFeature("hvx-length128b"));
      uint64_t VecSize = T.hasFeature("hvx-length64b") ? 64*8 : 128*8;
      if (Size == VecSize || Size == 2*VecSize)
        return ABIArgInfo::getDirectInReg();
    }

    // Large vector types should be returned via memory.
  if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 64)
    if (Size > 64)
      return getNaturalAlignIndirect(RetTy);
  }

  if (!isAggregateTypeForABI(RetTy)) {
    // Treat an enum type as its underlying type.
    if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
      RetTy = EnumTy->getDecl()->getIntegerType();

    return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
                                             : ABIArgInfo::getDirect());
    return RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy)
                                            : ABIArgInfo::getDirect();
  }

  if (isEmptyRecord(getContext(), RetTy, true))
    return ABIArgInfo::getIgnore();

  // Aggregates <= 8 bytes are returned in r0; other aggregates
  // Aggregates <= 8 bytes are returned in registers, other aggregates
  // are returned indirectly.
  uint64_t Size = getContext().getTypeSize(RetTy);
  if (Size <= 64) {
    // Return in the smallest viable integer type.
    if (Size <= 8)
      return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
    if (Size <= 16)
      return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
    if (Size <= 32)
      return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
    return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext()));
    if (!llvm::isPowerOf2_64(Size))
      Size = llvm::NextPowerOf2(Size);
    return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
  }

  return getNaturalAlignIndirect(RetTy, /*ByVal=*/true);
}

+20 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -triple hexagon -emit-llvm -target-cpu hexagonv66 -target-feature +hvxv66 -target-feature +hvx-length64b -o - %s | FileCheck %s --check-prefix CHECK-HVX64
// RUN: %clang_cc1 -triple hexagon -emit-llvm -target-cpu hexagonv66 -target-feature +hvxv66 -target-feature +hvx-length128b -o - %s | FileCheck %s --check-prefix CHECK-HVX128

typedef long HVX_Vector __attribute__((__vector_size__(__HVX_LENGTH__)))
  __attribute__((aligned(__HVX_LENGTH__)));
typedef long HVX_VectorPair __attribute__((__vector_size__(2*__HVX_LENGTH__)))
  __attribute__((aligned(__HVX_LENGTH__)));

// CHECK-HVX64: define {{.*}} <16 x i32> @foo(<16 x i32> %a, <32 x i32> %b)
// CHECK-HVX128: define {{.*}} <32 x i32> @foo(<32 x i32> %a, <64 x i32> %b) 
HVX_Vector foo(HVX_Vector a, HVX_VectorPair b) {
  return a;
}

// CHECK-HVX64: define {{.*}} <32 x i32> @bar(<16 x i32> %a, <32 x i32> %b)
// CHECK-HVX128: define {{.*}} <64 x i32> @bar(<32 x i32> %a, <64 x i32> %b)
HVX_VectorPair bar(HVX_Vector a, HVX_VectorPair b) {
  return b;
}