Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// 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 contains external dialect interfaces for CIR.
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H
#define CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H

#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are we using from this include?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess nothing here. I probably thought I was going to need it and added it proactively.


namespace cir::acc {

template <typename T>
struct OpenACCPointerLikeModel
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silly question perhaps, why is this not part of MLIR? It doesn't seem to refer to CIR at all? Or am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

: public mlir::acc::PointerLikeType::ExternalModel<
OpenACCPointerLikeModel<T>, T> {
mlir::Type getElementType(mlir::Type pointer) const {
return mlir::cast<T>(pointer).getPointee();
}
mlir::acc::VariableTypeCategory
getPointeeTypeCategory(mlir::Type pointer,
mlir::TypedValue<mlir::acc::PointerLikeType> varPtr,
mlir::Type varType) const;
};

} // namespace cir::acc

#endif // CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H
#define CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H

namespace mlir {
class DialectRegistry;
} // namespace mlir

namespace cir::acc {

void registerOpenACCExtensions(mlir::DialectRegistry &registry);

} // namespace cir::acc

#endif // CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H
7 changes: 7 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "clang/AST/DeclGroup.h"
#include "clang/CIR/CIRGenerator.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"

using namespace cir;
using namespace clang;
Expand All @@ -38,6 +39,12 @@ void CIRGenerator::Initialize(ASTContext &astContext) {
mlirContext = std::make_unique<mlir::MLIRContext>();
mlirContext->loadDialect<cir::CIRDialect>();
mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>();

// Register extensions to integrate CIR types with OpenACC.
mlir::DialectRegistry registry;
cir::acc::registerOpenACCExtensions(registry);
mlirContext->appendDialectRegistry(registry);

cgm = std::make_unique<clang::CIRGen::CIRGenModule>(
*mlirContext.get(), astContext, codeGenOpts, diags);
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ add_clang_library(clangCIR
clangBasic
clangLex
${dialect_libs}
CIROpenACCSupport
MLIRCIR
MLIRCIRInterfaces
)
1 change: 1 addition & 0 deletions clang/lib/CIR/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
add_subdirectory(IR)
add_subdirectory(OpenACC)
add_subdirectory(Transforms)
41 changes: 41 additions & 0 deletions clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Implementation of external dialect interfaces for CIR.
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"

namespace cir::acc {

template <>
mlir::acc::VariableTypeCategory
OpenACCPointerLikeModel<cir::PointerType>::getPointeeTypeCategory(
mlir::Type pointer, mlir::TypedValue<mlir::acc::PointerLikeType> varPtr,
mlir::Type varType) const {
mlir::Type eleTy = mlir::cast<cir::PointerType>(pointer).getPointee();

if (auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(eleTy))
return mappableTy.getTypeCategory(varPtr);

if (isAnyIntegerOrFloatingPointType(eleTy) ||
mlir::isa<cir::BoolType>(eleTy) || mlir::isa<cir::PointerType>(eleTy))
return mlir::acc::VariableTypeCategory::scalar;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems the CIR type system allows computation of interior pointers: https://godbolt.org/z/aPn1j5a69
Which means that scalar categorization might capture things which it shouldn't. More specifically, "a member of a composite variable" is not considered a "scalar" in OpenACC terminology - and the CIR type system by itself does not provide the appropriate features to distinguish this.

Here is how we dealt with this case in FIR which allows the same: https://github.com/llvm/llvm-project/blob/main/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp#L386

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so it's not just a property of the type, but an interpretation of the type within the context of the value it is associated with. That makes sense now for the extra parameters that I'm ignoring here.

if (mlir::isa<cir::ArrayType>(eleTy))
return mlir::acc::VariableTypeCategory::array;
if (mlir::isa<cir::RecordType>(eleTy))
return mlir::acc::VariableTypeCategory::composite;
if (mlir::isa<cir::FuncType>(eleTy) || mlir::isa<cir::VectorType>(eleTy))
return mlir::acc::VariableTypeCategory::nonscalar;

// Without further checking, this type cannot be categorized.
return mlir::acc::VariableTypeCategory::uncategorized;
}

} // namespace cir::acc
10 changes: 10 additions & 0 deletions clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_clang_library(CIROpenACCSupport
CIROpenACCTypeInterfaces.cpp
RegisterOpenACCExtensions.cpp

DEPENDS
MLIRCIRTypeConstraintsIncGen

LINK_LIBS PUBLIC
MLIRIR
)
27 changes: 27 additions & 0 deletions clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Registration for OpenACC extensions as applied to CIR dialect.
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"

namespace cir::acc {

void registerOpenACCExtensions(mlir::DialectRegistry &registry) {
registry.addExtension(+[](mlir::MLIRContext *ctx, cir::CIRDialect *dialect) {
cir::PointerType::attachInterface<
OpenACCPointerLikeModel<cir::PointerType>>(*ctx);
});
}

} // namespace cir::acc
11 changes: 11 additions & 0 deletions clang/unittests/CIR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_clang_unittest(CIRUnitTests
PointerLikeTest.cpp
LLVM_COMPONENTS
Core

LINK_LIBS
MLIRCIR
CIROpenACCSupport
MLIRIR
MLIROpenACCDialect
)
160 changes: 160 additions & 0 deletions clang/unittests/CIR/PointerLikeTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Unit tests for CIR implementation of OpenACC's PointertLikeType interface
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Value.h"
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h"
#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"
#include "gtest/gtest.h"

using namespace mlir;
using namespace cir;

//===----------------------------------------------------------------------===//
// Test Fixture
//===----------------------------------------------------------------------===//

class CIROpenACCPointerLikeTest : public ::testing::Test {
protected:
CIROpenACCPointerLikeTest() : b(&context), loc(UnknownLoc::get(&context)) {
context.loadDialect<cir::CIRDialect>();
context.loadDialect<mlir::acc::OpenACCDialect>();

// Register extension to integrate CIR types with OpenACC.
mlir::DialectRegistry registry;
cir::acc::registerOpenACCExtensions(registry);
context.appendDialectRegistry(registry);
}

MLIRContext context;
OpBuilder b;
Location loc;

mlir::IntegerAttr getSizeFromCharUnits(mlir::MLIRContext *ctx,
clang::CharUnits size) {
// Note that mlir::IntegerType is used instead of cir::IntType here
// because we don't need sign information for this to be useful, so keep
// it simple.
return mlir::IntegerAttr::get(mlir::IntegerType::get(ctx, 64),
size.getQuantity());
}

// General handler for types without a specific test
void testElementType(mlir::Type ty) {
mlir::Type ptrTy = cir::PointerType::get(ty);

// cir::PointerType should be castable to acc::PointerLikeType
auto pltTy = dyn_cast_if_present<mlir::acc::PointerLikeType>(ptrTy);
ASSERT_NE(pltTy, nullptr);

EXPECT_EQ(pltTy.getElementType(), ty);

OwningOpRef<cir::AllocaOp> varPtrOp = b.create<cir::AllocaOp>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need a OwningOpRef here? Thought those were only for top level operations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose here is to make have it automatically delete the op on return from the function.

loc, ptrTy, ty, "",
getSizeFromCharUnits(&context, clang::CharUnits::One()));

mlir::Value val = varPtrOp.get();
mlir::acc::VariableTypeCategory typeCategory = pltTy.getPointeeTypeCategory(
cast<TypedValue<mlir::acc::PointerLikeType>>(val),
mlir::acc::getVarType(varPtrOp.get()));

if (isAnyIntegerOrFloatingPointType(ty) ||
mlir::isa<cir::PointerType>(ty) || mlir::isa<cir::BoolType>(ty)) {
EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::scalar);
} else if (mlir::isa<cir::ArrayType>(ty)) {
EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::array);
} else if (mlir::isa<cir::RecordType>(ty)) {
EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::composite);
} else if (mlir::isa<cir::FuncType, cir::VectorType>(ty)) {
EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::nonscalar);
} else if (mlir::isa<cir::VoidType>(ty)) {
EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::uncategorized);
} else {
EXPECT_EQ(typeCategory, mlir::acc::VariableTypeCategory::uncategorized);
// If we hit this, we need to add support for a new type.
ASSERT_TRUE(false);
}
}
};

TEST_F(CIROpenACCPointerLikeTest, testPointerToInt) {
// Test various scalar types.
testElementType(cir::IntType::get(&context, 8, true));
testElementType(cir::IntType::get(&context, 8, false));
testElementType(cir::IntType::get(&context, 16, true));
testElementType(cir::IntType::get(&context, 16, false));
testElementType(cir::IntType::get(&context, 32, true));
testElementType(cir::IntType::get(&context, 32, false));
testElementType(cir::IntType::get(&context, 64, true));
testElementType(cir::IntType::get(&context, 64, false));
testElementType(cir::IntType::get(&context, 128, true));
testElementType(cir::IntType::get(&context, 128, false));
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToBool) {
testElementType(cir::BoolType::get(&context));
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToFloat) {
testElementType(cir::SingleType::get(&context));
testElementType(cir::DoubleType::get(&context));
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToPointer) {
mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
mlir::Type ptrTy = cir::PointerType::get(i32Ty);
testElementType(ptrTy);
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToArray) {
// Test an array type.
mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
testElementType(cir::ArrayType::get(i32Ty, 10));
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToStruct) {
// Test a struct type.
mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
llvm::ArrayRef<mlir::Type> fields = {i32Ty, i32Ty};
cir::RecordType structTy = cir::RecordType::get(
&context, b.getStringAttr("S"), cir::RecordType::RecordKind::Struct);
structTy.complete(fields, false, false);
testElementType(structTy);

// Test a union type.
cir::RecordType unionTy = cir::RecordType::get(
&context, b.getStringAttr("U"), cir::RecordType::RecordKind::Union);
unionTy.complete(fields, false, false);
testElementType(unionTy);
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToFunction) {
mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
cir::FuncType::get(SmallVector<mlir::Type, 2>{i32Ty, i32Ty}, i32Ty);
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToVector) {
mlir::Type i32Ty = cir::IntType::get(&context, 32, true);
mlir::Type vecTy = cir::VectorType::get(i32Ty, 4);
testElementType(vecTy);
}

TEST_F(CIROpenACCPointerLikeTest, testPointerToVoid) {
mlir::Type voidTy = cir::VoidType::get(&context);
testElementType(voidTy);
}
11 changes: 10 additions & 1 deletion clang/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ add_subdirectory(Index)
add_subdirectory(InstallAPI)
add_subdirectory(Serialization)
add_subdirectory(Support)

if (CLANG_ENABLE_CIR)
add_subdirectory(CIR)
endif()

# If we're doing a single merged clang unit test binary, add that target after
# all the previous subdirectories have been processed.
Expand All @@ -127,3 +129,10 @@ add_distinct_clang_unittest(AllClangUnitTests
# the merged clang unit test binary, we can update the include paths and make
# this the default.
include_directories(Tooling)

if (CLANG_ENABLE_CIR)
set(MLIR_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include )
set(MLIR_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/mlir/include)
include_directories(SYSTEM ${MLIR_INCLUDE_DIR})
include_directories(${MLIR_TABLEGEN_OUTPUT_DIR})
endif()
Loading