1 //===--- llvm/unittest/IR/VectorTypesTest.cpp - vector types unit tests ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/IR/DataLayout.h" 10 #include "llvm/IR/DerivedTypes.h" 11 #include "llvm/IR/LLVMContext.h" 12 #include "llvm/Support/TypeSize.h" 13 #include "gtest/gtest.h" 14 using namespace llvm; 15 16 namespace { 17 18 #define EXPECT_VTY_EQ(LHS, RHS) \ 19 do { \ 20 ASSERT_NE(LHS, nullptr) << #LHS << " must not be null"; \ 21 ASSERT_NE(RHS, nullptr) << #RHS << " must not be null"; \ 22 EXPECT_EQ(LHS, RHS) << "Expect that " << #LHS << " == " << #RHS \ 23 << " where " << #LHS << " = " << *LHS << " and " \ 24 << #RHS << " = " << *RHS; \ 25 } while (false) 26 27 #define EXPECT_VTY_NE(LHS, RHS) \ 28 do { \ 29 ASSERT_NE(LHS, nullptr) << #LHS << " must not be null"; \ 30 ASSERT_NE(RHS, nullptr) << #RHS << " must not be null"; \ 31 EXPECT_NE(LHS, RHS) << "Expect that " << #LHS << " != " << #RHS \ 32 << " where " << #LHS << " = " << *LHS << " and " \ 33 << #RHS << " = " << *RHS; \ 34 } while (false) 35 36 TEST(VectorTypesTest, FixedLength) { 37 LLVMContext Ctx; 38 39 Type *Int8Ty = Type::getInt8Ty(Ctx); 40 Type *Int16Ty = Type::getInt16Ty(Ctx); 41 Type *Int32Ty = Type::getInt32Ty(Ctx); 42 Type *Int64Ty = Type::getInt64Ty(Ctx); 43 Type *Float64Ty = Type::getDoubleTy(Ctx); 44 45 auto *V16Int8Ty = FixedVectorType::get(Int8Ty, 16); 46 ASSERT_NE(nullptr, V16Int8Ty); 47 EXPECT_EQ(V16Int8Ty->getNumElements(), 16U); 48 EXPECT_EQ(V16Int8Ty->getElementType()->getScalarSizeInBits(), 8U); 49 50 auto *V8Int32Ty = 51 dyn_cast<FixedVectorType>(VectorType::get(Int32Ty, 8, false)); 52 ASSERT_NE(nullptr, V8Int32Ty); 53 EXPECT_EQ(V8Int32Ty->getNumElements(), 8U); 54 EXPECT_EQ(V8Int32Ty->getElementType()->getScalarSizeInBits(), 32U); 55 56 auto *V8Int8Ty = 57 dyn_cast<FixedVectorType>(VectorType::get(Int8Ty, V8Int32Ty)); 58 EXPECT_VTY_NE(V8Int32Ty, V8Int8Ty); 59 EXPECT_EQ(V8Int8Ty->getElementCount(), V8Int32Ty->getElementCount()); 60 EXPECT_EQ(V8Int8Ty->getElementType()->getScalarSizeInBits(), 8U); 61 62 auto *V8Int32Ty2 = 63 dyn_cast<FixedVectorType>(VectorType::get(Int32Ty, V8Int32Ty)); 64 EXPECT_VTY_EQ(V8Int32Ty, V8Int32Ty2); 65 66 auto *V8Int16Ty = dyn_cast<FixedVectorType>( 67 VectorType::get(Int16Ty, ElementCount::getFixed(8))); 68 ASSERT_NE(nullptr, V8Int16Ty); 69 EXPECT_EQ(V8Int16Ty->getNumElements(), 8U); 70 EXPECT_EQ(V8Int16Ty->getElementType()->getScalarSizeInBits(), 16U); 71 72 auto EltCnt = ElementCount::getFixed(4); 73 auto *V4Int64Ty = dyn_cast<FixedVectorType>(VectorType::get(Int64Ty, EltCnt)); 74 ASSERT_NE(nullptr, V4Int64Ty); 75 EXPECT_EQ(V4Int64Ty->getNumElements(), 4U); 76 EXPECT_EQ(V4Int64Ty->getElementType()->getScalarSizeInBits(), 64U); 77 78 auto *V2Int64Ty = dyn_cast<FixedVectorType>( 79 VectorType::get(Int64Ty, EltCnt.divideCoefficientBy(2))); 80 ASSERT_NE(nullptr, V2Int64Ty); 81 EXPECT_EQ(V2Int64Ty->getNumElements(), 2U); 82 EXPECT_EQ(V2Int64Ty->getElementType()->getScalarSizeInBits(), 64U); 83 84 auto *V8Int64Ty = 85 dyn_cast<FixedVectorType>(VectorType::get(Int64Ty, EltCnt * 2)); 86 ASSERT_NE(nullptr, V8Int64Ty); 87 EXPECT_EQ(V8Int64Ty->getNumElements(), 8U); 88 EXPECT_EQ(V8Int64Ty->getElementType()->getScalarSizeInBits(), 64U); 89 90 auto *V4Float64Ty = 91 dyn_cast<FixedVectorType>(VectorType::get(Float64Ty, EltCnt)); 92 ASSERT_NE(nullptr, V4Float64Ty); 93 EXPECT_EQ(V4Float64Ty->getNumElements(), 4U); 94 EXPECT_EQ(V4Float64Ty->getElementType()->getScalarSizeInBits(), 64U); 95 96 auto *ExtTy = dyn_cast<FixedVectorType>( 97 VectorType::getExtendedElementVectorType(V8Int16Ty)); 98 EXPECT_VTY_EQ(ExtTy, V8Int32Ty); 99 EXPECT_EQ(ExtTy->getNumElements(), 8U); 100 EXPECT_EQ(ExtTy->getElementType()->getScalarSizeInBits(), 32U); 101 102 auto *TruncTy = dyn_cast<FixedVectorType>( 103 VectorType::getTruncatedElementVectorType(V8Int32Ty)); 104 EXPECT_VTY_EQ(TruncTy, V8Int16Ty); 105 EXPECT_EQ(TruncTy->getNumElements(), 8U); 106 EXPECT_EQ(TruncTy->getElementType()->getScalarSizeInBits(), 16U); 107 108 auto *HalvedTy = dyn_cast<FixedVectorType>( 109 VectorType::getHalfElementsVectorType(V4Int64Ty)); 110 EXPECT_VTY_EQ(HalvedTy, V2Int64Ty); 111 EXPECT_EQ(HalvedTy->getNumElements(), 2U); 112 EXPECT_EQ(HalvedTy->getElementType()->getScalarSizeInBits(), 64U); 113 114 auto *DoubledTy = dyn_cast<FixedVectorType>( 115 VectorType::getDoubleElementsVectorType(V4Int64Ty)); 116 EXPECT_VTY_EQ(DoubledTy, V8Int64Ty); 117 EXPECT_EQ(DoubledTy->getNumElements(), 8U); 118 EXPECT_EQ(DoubledTy->getElementType()->getScalarSizeInBits(), 64U); 119 120 auto *ConvTy = dyn_cast<FixedVectorType>(VectorType::getInteger(V4Float64Ty)); 121 EXPECT_VTY_EQ(ConvTy, V4Int64Ty); 122 EXPECT_EQ(ConvTy->getNumElements(), 4U); 123 EXPECT_EQ(ConvTy->getElementType()->getScalarSizeInBits(), 64U); 124 125 EltCnt = V8Int64Ty->getElementCount(); 126 EXPECT_EQ(EltCnt.getKnownMinValue(), 8U); 127 ASSERT_FALSE(EltCnt.isScalable()); 128 129 auto *SubTy = VectorType::getSubdividedVectorType(V4Int64Ty, 2); 130 EXPECT_EQ(SubTy->getElementCount(), ElementCount::getFixed(16)); 131 EXPECT_TRUE(SubTy->getElementType()->isIntegerTy(16)); 132 } 133 134 TEST(VectorTypesTest, Scalable) { 135 LLVMContext Ctx; 136 137 Type *Int8Ty = Type::getInt8Ty(Ctx); 138 Type *Int16Ty = Type::getInt16Ty(Ctx); 139 Type *Int32Ty = Type::getInt32Ty(Ctx); 140 Type *Int64Ty = Type::getInt64Ty(Ctx); 141 Type *Float64Ty = Type::getDoubleTy(Ctx); 142 143 auto *ScV16Int8Ty = ScalableVectorType::get(Int8Ty, 16); 144 ASSERT_NE(nullptr, ScV16Int8Ty); 145 EXPECT_EQ(ScV16Int8Ty->getMinNumElements(), 16U); 146 EXPECT_EQ(ScV16Int8Ty->getScalarSizeInBits(), 8U); 147 148 auto *ScV8Int32Ty = 149 dyn_cast<ScalableVectorType>(VectorType::get(Int32Ty, 8, true)); 150 ASSERT_NE(nullptr, ScV8Int32Ty); 151 EXPECT_EQ(ScV8Int32Ty->getMinNumElements(), 8U); 152 EXPECT_EQ(ScV8Int32Ty->getElementType()->getScalarSizeInBits(), 32U); 153 154 auto *ScV8Int8Ty = 155 dyn_cast<ScalableVectorType>(VectorType::get(Int8Ty, ScV8Int32Ty)); 156 EXPECT_VTY_NE(ScV8Int32Ty, ScV8Int8Ty); 157 EXPECT_EQ(ScV8Int8Ty->getElementCount(), ScV8Int32Ty->getElementCount()); 158 EXPECT_EQ(ScV8Int8Ty->getElementType()->getScalarSizeInBits(), 8U); 159 160 auto *ScV8Int32Ty2 = 161 dyn_cast<ScalableVectorType>(VectorType::get(Int32Ty, ScV8Int32Ty)); 162 EXPECT_VTY_EQ(ScV8Int32Ty, ScV8Int32Ty2); 163 164 auto *ScV8Int16Ty = dyn_cast<ScalableVectorType>( 165 VectorType::get(Int16Ty, ElementCount::getScalable(8))); 166 ASSERT_NE(nullptr, ScV8Int16Ty); 167 EXPECT_EQ(ScV8Int16Ty->getMinNumElements(), 8U); 168 EXPECT_EQ(ScV8Int16Ty->getElementType()->getScalarSizeInBits(), 16U); 169 170 auto EltCnt = ElementCount::getScalable(4); 171 auto *ScV4Int64Ty = 172 dyn_cast<ScalableVectorType>(VectorType::get(Int64Ty, EltCnt)); 173 ASSERT_NE(nullptr, ScV4Int64Ty); 174 EXPECT_EQ(ScV4Int64Ty->getMinNumElements(), 4U); 175 EXPECT_EQ(ScV4Int64Ty->getElementType()->getScalarSizeInBits(), 64U); 176 177 auto *ScV2Int64Ty = dyn_cast<ScalableVectorType>( 178 VectorType::get(Int64Ty, EltCnt.divideCoefficientBy(2))); 179 ASSERT_NE(nullptr, ScV2Int64Ty); 180 EXPECT_EQ(ScV2Int64Ty->getMinNumElements(), 2U); 181 EXPECT_EQ(ScV2Int64Ty->getElementType()->getScalarSizeInBits(), 64U); 182 183 auto *ScV8Int64Ty = 184 dyn_cast<ScalableVectorType>(VectorType::get(Int64Ty, EltCnt * 2)); 185 ASSERT_NE(nullptr, ScV8Int64Ty); 186 EXPECT_EQ(ScV8Int64Ty->getMinNumElements(), 8U); 187 EXPECT_EQ(ScV8Int64Ty->getElementType()->getScalarSizeInBits(), 64U); 188 189 auto *ScV4Float64Ty = 190 dyn_cast<ScalableVectorType>(VectorType::get(Float64Ty, EltCnt)); 191 ASSERT_NE(nullptr, ScV4Float64Ty); 192 EXPECT_EQ(ScV4Float64Ty->getMinNumElements(), 4U); 193 EXPECT_EQ(ScV4Float64Ty->getElementType()->getScalarSizeInBits(), 64U); 194 195 auto *ExtTy = dyn_cast<ScalableVectorType>( 196 VectorType::getExtendedElementVectorType(ScV8Int16Ty)); 197 EXPECT_VTY_EQ(ExtTy, ScV8Int32Ty); 198 EXPECT_EQ(ExtTy->getMinNumElements(), 8U); 199 EXPECT_EQ(ExtTy->getElementType()->getScalarSizeInBits(), 32U); 200 201 auto *TruncTy = dyn_cast<ScalableVectorType>( 202 VectorType::getTruncatedElementVectorType(ScV8Int32Ty)); 203 EXPECT_VTY_EQ(TruncTy, ScV8Int16Ty); 204 EXPECT_EQ(TruncTy->getMinNumElements(), 8U); 205 EXPECT_EQ(TruncTy->getElementType()->getScalarSizeInBits(), 16U); 206 207 auto *HalvedTy = dyn_cast<ScalableVectorType>( 208 VectorType::getHalfElementsVectorType(ScV4Int64Ty)); 209 EXPECT_VTY_EQ(HalvedTy, ScV2Int64Ty); 210 EXPECT_EQ(HalvedTy->getMinNumElements(), 2U); 211 EXPECT_EQ(HalvedTy->getElementType()->getScalarSizeInBits(), 64U); 212 213 auto *DoubledTy = dyn_cast<ScalableVectorType>( 214 VectorType::getDoubleElementsVectorType(ScV4Int64Ty)); 215 EXPECT_VTY_EQ(DoubledTy, ScV8Int64Ty); 216 EXPECT_EQ(DoubledTy->getMinNumElements(), 8U); 217 EXPECT_EQ(DoubledTy->getElementType()->getScalarSizeInBits(), 64U); 218 219 auto *ConvTy = 220 dyn_cast<ScalableVectorType>(VectorType::getInteger(ScV4Float64Ty)); 221 EXPECT_VTY_EQ(ConvTy, ScV4Int64Ty); 222 EXPECT_EQ(ConvTy->getMinNumElements(), 4U); 223 EXPECT_EQ(ConvTy->getElementType()->getScalarSizeInBits(), 64U); 224 225 EltCnt = ScV8Int64Ty->getElementCount(); 226 EXPECT_EQ(EltCnt.getKnownMinValue(), 8U); 227 ASSERT_TRUE(EltCnt.isScalable()); 228 } 229 230 TEST(VectorTypesTest, BaseVectorType) { 231 LLVMContext Ctx; 232 233 Type *Int16Ty = Type::getInt16Ty(Ctx); 234 Type *Int32Ty = Type::getInt32Ty(Ctx); 235 236 std::array<VectorType *, 8> VTys = { 237 VectorType::get(Int16Ty, ElementCount::getScalable(4)), 238 VectorType::get(Int16Ty, ElementCount::getFixed(4)), 239 VectorType::get(Int16Ty, ElementCount::getScalable(2)), 240 VectorType::get(Int16Ty, ElementCount::getFixed(2)), 241 VectorType::get(Int32Ty, ElementCount::getScalable(4)), 242 VectorType::get(Int32Ty, ElementCount::getFixed(4)), 243 VectorType::get(Int32Ty, ElementCount::getScalable(2)), 244 VectorType::get(Int32Ty, ElementCount::getFixed(2))}; 245 246 /* 247 The comparison matrix is symmetric, so we only check the upper triangle: 248 249 (0,0) (0,1) (0,2) ... (0,7) 250 (1,0) (1,1) (1,2) . 251 (2,0) (2,1) (2,2) . 252 . . . 253 . . 254 . . 255 (7,0) ... (7,7) 256 */ 257 for (size_t I = 0, IEnd = VTys.size(); I < IEnd; ++I) { 258 // test I == J 259 VectorType *VI = VTys[I]; 260 ElementCount ECI = VI->getElementCount(); 261 EXPECT_EQ(isa<ScalableVectorType>(VI), ECI.isScalable()); 262 263 for (size_t J = I + 1, JEnd = VTys.size(); J < JEnd; ++J) { 264 // test I < J 265 VectorType *VJ = VTys[J]; 266 EXPECT_VTY_NE(VI, VJ); 267 268 VectorType *VJPrime = VectorType::get(VI->getElementType(), VJ); 269 if (VI->getElementType() == VJ->getElementType()) { 270 EXPECT_VTY_EQ(VJ, VJPrime); 271 } else { 272 EXPECT_VTY_NE(VJ, VJPrime); 273 } 274 275 EXPECT_EQ(VJ->getTypeID(), VJPrime->getTypeID()) 276 << "VJ and VJPrime are the same sort of vector"; 277 } 278 } 279 } 280 281 TEST(VectorTypesTest, FixedLenComparisons) { 282 LLVMContext Ctx; 283 DataLayout DL; 284 285 Type *Int32Ty = Type::getInt32Ty(Ctx); 286 Type *Int64Ty = Type::getInt64Ty(Ctx); 287 288 auto *V2Int32Ty = FixedVectorType::get(Int32Ty, 2); 289 auto *V4Int32Ty = FixedVectorType::get(Int32Ty, 4); 290 291 auto *V2Int64Ty = FixedVectorType::get(Int64Ty, 2); 292 293 TypeSize V2I32Len = V2Int32Ty->getPrimitiveSizeInBits(); 294 EXPECT_EQ(V2I32Len.getKnownMinValue(), 64U); 295 EXPECT_FALSE(V2I32Len.isScalable()); 296 297 EXPECT_LT(V2Int32Ty->getPrimitiveSizeInBits().getFixedValue(), 298 V4Int32Ty->getPrimitiveSizeInBits().getFixedValue()); 299 EXPECT_GT(V2Int64Ty->getPrimitiveSizeInBits().getFixedValue(), 300 V2Int32Ty->getPrimitiveSizeInBits().getFixedValue()); 301 EXPECT_EQ(V4Int32Ty->getPrimitiveSizeInBits(), 302 V2Int64Ty->getPrimitiveSizeInBits()); 303 EXPECT_NE(V2Int32Ty->getPrimitiveSizeInBits(), 304 V2Int64Ty->getPrimitiveSizeInBits()); 305 306 // Check that a fixed-only comparison works for fixed size vectors. 307 EXPECT_EQ(V2Int64Ty->getPrimitiveSizeInBits().getFixedValue(), 308 V4Int32Ty->getPrimitiveSizeInBits().getFixedValue()); 309 310 // Check the DataLayout interfaces. 311 EXPECT_EQ(DL.getTypeSizeInBits(V2Int64Ty), DL.getTypeSizeInBits(V4Int32Ty)); 312 EXPECT_EQ(DL.getTypeSizeInBits(V2Int32Ty), 64U); 313 EXPECT_EQ(DL.getTypeSizeInBits(V2Int64Ty), 128U); 314 EXPECT_EQ(DL.getTypeStoreSize(V2Int64Ty), DL.getTypeStoreSize(V4Int32Ty)); 315 EXPECT_NE(DL.getTypeStoreSizeInBits(V2Int32Ty), 316 DL.getTypeStoreSizeInBits(V2Int64Ty)); 317 EXPECT_EQ(DL.getTypeStoreSizeInBits(V2Int32Ty), 64U); 318 EXPECT_EQ(DL.getTypeStoreSize(V2Int64Ty), 16U); 319 EXPECT_EQ(DL.getTypeAllocSize(V4Int32Ty), DL.getTypeAllocSize(V2Int64Ty)); 320 EXPECT_NE(DL.getTypeAllocSizeInBits(V2Int32Ty), 321 DL.getTypeAllocSizeInBits(V2Int64Ty)); 322 EXPECT_EQ(DL.getTypeAllocSizeInBits(V4Int32Ty), 128U); 323 EXPECT_EQ(DL.getTypeAllocSize(V2Int32Ty), 8U); 324 ASSERT_TRUE(DL.typeSizeEqualsStoreSize(V4Int32Ty)); 325 } 326 327 TEST(VectorTypesTest, ScalableComparisons) { 328 LLVMContext Ctx; 329 DataLayout DL; 330 331 Type *Int32Ty = Type::getInt32Ty(Ctx); 332 Type *Int64Ty = Type::getInt64Ty(Ctx); 333 334 auto *ScV2Int32Ty = ScalableVectorType::get(Int32Ty, 2); 335 auto *ScV4Int32Ty = ScalableVectorType::get(Int32Ty, 4); 336 337 auto *ScV2Int64Ty = ScalableVectorType::get(Int64Ty, 2); 338 339 TypeSize ScV2I32Len = ScV2Int32Ty->getPrimitiveSizeInBits(); 340 EXPECT_EQ(ScV2I32Len.getKnownMinValue(), 64U); 341 EXPECT_TRUE(ScV2I32Len.isScalable()); 342 343 EXPECT_LT(ScV2Int32Ty->getPrimitiveSizeInBits().getKnownMinValue(), 344 ScV4Int32Ty->getPrimitiveSizeInBits().getKnownMinValue()); 345 EXPECT_GT(ScV2Int64Ty->getPrimitiveSizeInBits().getKnownMinValue(), 346 ScV2Int32Ty->getPrimitiveSizeInBits().getKnownMinValue()); 347 EXPECT_EQ(ScV4Int32Ty->getPrimitiveSizeInBits().getKnownMinValue(), 348 ScV2Int64Ty->getPrimitiveSizeInBits().getKnownMinValue()); 349 EXPECT_NE(ScV2Int32Ty->getPrimitiveSizeInBits().getKnownMinValue(), 350 ScV2Int64Ty->getPrimitiveSizeInBits().getKnownMinValue()); 351 352 // Check the DataLayout interfaces. 353 EXPECT_EQ(DL.getTypeSizeInBits(ScV2Int64Ty), 354 DL.getTypeSizeInBits(ScV4Int32Ty)); 355 EXPECT_EQ(DL.getTypeSizeInBits(ScV2Int32Ty).getKnownMinValue(), 64U); 356 EXPECT_EQ(DL.getTypeStoreSize(ScV2Int64Ty), DL.getTypeStoreSize(ScV4Int32Ty)); 357 EXPECT_NE(DL.getTypeStoreSizeInBits(ScV2Int32Ty), 358 DL.getTypeStoreSizeInBits(ScV2Int64Ty)); 359 EXPECT_EQ(DL.getTypeStoreSizeInBits(ScV2Int32Ty).getKnownMinValue(), 64U); 360 EXPECT_EQ(DL.getTypeStoreSize(ScV2Int64Ty).getKnownMinValue(), 16U); 361 EXPECT_EQ(DL.getTypeAllocSize(ScV4Int32Ty), DL.getTypeAllocSize(ScV2Int64Ty)); 362 EXPECT_NE(DL.getTypeAllocSizeInBits(ScV2Int32Ty), 363 DL.getTypeAllocSizeInBits(ScV2Int64Ty)); 364 EXPECT_EQ(DL.getTypeAllocSizeInBits(ScV4Int32Ty).getKnownMinValue(), 128U); 365 EXPECT_EQ(DL.getTypeAllocSize(ScV2Int32Ty).getKnownMinValue(), 8U); 366 ASSERT_TRUE(DL.typeSizeEqualsStoreSize(ScV4Int32Ty)); 367 } 368 369 TEST(VectorTypesTest, CrossComparisons) { 370 LLVMContext Ctx; 371 372 Type *Int32Ty = Type::getInt32Ty(Ctx); 373 374 auto *V4Int32Ty = FixedVectorType::get(Int32Ty, 4); 375 auto *ScV4Int32Ty = ScalableVectorType::get(Int32Ty, 4); 376 377 // Even though the minimum size is the same, a scalable vector could be 378 // larger so we don't consider them to be the same size. 379 EXPECT_NE(V4Int32Ty->getPrimitiveSizeInBits(), 380 ScV4Int32Ty->getPrimitiveSizeInBits()); 381 // If we are only checking the minimum, then they are the same size. 382 EXPECT_EQ(V4Int32Ty->getPrimitiveSizeInBits().getKnownMinValue(), 383 ScV4Int32Ty->getPrimitiveSizeInBits().getKnownMinValue()); 384 385 // We can't use ordering comparisons (<,<=,>,>=) between scalable and 386 // non-scalable vector sizes. 387 } 388 389 } // end anonymous namespace 390