//===- IndexOpsFoldersTest.cpp - unit tests for index op folders ----------===// // // 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 // //===----------------------------------------------------------------------===// #include "mlir/Dialect/Index/IR/IndexDialect.h" #include "mlir/Dialect/Index/IR/IndexOps.h" #include "mlir/IR/OwningOpRef.h" #include "gtest/gtest.h" using namespace mlir; namespace { /// Test fixture for testing operation folders. class IndexFolderTest : public testing::Test { public: IndexFolderTest() { ctx.getOrLoadDialect(); } /// Instantiate an operation, invoke its folder, and return the attribute /// result. template void foldOp(IntegerAttr &value, Type type, ArrayRef operands); protected: /// The MLIR context to use. MLIRContext ctx; /// A builder to use. OpBuilder b{&ctx}; }; } // namespace template void IndexFolderTest::foldOp(IntegerAttr &value, Type type, ArrayRef operands) { // This function returns null so that `ASSERT_*` works within it. OperationState state(UnknownLoc::get(&ctx), OpT::getOperationName()); state.addTypes(type); OwningOpRef op = cast(b.create(state)); SmallVector results; LogicalResult result = op->getOperation()->fold(operands, results); // Propagate the failure to the test. if (failed(result)) { value = nullptr; return; } ASSERT_EQ(results.size(), 1u); value = dyn_cast_or_null(dyn_cast(results.front())); ASSERT_TRUE(value); } TEST_F(IndexFolderTest, TestCastUOpFolder) { IntegerAttr value; auto fold = [&](Type type, Attribute input) { foldOp(value, type, input); }; // Target width less than or equal to 32 bits. fold(b.getIntegerType(16), b.getIndexAttr(8000000000)); ASSERT_TRUE(value); EXPECT_EQ(value.getInt(), 20480u); // Target width greater than or equal to 64 bits. fold(b.getIntegerType(64), b.getIndexAttr(2000)); ASSERT_TRUE(value); EXPECT_EQ(value.getInt(), 2000u); // Fails to fold, because truncating to 32 bits and then extending creates a // different value. fold(b.getIntegerType(64), b.getIndexAttr(8000000000)); EXPECT_FALSE(value); // Target width between 32 and 64 bits. fold(b.getIntegerType(40), b.getIndexAttr(0x10000000010000)); // Fold succeeds because the upper bits are truncated in the cast. ASSERT_TRUE(value); EXPECT_EQ(value.getInt(), 65536); // Fails to fold because the upper bits are not truncated. fold(b.getIntegerType(60), b.getIndexAttr(0x10000000010000)); EXPECT_FALSE(value); } TEST_F(IndexFolderTest, TestCastSOpFolder) { IntegerAttr value; auto fold = [&](Type type, Attribute input) { foldOp(value, type, input); }; // Just test the extension cases to ensure signs are being respected. // Target width greater than or equal to 64 bits. fold(b.getIntegerType(64), b.getIndexAttr(-2000)); ASSERT_TRUE(value); EXPECT_EQ(value.getInt(), -2000); // Target width between 32 and 64 bits. fold(b.getIntegerType(40), b.getIndexAttr(-0x10000000010000)); // Fold succeeds because the upper bits are truncated in the cast. ASSERT_TRUE(value); EXPECT_EQ(value.getInt(), -65536); }