-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[CIR] Add PointerLikeType interface support for cir::PointerType #139768
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This adds code to attach the OpenACC PointerLikeType interface to cir::PointerType, along with a unit test for the interface.
@llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) ChangesThis adds code to attach the OpenACC PointerLikeType interface to cir::PointerType, along with a unit test for the interface. Full diff: https://github.com/llvm/llvm-project/pull/139768.diff 11 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h b/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
new file mode 100644
index 0000000000000..eccb6838a491f
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
@@ -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"
+
+namespace cir::acc {
+
+template <typename T>
+struct OpenACCPointerLikeModel
+ : 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
diff --git a/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h b/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
new file mode 100644
index 0000000000000..13780a01ea1bb
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
@@ -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 ®istry);
+
+} // namespace cir::acc
+
+#endif // CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index aa3864deb733c..40252ffecfba1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -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;
@@ -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);
}
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 7a701c3c0b82b..8f5796e59d3bb 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -35,6 +35,7 @@ add_clang_library(clangCIR
clangBasic
clangLex
${dialect_libs}
+ CIROpenACCSupport
MLIRCIR
MLIRCIRInterfaces
)
diff --git a/clang/lib/CIR/Dialect/CMakeLists.txt b/clang/lib/CIR/Dialect/CMakeLists.txt
index 9f57627c321fb..c825a61b2779b 100644
--- a/clang/lib/CIR/Dialect/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(IR)
+add_subdirectory(OpenACC)
add_subdirectory(Transforms)
diff --git a/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp b/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
new file mode 100644
index 0000000000000..ea563ecdfb3bb
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
@@ -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;
+ 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
diff --git a/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt b/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
new file mode 100644
index 0000000000000..5b0a1620a1bff
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_clang_library(CIROpenACCSupport
+ CIROpenACCTypeInterfaces.cpp
+ RegisterOpenACCExtensions.cpp
+
+ DEPENDS
+ MLIRCIRTypeConstraintsIncGen
+
+ LINK_LIBS PUBLIC
+ MLIRIR
+ )
diff --git a/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp b/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
new file mode 100644
index 0000000000000..3dfe7aeb6b1d6
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
@@ -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 ®istry) {
+ registry.addExtension(+[](mlir::MLIRContext *ctx, cir::CIRDialect *dialect) {
+ cir::PointerType::attachInterface<
+ OpenACCPointerLikeModel<cir::PointerType>>(*ctx);
+ });
+}
+
+} // namespace cir::acc
diff --git a/clang/unittests/CIR/CMakeLists.txt b/clang/unittests/CIR/CMakeLists.txt
new file mode 100644
index 0000000000000..171201b7beb23
--- /dev/null
+++ b/clang/unittests/CIR/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_clang_unittest(CIRUnitTests
+ PointerLikeTest.cpp
+ LLVM_COMPONENTS
+ Core
+
+ LINK_LIBS
+ MLIRCIR
+ CIROpenACCSupport
+ MLIRIR
+ MLIROpenACCDialect
+ )
diff --git a/clang/unittests/CIR/PointerLikeTest.cpp b/clang/unittests/CIR/PointerLikeTest.cpp
new file mode 100644
index 0000000000000..af8f32d237e71
--- /dev/null
+++ b/clang/unittests/CIR/PointerLikeTest.cpp
@@ -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>(
+ 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);
+}
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index b4114d419b75c..2a84607aa0937 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -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.
@@ -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()
|
@llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) ChangesThis adds code to attach the OpenACC PointerLikeType interface to cir::PointerType, along with a unit test for the interface. Full diff: https://github.com/llvm/llvm-project/pull/139768.diff 11 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h b/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
new file mode 100644
index 0000000000000..eccb6838a491f
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.h
@@ -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"
+
+namespace cir::acc {
+
+template <typename T>
+struct OpenACCPointerLikeModel
+ : 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
diff --git a/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h b/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
new file mode 100644
index 0000000000000..13780a01ea1bb
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h
@@ -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 ®istry);
+
+} // namespace cir::acc
+
+#endif // CLANG_CIR_DIALECT_OPENACC_REGISTEROPENACCEXTENSIONS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index aa3864deb733c..40252ffecfba1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -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;
@@ -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);
}
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 7a701c3c0b82b..8f5796e59d3bb 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -35,6 +35,7 @@ add_clang_library(clangCIR
clangBasic
clangLex
${dialect_libs}
+ CIROpenACCSupport
MLIRCIR
MLIRCIRInterfaces
)
diff --git a/clang/lib/CIR/Dialect/CMakeLists.txt b/clang/lib/CIR/Dialect/CMakeLists.txt
index 9f57627c321fb..c825a61b2779b 100644
--- a/clang/lib/CIR/Dialect/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(IR)
+add_subdirectory(OpenACC)
add_subdirectory(Transforms)
diff --git a/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp b/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
new file mode 100644
index 0000000000000..ea563ecdfb3bb
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/CIROpenACCTypeInterfaces.cpp
@@ -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;
+ 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
diff --git a/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt b/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
new file mode 100644
index 0000000000000..5b0a1620a1bff
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_clang_library(CIROpenACCSupport
+ CIROpenACCTypeInterfaces.cpp
+ RegisterOpenACCExtensions.cpp
+
+ DEPENDS
+ MLIRCIRTypeConstraintsIncGen
+
+ LINK_LIBS PUBLIC
+ MLIRIR
+ )
diff --git a/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp b/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
new file mode 100644
index 0000000000000..3dfe7aeb6b1d6
--- /dev/null
+++ b/clang/lib/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.cpp
@@ -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 ®istry) {
+ registry.addExtension(+[](mlir::MLIRContext *ctx, cir::CIRDialect *dialect) {
+ cir::PointerType::attachInterface<
+ OpenACCPointerLikeModel<cir::PointerType>>(*ctx);
+ });
+}
+
+} // namespace cir::acc
diff --git a/clang/unittests/CIR/CMakeLists.txt b/clang/unittests/CIR/CMakeLists.txt
new file mode 100644
index 0000000000000..171201b7beb23
--- /dev/null
+++ b/clang/unittests/CIR/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_clang_unittest(CIRUnitTests
+ PointerLikeTest.cpp
+ LLVM_COMPONENTS
+ Core
+
+ LINK_LIBS
+ MLIRCIR
+ CIROpenACCSupport
+ MLIRIR
+ MLIROpenACCDialect
+ )
diff --git a/clang/unittests/CIR/PointerLikeTest.cpp b/clang/unittests/CIR/PointerLikeTest.cpp
new file mode 100644
index 0000000000000..af8f32d237e71
--- /dev/null
+++ b/clang/unittests/CIR/PointerLikeTest.cpp
@@ -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>(
+ 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);
+}
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index b4114d419b75c..2a84607aa0937 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -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.
@@ -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()
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a good reviewer for this, hopefully @razvanlupusoru and @clementval can affirm this is right.
namespace cir::acc { | ||
|
||
template <typename T> | ||
struct OpenACCPointerLikeModel |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this clarifies it a bit?
https://mlir.llvm.org/docs/Interfaces/#external-models-for-attribute-operation-and-type-interfaces
#define CLANG_CIR_DIALECT_OPENACC_CIROPENACCTYPEINTERFACES_H | ||
|
||
#include "mlir/Dialect/OpenACC/OpenACC.h" | ||
#include "clang/CIR/Dialect/IR/CIRTypes.h" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
|
||
if (isAnyIntegerOrFloatingPointType(eleTy) || | ||
mlir::isa<cir::BoolType>(eleTy) || mlir::isa<cir::PointerType>(eleTy)) | ||
return mlir::acc::VariableTypeCategory::scalar; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
I just had one concern - otherwise looks great! Nice job! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat unit tests! LGTM
|
||
EXPECT_EQ(pltTy.getElementType(), ty); | ||
|
||
OwningOpRef<cir::AllocaOp> varPtrOp = b.create<cir::AllocaOp>( |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This adds code to attach the OpenACC PointerLikeType interface to cir::PointerType, along with a unit test for the interface.