huntergr updated this revision to Diff 222593. huntergr added a comment. Herald added a subscriber: dexonsmith.
- Renamed `ScalableSize` to `TypeSize`, including header name. - added `alignTo` function that takes and returns a `TypeSize`. I wasn't sure if this should be added to MathExtras.h where the other variants live, so just kept it in TypeSize.h for now Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D53137/new/ https://reviews.llvm.org/D53137 Files: clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGStmt.cpp clang/lib/CodeGen/CodeGenFunction.cpp llvm/include/llvm/ADT/DenseMapInfo.h llvm/include/llvm/IR/DataLayout.h llvm/include/llvm/IR/DerivedTypes.h llvm/include/llvm/IR/InstrTypes.h llvm/include/llvm/IR/Type.h llvm/include/llvm/Support/MachineValueType.h llvm/include/llvm/Support/ScalableSize.h llvm/include/llvm/Support/TypeSize.h llvm/lib/Analysis/InlineCost.cpp llvm/lib/CodeGen/Analysis.cpp llvm/lib/IR/DataLayout.cpp llvm/lib/IR/Instructions.cpp llvm/lib/IR/Type.cpp llvm/lib/Target/AArch64/AArch64ISelLowering.cpp llvm/lib/Transforms/Scalar/SROA.cpp llvm/test/Other/scalable-vectors-core-ir.ll llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp llvm/unittests/IR/VectorTypesTest.cpp
Index: llvm/unittests/IR/VectorTypesTest.cpp =================================================================== --- llvm/unittests/IR/VectorTypesTest.cpp +++ llvm/unittests/IR/VectorTypesTest.cpp @@ -6,9 +6,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/Support/ScalableSize.h" +#include "llvm/Support/TypeSize.h" #include "gtest/gtest.h" using namespace llvm; @@ -161,4 +162,117 @@ ASSERT_TRUE(EltCnt.Scalable); } +TEST(VectorTypesTest, FixedLenComparisons) { + LLVMContext Ctx; + DataLayout DL(""); + + Type *Int32Ty = Type::getInt32Ty(Ctx); + Type *Int64Ty = Type::getInt64Ty(Ctx); + + VectorType *V2Int32Ty = VectorType::get(Int32Ty, 2); + VectorType *V4Int32Ty = VectorType::get(Int32Ty, 4); + + VectorType *V2Int64Ty = VectorType::get(Int64Ty, 2); + + TypeSize V2I32Len = V2Int32Ty->getPrimitiveSizeInBits(); + EXPECT_EQ(V2I32Len.getKnownMinSize(), 64U); + EXPECT_FALSE(V2I32Len.isScalable()); + + EXPECT_LT(V2Int32Ty->getPrimitiveSizeInBits(), + V4Int32Ty->getPrimitiveSizeInBits()); + EXPECT_GT(V2Int64Ty->getPrimitiveSizeInBits(), + V2Int32Ty->getPrimitiveSizeInBits()); + EXPECT_EQ(V4Int32Ty->getPrimitiveSizeInBits(), + V2Int64Ty->getPrimitiveSizeInBits()); + EXPECT_NE(V2Int32Ty->getPrimitiveSizeInBits(), + V2Int64Ty->getPrimitiveSizeInBits()); + + // Check that a fixed-only comparison works for fixed size vectors. + EXPECT_EQ(V2Int64Ty->getPrimitiveSizeInBits().getFixedSize(), + V4Int32Ty->getPrimitiveSizeInBits().getFixedSize()); + + // Check the DataLayout interfaces. + EXPECT_EQ(DL.getTypeSizeInBits(V2Int64Ty), + DL.getTypeSizeInBits(V4Int32Ty)); + EXPECT_EQ(DL.getTypeSizeInBits(V2Int32Ty), 64U); + EXPECT_EQ(DL.getTypeSizeInBits(V2Int64Ty), 128U); + EXPECT_EQ(DL.getTypeStoreSize(V2Int64Ty), + DL.getTypeStoreSize(V4Int32Ty)); + EXPECT_NE(DL.getTypeStoreSizeInBits(V2Int32Ty), + DL.getTypeStoreSizeInBits(V2Int64Ty)); + EXPECT_EQ(DL.getTypeStoreSizeInBits(V2Int32Ty), 64U); + EXPECT_EQ(DL.getTypeStoreSize(V2Int64Ty), 16U); + EXPECT_EQ(DL.getTypeAllocSize(V4Int32Ty), + DL.getTypeAllocSize(V2Int64Ty)); + EXPECT_NE(DL.getTypeAllocSizeInBits(V2Int32Ty), + DL.getTypeAllocSizeInBits(V2Int64Ty)); + EXPECT_EQ(DL.getTypeAllocSizeInBits(V4Int32Ty), 128U); + EXPECT_EQ(DL.getTypeAllocSize(V2Int32Ty), 8U); + ASSERT_TRUE(DL.typeSizeEqualsStoreSize(V4Int32Ty)); +} + +TEST(VectorTypesTest, ScalableComparisons) { + LLVMContext Ctx; + DataLayout DL(""); + + Type *Int32Ty = Type::getInt32Ty(Ctx); + Type *Int64Ty = Type::getInt64Ty(Ctx); + + VectorType *ScV2Int32Ty = VectorType::get(Int32Ty, {2, true}); + VectorType *ScV4Int32Ty = VectorType::get(Int32Ty, {4, true}); + + VectorType *ScV2Int64Ty = VectorType::get(Int64Ty, {2, true}); + + TypeSize ScV2I32Len = ScV2Int32Ty->getPrimitiveSizeInBits(); + EXPECT_EQ(ScV2I32Len.getKnownMinSize(), 64U); + EXPECT_TRUE(ScV2I32Len.isScalable()); + + EXPECT_LT(ScV2Int32Ty->getPrimitiveSizeInBits(), + ScV4Int32Ty->getPrimitiveSizeInBits()); + EXPECT_GT(ScV2Int64Ty->getPrimitiveSizeInBits(), + ScV2Int32Ty->getPrimitiveSizeInBits()); + EXPECT_EQ(ScV4Int32Ty->getPrimitiveSizeInBits(), + ScV2Int64Ty->getPrimitiveSizeInBits()); + EXPECT_NE(ScV2Int32Ty->getPrimitiveSizeInBits(), + ScV2Int64Ty->getPrimitiveSizeInBits()); + + // Check the DataLayout interfaces. + EXPECT_EQ(DL.getTypeSizeInBits(ScV2Int64Ty), + DL.getTypeSizeInBits(ScV4Int32Ty)); + EXPECT_EQ(DL.getTypeSizeInBits(ScV2Int32Ty).getKnownMinSize(), 64U); + EXPECT_EQ(DL.getTypeStoreSize(ScV2Int64Ty), + DL.getTypeStoreSize(ScV4Int32Ty)); + EXPECT_NE(DL.getTypeStoreSizeInBits(ScV2Int32Ty), + DL.getTypeStoreSizeInBits(ScV2Int64Ty)); + EXPECT_EQ(DL.getTypeStoreSizeInBits(ScV2Int32Ty).getKnownMinSize(), 64U); + EXPECT_EQ(DL.getTypeStoreSize(ScV2Int64Ty).getKnownMinSize(), 16U); + EXPECT_EQ(DL.getTypeAllocSize(ScV4Int32Ty), + DL.getTypeAllocSize(ScV2Int64Ty)); + EXPECT_NE(DL.getTypeAllocSizeInBits(ScV2Int32Ty), + DL.getTypeAllocSizeInBits(ScV2Int64Ty)); + EXPECT_EQ(DL.getTypeAllocSizeInBits(ScV4Int32Ty).getKnownMinSize(), 128U); + EXPECT_EQ(DL.getTypeAllocSize(ScV2Int32Ty).getKnownMinSize(), 8U); + ASSERT_TRUE(DL.typeSizeEqualsStoreSize(ScV4Int32Ty)); +} + +TEST(VectorTypesTest, CrossComparisons) { + LLVMContext Ctx; + + Type *Int32Ty = Type::getInt32Ty(Ctx); + + VectorType *V4Int32Ty = VectorType::get(Int32Ty, {4, false}); + VectorType *ScV4Int32Ty = VectorType::get(Int32Ty, {4, true}); + + // Even though the minimum size is the same, a scalable vector could be + // larger so we don't consider them to be the same size. + EXPECT_NE(V4Int32Ty->getPrimitiveSizeInBits(), + ScV4Int32Ty->getPrimitiveSizeInBits()); + // If we are only checking the minimum, then they are the same size. + EXPECT_EQ(V4Int32Ty->getPrimitiveSizeInBits().getKnownMinSize(), + ScV4Int32Ty->getPrimitiveSizeInBits().getKnownMinSize()); + + // We can't use ordering comparisons (<,<=,>,>=) between scalable and + // non-scalable vector sizes. +} + } // end anonymous namespace Index: llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp =================================================================== --- llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp +++ llvm/unittests/CodeGen/ScalableVectorMVTsTest.cpp @@ -10,7 +10,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Support/MachineValueType.h" -#include "llvm/Support/ScalableSize.h" +#include "llvm/Support/TypeSize.h" #include "gtest/gtest.h" using namespace llvm; Index: llvm/test/Other/scalable-vectors-core-ir.ll =================================================================== --- /dev/null +++ llvm/test/Other/scalable-vectors-core-ir.ll @@ -0,0 +1,393 @@ +; RUN: opt -S -verify < %s | FileCheck %s +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +;; Check supported instructions are accepted without dropping 'vscale'. +;; Same order as the LangRef + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Unary Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +define <vscale x 2 x double> @fneg(<vscale x 2 x double> %val) { +; CHECK-LABEL: @fneg +; CHECK: %r = fneg <vscale x 2 x double> %val +; CHECK-NEXT: ret <vscale x 2 x double> %r + %r = fneg <vscale x 2 x double> %val + ret <vscale x 2 x double> %r +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Binary Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define <vscale x 8 x i16> @add(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) { +; CHECK-LABEL: @add +; CHECK: %r = add <vscale x 8 x i16> %a, %b +; CHECK-NEXT: ret <vscale x 8 x i16> %r + %r = add <vscale x 8 x i16> %a, %b + ret <vscale x 8 x i16> %r +} + +define <vscale x 4 x float> @fadd(<vscale x 4 x float> %a, <vscale x 4 x float> %b) { +; CHECK-LABEL: @fadd +; CHECK: %r = fadd <vscale x 4 x float> %a, %b +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = fadd <vscale x 4 x float> %a, %b + ret <vscale x 4 x float> %r +} + +define <vscale x 4 x i32> @sub(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @sub +; CHECK: %r = sub <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = sub <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x float> @fsub(<vscale x 4 x float> %a, <vscale x 4 x float> %b) { +; CHECK-LABEL: @fsub +; CHECK: %r = fsub <vscale x 4 x float> %a, %b +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = fsub <vscale x 4 x float> %a, %b + ret <vscale x 4 x float> %r +} + +define <vscale x 4 x i32> @mul(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @mul +; CHECK: %r = mul <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = mul <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x float> @fmul(<vscale x 4 x float> %a, <vscale x 4 x float> %b) { +; CHECK-LABEL: @fmul +; CHECK: %r = fmul <vscale x 4 x float> %a, %b +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = fmul <vscale x 4 x float> %a, %b + ret <vscale x 4 x float> %r +} + +define <vscale x 4 x i32> @udiv(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @udiv +; CHECK: %r = udiv <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = udiv <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @sdiv(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @sdiv +; CHECK: %r = sdiv <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = sdiv <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x float> @fdiv(<vscale x 4 x float> %a, <vscale x 4 x float> %b) { +; CHECK-LABEL: @fdiv +; CHECK: %r = fdiv <vscale x 4 x float> %a, %b +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = fdiv <vscale x 4 x float> %a, %b + ret <vscale x 4 x float> %r +} + +define <vscale x 4 x i32> @urem(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @urem +; CHECK: %r = urem <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = urem <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @srem(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @srem +; CHECK: %r = srem <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = srem <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x float> @frem(<vscale x 4 x float> %a, <vscale x 4 x float> %b) { +; CHECK-LABEL: @frem +; CHECK: %r = frem <vscale x 4 x float> %a, %b +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = frem <vscale x 4 x float> %a, %b + ret <vscale x 4 x float> %r +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Bitwise Binary Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define <vscale x 4 x i32> @shl(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @shl +; CHECK: %r = shl <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = shl <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @lshr(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @lshr +; CHECK: %r = lshr <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = lshr <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @ashr(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @ashr +; CHECK: %r = ashr <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = ashr <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @and(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @and +; CHECK: %r = and <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = and <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @or(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @or +; CHECK: %r = or <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = or <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @xor(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @xor +; CHECK: %r = xor <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = xor <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i32> %r +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Vector Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define i64 @extractelement(<vscale x 2 x i64> %val) { +; CHECK-LABEL: @extractelement +; CHECK: %r = extractelement <vscale x 2 x i64> %val, i32 0 +; CHECK-NEXT: ret i64 %r + %r = extractelement <vscale x 2 x i64> %val, i32 0 + ret i64 %r +} + +define <vscale x 16 x i8> @insertelement(<vscale x 16 x i8> %vec, i8 %ins) { +; CHECK-LABEL: @insertelement +; CHECK: %r = insertelement <vscale x 16 x i8> %vec, i8 %ins, i32 0 +; CHECK-NEXT: ret <vscale x 16 x i8> %r + %r = insertelement <vscale x 16 x i8> %vec, i8 %ins, i32 0 + ret <vscale x 16 x i8> %r +} + +define <vscale x 8 x half> @shufflevector(half %val) { +; CHECK-LABEL: @shufflevector +; CHECK: %insvec = insertelement <vscale x 8 x half> undef, half %val, i32 0 +; CHECK-NEXT: %r = shufflevector <vscale x 8 x half> %insvec, <vscale x 8 x half> undef, <vscale x 8 x i32> zeroinitializer +; CHECK-NEXT: ret <vscale x 8 x half> %r + %insvec = insertelement <vscale x 8 x half> undef, half %val, i32 0 + %r = shufflevector <vscale x 8 x half> %insvec, <vscale x 8 x half> undef, <vscale x 8 x i32> zeroinitializer + ret <vscale x 8 x half> %r +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Memory Access and Addressing Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define void @alloca() { +; CHECK-LABEL: @alloca +; CHECK: %vec = alloca <vscale x 4 x i32> +; CHECK-NEXT: ret void + %vec = alloca <vscale x 4 x i32> + ret void +} + +define <vscale x 2 x double> @load(<vscale x 2 x double>* %ptr) { +; CHECK-LABEL: @load +; CHECK: %r = load <vscale x 2 x double>, <vscale x 2 x double>* %ptr +; CHECK-NEXT: ret <vscale x 2 x double> %r + %r = load <vscale x 2 x double>, <vscale x 2 x double>* %ptr + ret <vscale x 2 x double> %r +} + +define void @store(<vscale x 4 x i32> %data, <vscale x 4 x i32>* %ptr) { +; CHECK-LABEL: @store +; CHECK: store <vscale x 4 x i32> %data, <vscale x 4 x i32>* %ptr +; CHECK-NEXT: ret void + store <vscale x 4 x i32> %data, <vscale x 4 x i32>* %ptr + ret void +} + +define <vscale x 4 x float>* @getelementptr(<vscale x 4 x float>* %base) { +; CHECK-LABEL: @getelementptr +; CHECK: %r = getelementptr <vscale x 4 x float>, <vscale x 4 x float>* %base, i64 0 +; CHECK-NEXT: ret <vscale x 4 x float>* %r + %r = getelementptr <vscale x 4 x float>, <vscale x 4 x float>* %base, i64 0 + ret <vscale x 4 x float>* %r +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Conversion Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define <vscale x 4 x i32> @truncto(<vscale x 4 x i64> %val) { +; CHECK-LABEL: @truncto +; CHECK: %r = trunc <vscale x 4 x i64> %val to <vscale x 4 x i32> +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = trunc <vscale x 4 x i64> %val to <vscale x 4 x i32> + ret <vscale x 4 x i32> %r +} + +define <vscale x 2 x i64> @zextto(<vscale x 2 x i16> %val) { +; CHECK-LABEL: @zextto +; CHECK: %r = zext <vscale x 2 x i16> %val to <vscale x 2 x i64> +; CHECK-NEXT: ret <vscale x 2 x i64> %r + %r = zext <vscale x 2 x i16> %val to <vscale x 2 x i64> + ret <vscale x 2 x i64> %r +} + +define <vscale x 4 x i32> @sextto(<vscale x 4 x i8> %val) { +; CHECK-LABEL: @sextto +; CHECK: %r = sext <vscale x 4 x i8> %val to <vscale x 4 x i32> +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = sext <vscale x 4 x i8> %val to <vscale x 4 x i32> + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x half> @fptruncto(<vscale x 4 x float> %val) { +; CHECK-LABEL: @fptruncto +; CHECK: %r = fptrunc <vscale x 4 x float> %val to <vscale x 4 x half> +; CHECK-NEXT: ret <vscale x 4 x half> %r + %r = fptrunc <vscale x 4 x float> %val to <vscale x 4 x half> + ret <vscale x 4 x half> %r +} + +define <vscale x 2 x double> @fpextto(<vscale x 2 x half> %val) { +; CHECK-LABEL: @fpextto +; CHECK: %r = fpext <vscale x 2 x half> %val to <vscale x 2 x double> +; CHECK-NEXT: ret <vscale x 2 x double> %r + %r = fpext <vscale x 2 x half> %val to <vscale x 2 x double> + ret <vscale x 2 x double> %r +} + +define <vscale x 4 x i32> @fptouito(<vscale x 4 x float> %val) { +; CHECK-LABEL: @fptoui +; CHECK: %r = fptoui <vscale x 4 x float> %val to <vscale x 4 x i32> +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = fptoui <vscale x 4 x float> %val to <vscale x 4 x i32> + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x i32> @fptosito(<vscale x 4 x float> %val) { +; CHECK-LABEL: @fptosi +; CHECK: %r = fptosi <vscale x 4 x float> %val to <vscale x 4 x i32> +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = fptosi <vscale x 4 x float> %val to <vscale x 4 x i32> + ret <vscale x 4 x i32> %r +} + +define <vscale x 4 x float> @uitofpto(<vscale x 4 x i32> %val) { +; CHECK-LABEL: @uitofp +; CHECK: %r = uitofp <vscale x 4 x i32> %val to <vscale x 4 x float> +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = uitofp <vscale x 4 x i32> %val to <vscale x 4 x float> + ret <vscale x 4 x float> %r +} + +define <vscale x 4 x float> @sitofpto(<vscale x 4 x i32> %val) { +; CHECK-LABEL: @sitofp +; CHECK: %r = sitofp <vscale x 4 x i32> %val to <vscale x 4 x float> +; CHECK-NEXT: ret <vscale x 4 x float> %r + %r = sitofp <vscale x 4 x i32> %val to <vscale x 4 x float> + ret <vscale x 4 x float> %r +} + +define <vscale x 2 x i64> @ptrtointto(<vscale x 2 x i32*> %val) { +; CHECK-LABEL: @ptrtointto +; CHECK: %r = ptrtoint <vscale x 2 x i32*> %val to <vscale x 2 x i64> +; CHECK-NEXT: ret <vscale x 2 x i64> %r + %r = ptrtoint <vscale x 2 x i32*> %val to <vscale x 2 x i64> + ret <vscale x 2 x i64> %r +} + +define <vscale x 2 x i32*> @inttoptrto(<vscale x 2 x i64> %val) { +; CHECK-LABEL: @inttoptrto +; CHECK: %r = inttoptr <vscale x 2 x i64> %val to <vscale x 2 x i32*> +; CHECK-NEXT: ret <vscale x 2 x i32*> %r + %r = inttoptr <vscale x 2 x i64> %val to <vscale x 2 x i32*> + ret <vscale x 2 x i32*> %r +} + +define <vscale x 2 x i64> @bitcastto(<vscale x 2 x double> %a) { +; CHECK-LABEL: @bitcast +; CHECK: %r = bitcast <vscale x 2 x double> %a to <vscale x 2 x i64> +; CHECK-NEXT: ret <vscale x 2 x i64> %r + %r = bitcast <vscale x 2 x double> %a to <vscale x 2 x i64> + ret <vscale x 2 x i64> %r +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Other Operations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define <vscale x 4 x i1> @icmp(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: @icmp +; CHECK: %r = icmp eq <vscale x 4 x i32> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i1> %r + %r = icmp eq <vscale x 4 x i32> %a, %b + ret <vscale x 4 x i1> %r +} + +define <vscale x 4 x i1> @fcmp(<vscale x 4 x float> %a, <vscale x 4 x float> %b) { +; CHECK-LABEL: @fcmp +; CHECK: %r = fcmp une <vscale x 4 x float> %a, %b +; CHECK-NEXT: ret <vscale x 4 x i1> %r + %r = fcmp une <vscale x 4 x float> %a, %b + ret <vscale x 4 x i1> %r +} + +define <vscale x 16 x i8> @phi(<vscale x 16 x i8> %a, i32 %val) { +; CHECK-LABEL: @phi +; CHECK: %r = phi <vscale x 16 x i8> [ %a, %entry ], [ %added, %iszero ] +; CHECK-NEXT: ret <vscale x 16 x i8> %r +entry: + %cmp = icmp eq i32 %val, 0 + br i1 %cmp, label %iszero, label %end + +iszero: + %ins = insertelement <vscale x 16 x i8> undef, i8 1, i32 0 + %splatone = shufflevector <vscale x 16 x i8> %ins, <vscale x 16 x i8> undef, <vscale x 16 x i32> zeroinitializer + %added = add <vscale x 16 x i8> %a, %splatone + br label %end + +end: + %r = phi <vscale x 16 x i8> [ %a, %entry ], [ %added, %iszero ] + ret <vscale x 16 x i8> %r +} + +define <vscale x 8 x half> @select(<vscale x 8 x half> %a, <vscale x 8 x half> %b, <vscale x 8 x i1> %sval) { +; CHECK-LABEL: @select +; CHECK: %r = select <vscale x 8 x i1> %sval, <vscale x 8 x half> %a, <vscale x 8 x half> %b +; CHECK-NEXT: ret <vscale x 8 x half> %r + %r = select <vscale x 8 x i1> %sval, <vscale x 8 x half> %a, <vscale x 8 x half> %b + ret <vscale x 8 x half> %r +} + +declare <vscale x 4 x i32> @callee(<vscale x 4 x i32>) +define <vscale x 4 x i32> @call(<vscale x 4 x i32> %val) { +; CHECK-LABEL: @call +; CHECK: %r = call <vscale x 4 x i32> @callee(<vscale x 4 x i32> %val) +; CHECK-NEXT: ret <vscale x 4 x i32> %r + %r = call <vscale x 4 x i32> @callee(<vscale x 4 x i32> %val) + ret <vscale x 4 x i32> %r +} \ No newline at end of file Index: llvm/lib/Transforms/Scalar/SROA.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SROA.cpp +++ llvm/lib/Transforms/Scalar/SROA.cpp @@ -959,14 +959,16 @@ std::tie(UsedI, I) = Uses.pop_back_val(); if (LoadInst *LI = dyn_cast<LoadInst>(I)) { - Size = std::max(Size, DL.getTypeStoreSize(LI->getType())); + Size = std::max(Size, + DL.getTypeStoreSize(LI->getType()).getFixedSize()); continue; } if (StoreInst *SI = dyn_cast<StoreInst>(I)) { Value *Op = SI->getOperand(0); if (Op == UsedI) return SI; - Size = std::max(Size, DL.getTypeStoreSize(Op->getType())); + Size = std::max(Size, + DL.getTypeStoreSize(Op->getType()).getFixedSize()); continue; } Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -8511,7 +8511,7 @@ // Get the shift amount based on the scaling factor: // log2(sizeof(IdxTy)) - log2(8). uint64_t ShiftAmt = - countTrailingZeros(DL.getTypeStoreSizeInBits(IdxTy)) - 3; + countTrailingZeros(DL.getTypeStoreSizeInBits(IdxTy).getFixedSize()) - 3; // Is the constant foldable in the shift of the addressing mode? // I.e., shift amount is between 1 and 4 inclusive. if (ShiftAmt == 0 || ShiftAmt > 4) Index: llvm/lib/IR/Type.cpp =================================================================== --- llvm/lib/IR/Type.cpp +++ llvm/lib/IR/Type.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TypeSize.h" #include <cassert> #include <utility> @@ -111,18 +112,22 @@ return false; } -unsigned Type::getPrimitiveSizeInBits() const { +TypeSize Type::getPrimitiveSizeInBits() const { switch (getTypeID()) { - case Type::HalfTyID: return 16; - case Type::FloatTyID: return 32; - case Type::DoubleTyID: return 64; - case Type::X86_FP80TyID: return 80; - case Type::FP128TyID: return 128; - case Type::PPC_FP128TyID: return 128; - case Type::X86_MMXTyID: return 64; - case Type::IntegerTyID: return cast<IntegerType>(this)->getBitWidth(); - case Type::VectorTyID: return cast<VectorType>(this)->getBitWidth(); - default: return 0; + case Type::HalfTyID: return TypeSize::Fixed(16); + case Type::FloatTyID: return TypeSize::Fixed(32); + case Type::DoubleTyID: return TypeSize::Fixed(64); + case Type::X86_FP80TyID: return TypeSize::Fixed(80); + case Type::FP128TyID: return TypeSize::Fixed(128); + case Type::PPC_FP128TyID: return TypeSize::Fixed(128); + case Type::X86_MMXTyID: return TypeSize::Fixed(64); + case Type::IntegerTyID: + return TypeSize::Fixed(cast<IntegerType>(this)->getBitWidth()); + case Type::VectorTyID: { + const VectorType *VTy = cast<VectorType>(this); + return TypeSize(VTy->getBitWidth(), VTy->isScalable()); + } + default: return TypeSize::Fixed(0); } } Index: llvm/lib/IR/Instructions.cpp =================================================================== --- llvm/lib/IR/Instructions.cpp +++ llvm/lib/IR/Instructions.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/TypeSize.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -1796,7 +1797,7 @@ const Twine &Name, Instruction *InsertBefore) : Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(), - cast<VectorType>(Mask->getType())->getNumElements()), + cast<VectorType>(Mask->getType())->getElementCount()), ShuffleVector, OperandTraits<ShuffleVectorInst>::op_begin(this), OperandTraits<ShuffleVectorInst>::operands(this), @@ -1813,7 +1814,7 @@ const Twine &Name, BasicBlock *InsertAtEnd) : Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(), - cast<VectorType>(Mask->getType())->getNumElements()), + cast<VectorType>(Mask->getType())->getElementCount()), ShuffleVector, OperandTraits<ShuffleVectorInst>::op_begin(this), OperandTraits<ShuffleVectorInst>::operands(this), @@ -2986,8 +2987,8 @@ } // Get the bit sizes, we'll need these - unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr - unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr + auto SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr + auto DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr // Run through the possibilities ... if (DestTy->isIntegerTy()) { // Casting to integral @@ -3034,7 +3035,7 @@ if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) { if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy)) { - if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) { + if (SrcVecTy->getElementCount() == DestVecTy->getElementCount()) { // An element by element cast. Valid if casting the elements is valid. SrcTy = SrcVecTy->getElementType(); DestTy = DestVecTy->getElementType(); @@ -3048,12 +3049,12 @@ } } - unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr - unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr + auto SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr + auto DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr // Could still have vectors of pointers if the number of elements doesn't // match - if (SrcBits == 0 || DestBits == 0) + if (SrcBits.getKnownMinSize() == 0 || DestBits.getKnownMinSize() == 0) return false; if (SrcBits != DestBits) Index: llvm/lib/IR/DataLayout.cpp =================================================================== --- llvm/lib/IR/DataLayout.cpp +++ llvm/lib/IR/DataLayout.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/TypeSize.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -745,7 +746,10 @@ llvm_unreachable("Bad type for getAlignment!!!"); } - return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty), abi_or_pref, Ty); + // If we're dealing with a scalable vector, we just need the known minimum + // size for determining alignment. If not, we'll get the exact size. + return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty).getKnownMinSize(), + abi_or_pref, Ty); } unsigned DataLayout::getABITypeAlignment(Type *Ty) const { Index: llvm/lib/CodeGen/Analysis.cpp =================================================================== --- llvm/lib/CodeGen/Analysis.cpp +++ llvm/lib/CodeGen/Analysis.cpp @@ -309,7 +309,8 @@ NoopInput = Op; } else if (isa<TruncInst>(I) && TLI.allowTruncateForTailCall(Op->getType(), I->getType())) { - DataBits = std::min(DataBits, I->getType()->getPrimitiveSizeInBits()); + DataBits = std::min((uint64_t)DataBits, + I->getType()->getPrimitiveSizeInBits().getFixedSize()); NoopInput = Op; } else if (auto CS = ImmutableCallSite(I)) { const Value *ReturnedOp = CS.getReturnedArgOperand(); Index: llvm/lib/Analysis/InlineCost.cpp =================================================================== --- llvm/lib/Analysis/InlineCost.cpp +++ llvm/lib/Analysis/InlineCost.cpp @@ -436,7 +436,8 @@ if (auto *AllocSize = dyn_cast_or_null<ConstantInt>(Size)) { Type *Ty = I.getAllocatedType(); AllocatedSize = SaturatingMultiplyAdd( - AllocSize->getLimitedValue(), DL.getTypeAllocSize(Ty), AllocatedSize); + AllocSize->getLimitedValue(), DL.getTypeAllocSize(Ty).getFixedSize(), + AllocatedSize); return Base::visitAlloca(I); } } @@ -444,7 +445,8 @@ // Accumulate the allocated size. if (I.isStaticAlloca()) { Type *Ty = I.getAllocatedType(); - AllocatedSize = SaturatingAdd(DL.getTypeAllocSize(Ty), AllocatedSize); + AllocatedSize = SaturatingAdd(DL.getTypeAllocSize(Ty).getFixedSize(), + AllocatedSize); } // We will happily inline static alloca instructions. Index: llvm/include/llvm/Support/TypeSize.h =================================================================== --- /dev/null +++ llvm/include/llvm/Support/TypeSize.h @@ -0,0 +1,200 @@ +//===- TypeSize.h - Wrapper around type sizes -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides a struct that can be used to query the size of IR types +// which may be scalable vectors. It provides convenience operators so that +// it can be used in much the same way as a single scalar value. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPESIZE_H +#define LLVM_SUPPORT_TYPESIZE_H + +#include <tuple> + +namespace llvm { + +class ElementCount { +public: + unsigned Min; // Minimum number of vector elements. + bool Scalable; // If true, NumElements is a multiple of 'Min' determined + // at runtime rather than compile time. + + ElementCount(unsigned Min, bool Scalable) + : Min(Min), Scalable(Scalable) {} + + ElementCount operator*(unsigned RHS) { + return { Min * RHS, Scalable }; + } + ElementCount operator/(unsigned RHS) { + return { Min / RHS, Scalable }; + } + + bool operator==(const ElementCount& RHS) const { + return Min == RHS.Min && Scalable == RHS.Scalable; + } + bool operator!=(const ElementCount& RHS) const { + return !(*this == RHS); + } +}; + +// This class is used to represent the size of types. If the type is of fixed +// size, it will represent the exact size. If the type is a scalable vector, +// it will represent the known minimum size. +class TypeSize { + uint64_t MinSize; // The known minimum size. + bool IsScalable; // If true, then the runtime size is an integer multiple + // of MinSize. + +public: + constexpr TypeSize(uint64_t MinSize, bool Scalable) + : MinSize(MinSize), IsScalable(Scalable) {} + + static constexpr TypeSize Fixed(uint64_t Size) { + return TypeSize(Size, /*IsScalable=*/false); + } + + static constexpr TypeSize Scalable(uint64_t MinSize) { + return TypeSize(MinSize, /*IsScalable=*/true); + } + + // Scalable vector types with the same minimum size as a fixed size type are + // not guaranteed to be the same size at runtime, so they are never + // considered to be equal. + friend bool operator==(const TypeSize &LHS, const TypeSize &RHS) { + return std::tie(LHS.MinSize, LHS.IsScalable) == + std::tie(RHS.MinSize, RHS.IsScalable); + } + + friend bool operator!=(const TypeSize &LHS, const TypeSize &RHS) { + return !(LHS == RHS); + } + + // For many cases, size ordering between scalable and fixed size types cannot + // be determined at compile time, so such comparisons aren't allowed. + // + // e.g. <vscale x 2 x i16> could be bigger than <4 x i32> with a runtime + // vscale >= 5, equal sized with a vscale of 4, and smaller with + // a vscale <= 3. + // + // If the scalable flags match, just perform the requested comparison + // between the minimum sizes. + friend bool operator<(const TypeSize &LHS, const TypeSize &RHS) { + assert(LHS.IsScalable == RHS.IsScalable && + "Ordering comparison of scalable and fixed types"); + + return LHS.MinSize < RHS.MinSize; + } + + friend bool operator>(const TypeSize &LHS, const TypeSize &RHS) { + return RHS < LHS; + } + + friend bool operator<=(const TypeSize &LHS, const TypeSize &RHS) { + return !(RHS < LHS); + } + + friend bool operator>=(const TypeSize &LHS, const TypeSize& RHS) { + return !(LHS < RHS); + } + + // Convenience operators to obtain relative sizes independently of + // the scalable flag. + TypeSize operator*(unsigned RHS) const { + return { MinSize * RHS, IsScalable }; + } + + friend TypeSize operator*(const unsigned LHS, const TypeSize &RHS) { + return { LHS * RHS.MinSize, RHS.IsScalable }; + } + + TypeSize operator/(unsigned RHS) const { + return { MinSize / RHS, IsScalable }; + } + + // Return the minimum size with the assumption that the size is exact. + // Use in places where a scalable size doesn't make sense (e.g. non-vector + // types, or vectors in backends which don't support scalable vectors) + uint64_t getFixedSize() const { + assert(!Scalable && "Request for a fixed size on a scalable object"); + return MinSize; + } + + // Return the known minimum size. Use in places where the scalable property + // doesn't matter (e.g. determining alignment) or in conjunction with the + // isScalable method below. + uint64_t getKnownMinSize() const { + return MinSize; + } + + // Return whether or not the size is scalable. + bool isScalable() const { + return IsScalable; + } + + // Casts to a uint64_t if this is a fixed-width size. + // + // NOTE: This interface is obsolete and will be removed in a future version + // of LLVM in favour of calling getFixedSize() directly + operator uint64_t() const { + return getFixedSize(); + } + + // Additional convenience operators needed to avoid ambiguous parses + // TODO: Make uint64_t the default operator? + TypeSize operator*(uint64_t RHS) const { + return { MinSize * RHS, IsScalable }; + } + + TypeSize operator*(int RHS) const { + return { MinSize * RHS, IsScalable }; + } + + TypeSize operator*(int64_t RHS) const { + return { MinSize * RHS, IsScalable }; + } + + friend TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) { + return { LHS * RHS.MinSize, RHS.IsScalable }; + } + + friend TypeSize operator*(const int LHS, const TypeSize &RHS) { + return { LHS * RHS.MinSize, RHS.IsScalable }; + } + + friend TypeSize operator*(const int64_t LHS, const TypeSize &RHS) { + return { LHS * RHS.MinSize, RHS.IsScalable }; + } + + TypeSize operator/(uint64_t RHS) const { + return { MinSize / RHS, IsScalable }; + } + + TypeSize operator/(int RHS) const { + return { MinSize / RHS, IsScalable }; + } + + TypeSize operator/(int64_t RHS) const { + return { MinSize / RHS, IsScalable }; + } +}; + +/// Returns a TypeSize with a known minimum size that is the next integer +/// (mod 2**64) that is greater than or equal to \p Value and is a multiple +/// of \p Align. \p Align must be non-zero. +/// +/// Similar to the alignTo functions in MathExtras.h +inline TypeSize alignTo(TypeSize Size, uint64_t Align) { + assert(Align != 0u && "Align must be non-zero"); + return {(Size.getKnownMinSize() + Align - 1) / Align * Align, + Size.isScalable()}; +} + +} // end namespace llvm + +#endif // LLVM_SUPPORT_TypeSize_H Index: llvm/include/llvm/Support/ScalableSize.h =================================================================== --- llvm/include/llvm/Support/ScalableSize.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- ScalableSize.h - Scalable vector size info ---------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides a struct that can be used to query the size of IR types -// which may be scalable vectors. It provides convenience operators so that -// it can be used in much the same way as a single scalar value. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_SCALABLESIZE_H -#define LLVM_SUPPORT_SCALABLESIZE_H - -namespace llvm { - -class ElementCount { -public: - unsigned Min; // Minimum number of vector elements. - bool Scalable; // If true, NumElements is a multiple of 'Min' determined - // at runtime rather than compile time. - - ElementCount(unsigned Min, bool Scalable) - : Min(Min), Scalable(Scalable) {} - - ElementCount operator*(unsigned RHS) { - return { Min * RHS, Scalable }; - } - ElementCount operator/(unsigned RHS) { - return { Min / RHS, Scalable }; - } - - bool operator==(const ElementCount& RHS) const { - return Min == RHS.Min && Scalable == RHS.Scalable; - } - bool operator!=(const ElementCount& RHS) const { - return !(*this == RHS); - } -}; - -} // end namespace llvm - -#endif // LLVM_SUPPORT_SCALABLESIZE_H Index: llvm/include/llvm/Support/MachineValueType.h =================================================================== --- llvm/include/llvm/Support/MachineValueType.h +++ llvm/include/llvm/Support/MachineValueType.h @@ -17,7 +17,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/ScalableSize.h" +#include "llvm/Support/TypeSize.h" #include <cassert> namespace llvm { Index: llvm/include/llvm/IR/Type.h =================================================================== --- llvm/include/llvm/IR/Type.h +++ llvm/include/llvm/IR/Type.h @@ -21,6 +21,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TypeSize.h" #include <cassert> #include <cstdint> #include <iterator> @@ -281,12 +282,15 @@ /// This will return zero if the type does not have a size or is not a /// primitive type. /// + /// If this is a scalable vector type, the scalable property will be set and + /// the runtime size will be a positive integer multiple of the base size. + /// /// Note that this may not reflect the size of memory allocated for an /// instance of the type or the number of bytes that are written when an /// instance of the type is stored to memory. The DataLayout class provides /// additional query functions to provide this information. /// - unsigned getPrimitiveSizeInBits() const LLVM_READONLY; + TypeSize getPrimitiveSizeInBits() const LLVM_READONLY; /// If this is a vector type, return the getPrimitiveSizeInBits value for the /// element type. Otherwise return the getPrimitiveSizeInBits value for this Index: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -975,7 +975,7 @@ static Type* makeCmpResultType(Type* opnd_type) { if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) { return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), - vt->getNumElements()); + vt->getElementCount()); } return Type::getInt1Ty(opnd_type->getContext()); } Index: llvm/include/llvm/IR/DerivedTypes.h =================================================================== --- llvm/include/llvm/IR/DerivedTypes.h +++ llvm/include/llvm/IR/DerivedTypes.h @@ -23,7 +23,7 @@ #include "llvm/IR/Type.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/ScalableSize.h" +#include "llvm/Support/TypeSize.h" #include <cassert> #include <cstdint> Index: llvm/include/llvm/IR/DataLayout.h =================================================================== --- llvm/include/llvm/IR/DataLayout.h +++ llvm/include/llvm/IR/DataLayout.h @@ -30,6 +30,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Alignment.h" +#include "llvm/Support/TypeSize.h" #include <cassert> #include <cstdint> #include <string> @@ -437,23 +438,33 @@ /// Returns the number of bits necessary to hold the specified type. /// + /// If Ty is a scalable vector type, the scalable property will be set and + /// the runtime size will be a positive integer multiple of the base size. + /// /// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must /// have a size (Type::isSized() must return true). - uint64_t getTypeSizeInBits(Type *Ty) const; + TypeSize getTypeSizeInBits(Type *Ty) const; /// Returns the maximum number of bytes that may be overwritten by /// storing the specified type. /// + /// If Ty is a scalable vector type, the scalable property will be set and + /// the runtime size will be a positive integer multiple of the base size. + /// /// For example, returns 5 for i36 and 10 for x86_fp80. - uint64_t getTypeStoreSize(Type *Ty) const { - return (getTypeSizeInBits(Ty) + 7) / 8; + TypeSize getTypeStoreSize(Type *Ty) const { + auto BaseSize = getTypeSizeInBits(Ty); + return { (BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable() }; } /// Returns the maximum number of bits that may be overwritten by /// storing the specified type; always a multiple of 8. /// + /// If Ty is a scalable vector type, the scalable property will be set and + /// the runtime size will be a positive integer multiple of the base size. + /// /// For example, returns 40 for i36 and 80 for x86_fp80. - uint64_t getTypeStoreSizeInBits(Type *Ty) const { + TypeSize getTypeStoreSizeInBits(Type *Ty) const { return 8 * getTypeStoreSize(Ty); } @@ -468,9 +479,12 @@ /// Returns the offset in bytes between successive objects of the /// specified type, including alignment padding. /// + /// If Ty is a scalable vector type, the scalable property will be set and + /// the runtime size will be a positive integer multiple of the base size. + /// /// This is the amount that alloca reserves for this type. For example, /// returns 12 or 16 for x86_fp80, depending on alignment. - uint64_t getTypeAllocSize(Type *Ty) const { + TypeSize getTypeAllocSize(Type *Ty) const { // Round up to the next alignment boundary. return alignTo(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); } @@ -478,9 +492,12 @@ /// Returns the offset in bits between successive objects of the /// specified type, including alignment padding; always a multiple of 8. /// + /// If Ty is a scalable vector type, the scalable property will be set and + /// the runtime size will be a positive integer multiple of the base size. + /// /// This is the amount that alloca reserves for this type. For example, /// returns 96 or 128 for x86_fp80, depending on alignment. - uint64_t getTypeAllocSizeInBits(Type *Ty) const { + TypeSize getTypeAllocSizeInBits(Type *Ty) const { return 8 * getTypeAllocSize(Ty); } @@ -598,13 +615,13 @@ // The implementation of this method is provided inline as it is particularly // well suited to constant folding when called on a specific Type subclass. -inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { +inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const { assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); switch (Ty->getTypeID()) { case Type::LabelTyID: - return getPointerSizeInBits(0); + return TypeSize::Fixed(getPointerSizeInBits(0)); case Type::PointerTyID: - return getPointerSizeInBits(Ty->getPointerAddressSpace()); + return TypeSize::Fixed(getPointerSizeInBits(Ty->getPointerAddressSpace())); case Type::ArrayTyID: { ArrayType *ATy = cast<ArrayType>(Ty); return ATy->getNumElements() * @@ -612,26 +629,30 @@ } case Type::StructTyID: // Get the layout annotation... which is lazily created on demand. - return getStructLayout(cast<StructType>(Ty))->getSizeInBits(); + return TypeSize::Fixed( + getStructLayout(cast<StructType>(Ty))->getSizeInBits()); case Type::IntegerTyID: - return Ty->getIntegerBitWidth(); + return TypeSize::Fixed(Ty->getIntegerBitWidth()); case Type::HalfTyID: - return 16; + return TypeSize::Fixed(16); case Type::FloatTyID: - return 32; + return TypeSize::Fixed(32); case Type::DoubleTyID: case Type::X86_MMXTyID: - return 64; + return TypeSize::Fixed(64); case Type::PPC_FP128TyID: case Type::FP128TyID: - return 128; + return TypeSize::Fixed(128); // In memory objects this is always aligned to a higher boundary, but // only 80 bits contain information. case Type::X86_FP80TyID: - return 80; + return TypeSize::Fixed(80); case Type::VectorTyID: { VectorType *VTy = cast<VectorType>(Ty); - return VTy->getNumElements() * getTypeSizeInBits(VTy->getElementType()); + auto EltCnt = VTy->getElementCount(); + uint64_t MinBits = EltCnt.Min * + getTypeSizeInBits(VTy->getElementType()).getFixedSize(); + return TypeSize(MinBits, EltCnt.Scalable); } default: llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type"); Index: llvm/include/llvm/ADT/DenseMapInfo.h =================================================================== --- llvm/include/llvm/ADT/DenseMapInfo.h +++ llvm/include/llvm/ADT/DenseMapInfo.h @@ -17,7 +17,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/PointerLikeTypeTraits.h" -#include "llvm/Support/ScalableSize.h" +#include "llvm/Support/TypeSize.h" #include <cassert> #include <cstddef> #include <cstdint> Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -431,13 +431,13 @@ // Scan function arguments for vector width. for (llvm::Argument &A : CurFn->args()) if (auto *VT = dyn_cast<llvm::VectorType>(A.getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); // Update vector width based on return type. if (auto *VT = dyn_cast<llvm::VectorType>(CurFn->getReturnType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); // Add the required-vector-width attribute. This contains the max width from: // 1. min-vector-width attribute used in the source program. Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -2073,8 +2073,8 @@ // Update largest vector width for any vector types. if (auto *VT = dyn_cast<llvm::VectorType>(ResultRegTypes.back())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); } else { ArgTypes.push_back(Dest.getAddress().getType()); Args.push_back(Dest.getPointer()); @@ -2098,8 +2098,8 @@ // Update largest vector width for any vector types. if (auto *VT = dyn_cast<llvm::VectorType>(Arg->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); if (Info.allowsRegister()) InOutConstraints += llvm::utostr(i); else @@ -2185,8 +2185,8 @@ // Update largest vector width for any vector types. if (auto *VT = dyn_cast<llvm::VectorType>(Arg->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); ArgTypes.push_back(Arg->getType()); Args.push_back(Arg); Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -4277,8 +4277,8 @@ // Update the largest vector width if any arguments have vector types. for (unsigned i = 0; i < IRCallArgs.size(); ++i) { if (auto *VT = dyn_cast<llvm::VectorType>(IRCallArgs[i]->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); } // Compute the calling convention and attributes. @@ -4361,8 +4361,8 @@ // Update largest vector width from the return type. if (auto *VT = dyn_cast<llvm::VectorType>(CI->getType())) - LargestVectorWidth = std::max(LargestVectorWidth, - VT->getPrimitiveSizeInBits()); + LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getFixedSize()); // Insert instrumentation or attach profile metadata at indirect call sites. // For more details, see the comment before the definition of
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits