1 //===- OperationSupportTest.cpp - Operation support 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 "mlir/IR/OperationSupport.h" 10 #include "mlir/IR/Builders.h" 11 #include "mlir/IR/BuiltinTypes.h" 12 #include "gtest/gtest.h" 13 14 using namespace mlir; 15 using namespace mlir::detail; 16 17 static Operation *createOp(MLIRContext *context, 18 ArrayRef<Value> operands = llvm::None, 19 ArrayRef<Type> resultTypes = llvm::None, 20 unsigned int numRegions = 0) { 21 context->allowUnregisteredDialects(); 22 return Operation::create(UnknownLoc::get(context), 23 OperationName("foo.bar", context), resultTypes, 24 operands, llvm::None, llvm::None, numRegions); 25 } 26 27 namespace { 28 TEST(OperandStorageTest, NonResizable) { 29 MLIRContext context; 30 Builder builder(&context); 31 32 Operation *useOp = 33 createOp(&context, /*operands=*/llvm::None, builder.getIntegerType(16)); 34 Value operand = useOp->getResult(0); 35 36 // Create a non-resizable operation with one operand. 37 Operation *user = createOp(&context, operand); 38 39 // The same number of operands is okay. 40 user->setOperands(operand); 41 EXPECT_EQ(user->getNumOperands(), 1u); 42 43 // Removing is okay. 44 user->setOperands(llvm::None); 45 EXPECT_EQ(user->getNumOperands(), 0u); 46 47 // Destroy the operations. 48 user->destroy(); 49 useOp->destroy(); 50 } 51 52 TEST(OperandStorageTest, Resizable) { 53 MLIRContext context; 54 Builder builder(&context); 55 56 Operation *useOp = 57 createOp(&context, /*operands=*/llvm::None, builder.getIntegerType(16)); 58 Value operand = useOp->getResult(0); 59 60 // Create a resizable operation with one operand. 61 Operation *user = createOp(&context, operand); 62 63 // The same number of operands is okay. 64 user->setOperands(operand); 65 EXPECT_EQ(user->getNumOperands(), 1u); 66 67 // Removing is okay. 68 user->setOperands(llvm::None); 69 EXPECT_EQ(user->getNumOperands(), 0u); 70 71 // Adding more operands is okay. 72 user->setOperands({operand, operand, operand}); 73 EXPECT_EQ(user->getNumOperands(), 3u); 74 75 // Destroy the operations. 76 user->destroy(); 77 useOp->destroy(); 78 } 79 80 TEST(OperandStorageTest, RangeReplace) { 81 MLIRContext context; 82 Builder builder(&context); 83 84 Operation *useOp = 85 createOp(&context, /*operands=*/llvm::None, builder.getIntegerType(16)); 86 Value operand = useOp->getResult(0); 87 88 // Create a resizable operation with one operand. 89 Operation *user = createOp(&context, operand); 90 91 // Check setting with the same number of operands. 92 user->setOperands(/*start=*/0, /*length=*/1, operand); 93 EXPECT_EQ(user->getNumOperands(), 1u); 94 95 // Check setting with more operands. 96 user->setOperands(/*start=*/0, /*length=*/1, {operand, operand, operand}); 97 EXPECT_EQ(user->getNumOperands(), 3u); 98 99 // Check setting with less operands. 100 user->setOperands(/*start=*/1, /*length=*/2, {operand}); 101 EXPECT_EQ(user->getNumOperands(), 2u); 102 103 // Check inserting without replacing operands. 104 user->setOperands(/*start=*/2, /*length=*/0, {operand}); 105 EXPECT_EQ(user->getNumOperands(), 3u); 106 107 // Check erasing operands. 108 user->setOperands(/*start=*/0, /*length=*/3, {}); 109 EXPECT_EQ(user->getNumOperands(), 0u); 110 111 // Destroy the operations. 112 user->destroy(); 113 useOp->destroy(); 114 } 115 116 TEST(OperandStorageTest, MutableRange) { 117 MLIRContext context; 118 Builder builder(&context); 119 120 Operation *useOp = 121 createOp(&context, /*operands=*/llvm::None, builder.getIntegerType(16)); 122 Value operand = useOp->getResult(0); 123 124 // Create a resizable operation with one operand. 125 Operation *user = createOp(&context, operand); 126 127 // Check setting with the same number of operands. 128 MutableOperandRange mutableOperands(user); 129 mutableOperands.assign(operand); 130 EXPECT_EQ(mutableOperands.size(), 1u); 131 EXPECT_EQ(user->getNumOperands(), 1u); 132 133 // Check setting with more operands. 134 mutableOperands.assign({operand, operand, operand}); 135 EXPECT_EQ(mutableOperands.size(), 3u); 136 EXPECT_EQ(user->getNumOperands(), 3u); 137 138 // Check with inserting a new operand. 139 mutableOperands.append({operand, operand}); 140 EXPECT_EQ(mutableOperands.size(), 5u); 141 EXPECT_EQ(user->getNumOperands(), 5u); 142 143 // Check erasing operands. 144 mutableOperands.clear(); 145 EXPECT_EQ(mutableOperands.size(), 0u); 146 EXPECT_EQ(user->getNumOperands(), 0u); 147 148 // Destroy the operations. 149 user->destroy(); 150 useOp->destroy(); 151 } 152 153 TEST(OperationOrderTest, OrderIsAlwaysValid) { 154 MLIRContext context; 155 Builder builder(&context); 156 157 Operation *containerOp = 158 createOp(&context, /*operands=*/llvm::None, /*resultTypes=*/llvm::None, 159 /*numRegions=*/1); 160 Region ®ion = containerOp->getRegion(0); 161 Block *block = new Block(); 162 region.push_back(block); 163 164 // Insert two operations, then iteratively add more operations in the middle 165 // of them. Eventually we will insert more than kOrderStride operations and 166 // the block order will need to be recomputed. 167 Operation *frontOp = createOp(&context); 168 Operation *backOp = createOp(&context); 169 block->push_back(frontOp); 170 block->push_back(backOp); 171 172 // Chosen to be larger than Operation::kOrderStride. 173 int kNumOpsToInsert = 10; 174 for (int i = 0; i < kNumOpsToInsert; ++i) { 175 Operation *op = createOp(&context); 176 block->getOperations().insert(backOp->getIterator(), op); 177 ASSERT_TRUE(op->isBeforeInBlock(backOp)); 178 // Note verifyOpOrder() returns false if the order is valid. 179 ASSERT_FALSE(block->verifyOpOrder()); 180 } 181 182 containerOp->destroy(); 183 } 184 185 } // end namespace 186