brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.1 KiB · b3dfba7 Raw
363 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Unit tests for CIR implementation of OpenACC's PointertLikeType interface10//11//===----------------------------------------------------------------------===//12 13#include "mlir/Dialect/OpenACC/OpenACC.h"14#include "mlir/IR/BuiltinTypes.h"15#include "mlir/IR/Diagnostics.h"16#include "mlir/IR/MLIRContext.h"17#include "mlir/IR/Value.h"18#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"19#include "clang/CIR/Dialect/IR/CIRDialect.h"20#include "clang/CIR/Dialect/IR/CIRTypes.h"21#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"22#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"23#include "gtest/gtest.h"24 25using namespace mlir;26using namespace cir;27 28//===----------------------------------------------------------------------===//29// Test Fixture30//===----------------------------------------------------------------------===//31 32class CIROpenACCPointerLikeTest : public ::testing::Test {33protected:34  CIROpenACCPointerLikeTest() : b(&context), loc(UnknownLoc::get(&context)) {35    context.loadDialect<cir::CIRDialect>();36    context.loadDialect<mlir::acc::OpenACCDialect>();37 38    // Register extension to integrate CIR types with OpenACC.39    mlir::DialectRegistry registry;40    cir::acc::registerOpenACCExtensions(registry);41    context.appendDialectRegistry(registry);42  }43 44  MLIRContext context;45  OpBuilder b;46  Location loc;47  llvm::StringMap<unsigned> recordNames;48 49  mlir::IntegerAttr getAlignOne(mlir::MLIRContext *ctx) {50    // Note that mlir::IntegerType is used instead of cir::IntType here because51    // we don't need sign information for this to be useful, so keep it simple.52    clang::CharUnits align = clang::CharUnits::One();53    return b.getI64IntegerAttr(align.getQuantity());54  }55 56  mlir::StringAttr getUniqueRecordName(const std::string &baseName) {57    auto it = recordNames.find(baseName);58    if (it == recordNames.end()) {59      recordNames[baseName] = 0;60      return b.getStringAttr(baseName);61    }62 63    return b.getStringAttr(baseName + "." +64                           std::to_string(recordNames[baseName]++));65  }66 67  // General handler for types without a specific test68  void testSingleType(mlir::Type ty,69                      mlir::acc::VariableTypeCategory expectedTypeCategory) {70    mlir::Type ptrTy = cir::PointerType::get(ty);71 72    // cir::PointerType should be castable to acc::PointerLikeType73    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);74    ASSERT_NE(pltTy, nullptr);75 76    EXPECT_EQ(pltTy.getElementType(), ty);77 78    OwningOpRef<cir::AllocaOp> varPtrOp =79        cir::AllocaOp::create(b, loc, ptrTy, ty, "", getAlignOne(&context));80 81    mlir::Value val = varPtrOp.get();82    mlir::acc::VariableTypeCategory typeCategory = pltTy.getPointeeTypeCategory(83        cast<TypedValue<mlir::acc::PointerLikeType>>(val),84        mlir::acc::getVarType(varPtrOp.get()));85 86    EXPECT_EQ(typeCategory, expectedTypeCategory);87  }88 89  void testScalarType(mlir::Type ty) {90    testSingleType(ty, mlir::acc::VariableTypeCategory::scalar);91  }92 93  void testNonScalarType(mlir::Type ty) {94    testSingleType(ty, mlir::acc::VariableTypeCategory::nonscalar);95  }96 97  void testUncategorizedType(mlir::Type ty) {98    testSingleType(ty, mlir::acc::VariableTypeCategory::uncategorized);99  }100 101  void testArrayType(mlir::Type ty) {102    // Build the array pointer type.103    mlir::Type arrTy = cir::ArrayType::get(ty, 10);104    mlir::Type ptrTy = cir::PointerType::get(arrTy);105 106    // Verify that the pointer points to the array type..107    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);108    ASSERT_NE(pltTy, nullptr);109    EXPECT_EQ(pltTy.getElementType(), arrTy);110 111    // Create an alloca for the array112    OwningOpRef<cir::AllocaOp> varPtrOp =113        cir::AllocaOp::create(b, loc, ptrTy, arrTy, "", getAlignOne(&context));114 115    // Verify that the type category is array.116    mlir::Value val = varPtrOp.get();117    mlir::acc::VariableTypeCategory typeCategory = pltTy.getPointeeTypeCategory(118        cast<TypedValue<mlir::acc::PointerLikeType>>(val),119        mlir::acc::getVarType(varPtrOp.get()));120    EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::array);121 122    // Create an array-to-pointer decay cast.123    mlir::Type ptrToElemTy = cir::PointerType::get(ty);124    OwningOpRef<cir::CastOp> decayPtr = cir::CastOp::create(125        b, loc, ptrToElemTy, cir::CastKind::array_to_ptrdecay, val);126    mlir::Value decayVal = decayPtr.get();127 128    // Verify that we still get the expected element type.129    auto decayPltTy =130        dyn_cast_if_present<mlir::acc::PointerLikeType>(decayVal.getType());131    ASSERT_NE(decayPltTy, nullptr);132    EXPECT_EQ(decayPltTy.getElementType(), ty);133 134    // Verify that we still identify the type category as an array.135    mlir::acc::VariableTypeCategory decayTypeCategory =136        decayPltTy.getPointeeTypeCategory(137            cast<TypedValue<mlir::acc::PointerLikeType>>(decayVal),138            mlir::acc::getVarType(decayPtr.get()));139    EXPECT_EQ(decayTypeCategory, mlir::acc::VariableTypeCategory::array);140 141    // Create an element access.142    mlir::Type i32Ty = cir::IntType::get(&context, 32, true);143    mlir::Value index =144        cir::ConstantOp::create(b, loc, cir::IntAttr::get(i32Ty, 2));145    OwningOpRef<cir::PtrStrideOp> accessPtr =146        cir::PtrStrideOp::create(b, loc, ptrToElemTy, decayVal, index);147    mlir::Value accessVal = accessPtr.get();148 149    // Verify that we still get the expected element type.150    auto accessPltTy =151        dyn_cast_if_present<mlir::acc::PointerLikeType>(accessVal.getType());152    ASSERT_NE(accessPltTy, nullptr);153    EXPECT_EQ(accessPltTy.getElementType(), ty);154 155    // Verify that we still identify the type category as an array.156    mlir::acc::VariableTypeCategory accessTypeCategory =157        accessPltTy.getPointeeTypeCategory(158            cast<TypedValue<mlir::acc::PointerLikeType>>(accessVal),159            mlir::acc::getVarType(accessPtr.get()));160    EXPECT_EQ(accessTypeCategory, mlir::acc::VariableTypeCategory::array);161  }162 163  // Structures and unions are accessed in the same way, so use a common test.164  void testRecordType(mlir::Type ty1, mlir::Type ty2,165                      cir::RecordType::RecordKind kind) {166    // Build the structure pointer type.167    cir::RecordType structTy =168        cir::RecordType::get(&context, getUniqueRecordName("S"), kind);169    structTy.complete({ty1, ty2}, false, false);170    mlir::Type ptrTy = cir::PointerType::get(structTy);171 172    // Verify that the pointer points to the structure type.173    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);174    ASSERT_NE(pltTy, nullptr);175    EXPECT_EQ(pltTy.getElementType(), structTy);176 177    // Create an alloca for the array178    OwningOpRef<cir::AllocaOp> varPtrOp = cir::AllocaOp::create(179        b, loc, ptrTy, structTy, "", getAlignOne(&context));180 181    // Verify that the type category is composite.182    mlir::Value val = varPtrOp.get();183    mlir::acc::VariableTypeCategory typeCategory = pltTy.getPointeeTypeCategory(184        cast<TypedValue<mlir::acc::PointerLikeType>>(val),185        mlir::acc::getVarType(varPtrOp.get()));186    EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::composite);187 188    // Access the first element of the structure.189    OwningOpRef<cir::GetMemberOp> access1 = cir::GetMemberOp::create(190        b, loc, cir::PointerType::get(ty1), val, "f1", 0u);191    mlir::Value accessVal1 = access1.get();192 193    // Verify that we get the expected element type.194    auto access1PltTy =195        dyn_cast_if_present<mlir::acc::PointerLikeType>(accessVal1.getType());196    ASSERT_NE(access1PltTy, nullptr);197    EXPECT_EQ(access1PltTy.getElementType(), ty1);198 199    // Verify that the type category is still composite.200    mlir::acc::VariableTypeCategory access1TypeCategory =201        access1PltTy.getPointeeTypeCategory(202            cast<TypedValue<mlir::acc::PointerLikeType>>(accessVal1),203            mlir::acc::getVarType(access1.get()));204    EXPECT_EQ(access1TypeCategory, mlir::acc::VariableTypeCategory::composite);205 206    // Access the second element of the structure.207    OwningOpRef<cir::GetMemberOp> access2 = cir::GetMemberOp::create(208        b, loc, cir::PointerType::get(ty2), val, "f2", 1u);209    mlir::Value accessVal2 = access2.get();210 211    // Verify that we get the expected element type.212    auto access2PltTy =213        dyn_cast_if_present<mlir::acc::PointerLikeType>(accessVal2.getType());214    ASSERT_NE(access2PltTy, nullptr);215    EXPECT_EQ(access2PltTy.getElementType(), ty2);216 217    // Verify that the type category is still composite.218    mlir::acc::VariableTypeCategory access2TypeCategory =219        access2PltTy.getPointeeTypeCategory(220            cast<TypedValue<mlir::acc::PointerLikeType>>(accessVal2),221            mlir::acc::getVarType(access2.get()));222    EXPECT_EQ(access2TypeCategory, mlir::acc::VariableTypeCategory::composite);223  }224 225  void testStructType(mlir::Type ty1, mlir::Type ty2) {226    testRecordType(ty1, ty2, cir::RecordType::RecordKind::Struct);227  }228 229  void testUnionType(mlir::Type ty1, mlir::Type ty2) {230    testRecordType(ty1, ty2, cir::RecordType::RecordKind::Union);231  }232 233  // This is testing a case like this:234  //235  // struct S {236  //   int *f1;237  //   int *f2;238  // } *p;239  // int *pMember = p->f2;240  //241  // That is, we are not testing a pointer to a member, we're testing a pointer242  // that is loaded as a member value.243  void testPointerToMemberType(244      mlir::Type ty, mlir::acc::VariableTypeCategory expectedTypeCategory) {245    // Construct a struct type with two members that are pointers to the input246    // type.247    mlir::Type ptrTy = cir::PointerType::get(ty);248    cir::RecordType structTy =249        cir::RecordType::get(&context, getUniqueRecordName("S"),250                             cir::RecordType::RecordKind::Struct);251    structTy.complete({ptrTy, ptrTy}, false, false);252    mlir::Type structPptrTy = cir::PointerType::get(structTy);253 254    // Create an alloca for the struct.255    OwningOpRef<cir::AllocaOp> varPtrOp = cir::AllocaOp::create(256        b, loc, structPptrTy, structTy, "S", getAlignOne(&context));257    mlir::Value val = varPtrOp.get();258 259    // Get a pointer to the second member.260    OwningOpRef<cir::GetMemberOp> access = cir::GetMemberOp::create(261        b, loc, cir::PointerType::get(ptrTy), val, b.getStringAttr("f2"), 1);262    mlir::Value accessVal = access.get();263 264    // Load the value of the second member. This is the pointer we want to test.265    OwningOpRef<cir::LoadOp> loadOp = cir::LoadOp::create(b, loc, accessVal);266    mlir::Value loadVal = loadOp.get();267 268    // Verify that the type category is the expected type category.269    auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);270    mlir::acc::VariableTypeCategory typeCategory = pltTy.getPointeeTypeCategory(271        cast<TypedValue<mlir::acc::PointerLikeType>>(loadVal),272        mlir::acc::getVarType(loadOp.get()));273 274    EXPECT_EQ(typeCategory, expectedTypeCategory);275  }276};277 278TEST_F(CIROpenACCPointerLikeTest, testPointerToInt) {279  // Test various scalar types.280  testScalarType(cir::IntType::get(&context, 8, true));281  testScalarType(cir::IntType::get(&context, 8, false));282  testScalarType(cir::IntType::get(&context, 16, true));283  testScalarType(cir::IntType::get(&context, 16, false));284  testScalarType(cir::IntType::get(&context, 32, true));285  testScalarType(cir::IntType::get(&context, 32, false));286  testScalarType(cir::IntType::get(&context, 64, true));287  testScalarType(cir::IntType::get(&context, 64, false));288  testScalarType(cir::IntType::get(&context, 128, true));289  testScalarType(cir::IntType::get(&context, 128, false));290}291 292TEST_F(CIROpenACCPointerLikeTest, testPointerToBool) {293  testScalarType(cir::BoolType::get(&context));294}295 296TEST_F(CIROpenACCPointerLikeTest, testPointerToFloat) {297  testScalarType(cir::SingleType::get(&context));298  testScalarType(cir::DoubleType::get(&context));299}300 301TEST_F(CIROpenACCPointerLikeTest, testPointerToPointer) {302  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);303  mlir::Type ptrTy = cir::PointerType::get(i32Ty);304  testScalarType(ptrTy);305}306 307TEST_F(CIROpenACCPointerLikeTest, testPointerToArray) {308  // Test an array type.309  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);310  testArrayType(i32Ty);311}312 313TEST_F(CIROpenACCPointerLikeTest, testPointerToStruct) {314  // Test a struct type.315  mlir::Type i16Ty = cir::IntType::get(&context, 16, true);316  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);317  testStructType(i16Ty, i32Ty);318}319 320TEST_F(CIROpenACCPointerLikeTest, testPointerToUnion) {321  // Test a union type.322  mlir::Type i16Ty = cir::IntType::get(&context, 16, true);323  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);324  testUnionType(i16Ty, i32Ty);325}326 327TEST_F(CIROpenACCPointerLikeTest, testPointerToFunction) {328  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);329  mlir::Type funcTy =330      cir::FuncType::get(SmallVector<mlir::Type, 2>{i32Ty, i32Ty}, i32Ty);331  testNonScalarType(funcTy);332}333 334TEST_F(CIROpenACCPointerLikeTest, testPointerToVector) {335  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);336  mlir::Type vecTy = cir::VectorType::get(i32Ty, 4);337  testNonScalarType(vecTy);338}339 340TEST_F(CIROpenACCPointerLikeTest, testPointerToVoid) {341  mlir::Type voidTy = cir::VoidType::get(&context);342  testUncategorizedType(voidTy);343}344 345TEST_F(CIROpenACCPointerLikeTest, testPointerToIntMember) {346  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);347  testPointerToMemberType(i32Ty, mlir::acc::VariableTypeCategory::scalar);348}349 350TEST_F(CIROpenACCPointerLikeTest, testPointerToArrayMember) {351  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);352  mlir::Type arrTy = cir::ArrayType::get(i32Ty, 10);353  testPointerToMemberType(arrTy, mlir::acc::VariableTypeCategory::array);354}355 356TEST_F(CIROpenACCPointerLikeTest, testPointerToStructMember) {357  mlir::Type i32Ty = cir::IntType::get(&context, 32, true);358  cir::RecordType structTy = cir::RecordType::get(359      &context, getUniqueRecordName("S"), cir::RecordType::RecordKind::Struct);360  structTy.complete({i32Ty, i32Ty}, false, false);361  testPointerToMemberType(structTy, mlir::acc::VariableTypeCategory::composite);362}363