1 //===- MachineOperandTest.cpp ---------------------------------===// 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 "llvm/CodeGen/MachineOperand.h" 10 #include "llvm/ADT/ilist_node.h" 11 #include "llvm/CodeGen/CodeGenTargetMachineImpl.h" 12 #include "llvm/CodeGen/MachineFunction.h" 13 #include "llvm/CodeGen/MachineModuleInfo.h" 14 #include "llvm/CodeGen/TargetFrameLowering.h" 15 #include "llvm/CodeGen/TargetInstrInfo.h" 16 #include "llvm/CodeGen/TargetLowering.h" 17 #include "llvm/CodeGenTypes/LowLevelType.h" 18 #include "llvm/IR/Constants.h" 19 #include "llvm/IR/InstrTypes.h" 20 #include "llvm/IR/LLVMContext.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/IR/ModuleSlotTracker.h" 23 #include "llvm/MC/MCAsmInfo.h" 24 #include "llvm/MC/MCContext.h" 25 #include "llvm/MC/TargetRegistry.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include "gtest/gtest.h" 28 29 using namespace llvm; 30 31 namespace { 32 33 // Include helper functions to ease the manipulation of MachineFunctions. 34 #include "MFCommon.inc" 35 36 TEST(MachineOperandTest, ChangeToTargetIndexTest) { 37 // Creating a MachineOperand to change it to TargetIndex 38 MachineOperand MO = MachineOperand::CreateImm(50); 39 40 // Checking some precondition on the newly created 41 // MachineOperand. 42 ASSERT_TRUE(MO.isImm()); 43 ASSERT_TRUE(MO.getImm() == 50); 44 ASSERT_FALSE(MO.isTargetIndex()); 45 46 // Changing to TargetIndex with some arbitrary values 47 // for index, offset and flags. 48 MO.ChangeToTargetIndex(74, 57, 12); 49 50 // Checking that the mutation to TargetIndex happened 51 // correctly. 52 ASSERT_TRUE(MO.isTargetIndex()); 53 ASSERT_TRUE(MO.getIndex() == 74); 54 ASSERT_TRUE(MO.getOffset() == 57); 55 ASSERT_TRUE(MO.getTargetFlags() == 12); 56 } 57 58 TEST(MachineOperandTest, PrintRegisterMask) { 59 LLVMContext Ctx; 60 Module Mod("Module", Ctx); 61 auto MF = createMachineFunction(Ctx, Mod); 62 63 uint32_t *Dummy = MF->allocateRegMask(); 64 MachineOperand MO = MachineOperand::CreateRegMask(Dummy); 65 66 // Checking some preconditions on the newly created 67 // MachineOperand. 68 ASSERT_TRUE(MO.isRegMask()); 69 ASSERT_TRUE(MO.getRegMask() == Dummy); 70 71 // Print a MachineOperand containing a RegMask. Here we check that without a 72 // TRI and IntrinsicInfo we still print a less detailed regmask. 73 std::string str; 74 raw_string_ostream OS(str); 75 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 76 ASSERT_TRUE(str == "<regmask ...>"); 77 } 78 79 TEST(MachineOperandTest, PrintSubReg) { 80 // Create a MachineOperand with RegNum=1 and SubReg=5. 81 MachineOperand MO = MachineOperand::CreateReg( 82 /*Reg=*/1, /*isDef=*/false, /*isImp=*/false, /*isKill=*/false, 83 /*isDead=*/false, /*isUndef=*/false, /*isEarlyClobber=*/false, 84 /*SubReg=*/5, /*isDebug=*/false, /*isInternalRead=*/false); 85 86 // Checking some preconditions on the newly created 87 // MachineOperand. 88 ASSERT_TRUE(MO.isReg()); 89 ASSERT_TRUE(MO.getReg() == 1); 90 ASSERT_TRUE(MO.getSubReg() == 5); 91 92 // Print a MachineOperand containing a SubReg. Here we check that without a 93 // TRI and IntrinsicInfo we can still print the subreg index. 94 std::string str; 95 raw_string_ostream OS(str); 96 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 97 ASSERT_TRUE(str == "$physreg1.subreg5"); 98 } 99 100 TEST(MachineOperandTest, PrintCImm) { 101 LLVMContext Context; 102 APInt Int(128, UINT64_MAX); 103 ++Int; 104 ConstantInt *CImm = ConstantInt::get(Context, Int); 105 // Create a MachineOperand with an Imm=(UINT64_MAX + 1) 106 MachineOperand MO = MachineOperand::CreateCImm(CImm); 107 108 // Checking some preconditions on the newly created 109 // MachineOperand. 110 ASSERT_TRUE(MO.isCImm()); 111 ASSERT_TRUE(MO.getCImm() == CImm); 112 ASSERT_TRUE(MO.getCImm()->getValue() == Int); 113 114 // Print a MachineOperand containing a SubReg. Here we check that without a 115 // TRI and IntrinsicInfo we can still print the subreg index. 116 std::string str; 117 raw_string_ostream OS(str); 118 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 119 ASSERT_TRUE(str == "i128 18446744073709551616"); 120 } 121 122 TEST(MachineOperandTest, PrintSubRegIndex) { 123 // Create a MachineOperand with an immediate and print it as a subreg index. 124 MachineOperand MO = MachineOperand::CreateImm(3); 125 126 // Checking some preconditions on the newly created 127 // MachineOperand. 128 ASSERT_TRUE(MO.isImm()); 129 ASSERT_TRUE(MO.getImm() == 3); 130 131 // Print a MachineOperand containing a SubRegIdx. Here we check that without a 132 // TRI and IntrinsicInfo we can print the operand as a subreg index. 133 std::string str; 134 raw_string_ostream OS(str); 135 MachineOperand::printSubRegIdx(OS, MO.getImm(), nullptr); 136 ASSERT_TRUE(str == "%subreg.3"); 137 } 138 139 TEST(MachineOperandTest, PrintCPI) { 140 // Create a MachineOperand with a constant pool index and print it. 141 MachineOperand MO = MachineOperand::CreateCPI(0, 8); 142 143 // Checking some preconditions on the newly created 144 // MachineOperand. 145 ASSERT_TRUE(MO.isCPI()); 146 ASSERT_TRUE(MO.getIndex() == 0); 147 ASSERT_TRUE(MO.getOffset() == 8); 148 149 // Print a MachineOperand containing a constant pool index and a positive 150 // offset. 151 std::string str; 152 { 153 raw_string_ostream OS(str); 154 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 155 ASSERT_TRUE(str == "%const.0 + 8"); 156 } 157 158 str.clear(); 159 160 MO.setOffset(-12); 161 162 // Print a MachineOperand containing a constant pool index and a negative 163 // offset. 164 { 165 raw_string_ostream OS(str); 166 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 167 ASSERT_TRUE(str == "%const.0 - 12"); 168 } 169 } 170 171 TEST(MachineOperandTest, PrintTargetIndexName) { 172 // Create a MachineOperand with a target index and print it. 173 MachineOperand MO = MachineOperand::CreateTargetIndex(0, 8); 174 175 // Checking some preconditions on the newly created 176 // MachineOperand. 177 ASSERT_TRUE(MO.isTargetIndex()); 178 ASSERT_TRUE(MO.getIndex() == 0); 179 ASSERT_TRUE(MO.getOffset() == 8); 180 181 // Print a MachineOperand containing a target index and a positive offset. 182 std::string str; 183 { 184 raw_string_ostream OS(str); 185 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 186 ASSERT_TRUE(str == "target-index(<unknown>) + 8"); 187 } 188 189 str.clear(); 190 191 MO.setOffset(-12); 192 193 // Print a MachineOperand containing a target index and a negative offset. 194 { 195 raw_string_ostream OS(str); 196 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 197 ASSERT_TRUE(str == "target-index(<unknown>) - 12"); 198 } 199 } 200 201 TEST(MachineOperandTest, PrintJumpTableIndex) { 202 // Create a MachineOperand with a jump-table index and print it. 203 MachineOperand MO = MachineOperand::CreateJTI(3); 204 205 // Checking some preconditions on the newly created 206 // MachineOperand. 207 ASSERT_TRUE(MO.isJTI()); 208 ASSERT_TRUE(MO.getIndex() == 3); 209 210 // Print a MachineOperand containing a jump-table index. 211 std::string str; 212 raw_string_ostream OS(str); 213 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 214 ASSERT_TRUE(str == "%jump-table.3"); 215 } 216 217 TEST(MachineOperandTest, PrintExternalSymbol) { 218 // Create a MachineOperand with an external symbol and print it. 219 MachineOperand MO = MachineOperand::CreateES("foo"); 220 221 // Checking some preconditions on the newly created 222 // MachineOperand. 223 ASSERT_TRUE(MO.isSymbol()); 224 ASSERT_TRUE(MO.getSymbolName() == StringRef("foo")); 225 226 // Print a MachineOperand containing an external symbol and no offset. 227 std::string str; 228 { 229 raw_string_ostream OS(str); 230 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 231 ASSERT_TRUE(str == "&foo"); 232 } 233 234 str.clear(); 235 MO.setOffset(12); 236 237 // Print a MachineOperand containing an external symbol and a positive offset. 238 { 239 raw_string_ostream OS(str); 240 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 241 ASSERT_TRUE(str == "&foo + 12"); 242 } 243 244 str.clear(); 245 MO.setOffset(-12); 246 247 // Print a MachineOperand containing an external symbol and a negative offset. 248 { 249 raw_string_ostream OS(str); 250 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 251 ASSERT_TRUE(str == "&foo - 12"); 252 } 253 } 254 255 TEST(MachineOperandTest, PrintGlobalAddress) { 256 LLVMContext Ctx; 257 Module M("MachineOperandGVTest", Ctx); 258 M.getOrInsertGlobal("foo", Type::getInt32Ty(Ctx)); 259 260 GlobalValue *GV = M.getNamedValue("foo"); 261 262 // Create a MachineOperand with a global address and a positive offset and 263 // print it. 264 MachineOperand MO = MachineOperand::CreateGA(GV, 12); 265 266 // Checking some preconditions on the newly created 267 // MachineOperand. 268 ASSERT_TRUE(MO.isGlobal()); 269 ASSERT_TRUE(MO.getGlobal() == GV); 270 ASSERT_TRUE(MO.getOffset() == 12); 271 272 std::string str; 273 // Print a MachineOperand containing a global address and a positive offset. 274 { 275 raw_string_ostream OS(str); 276 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 277 ASSERT_TRUE(str == "@foo + 12"); 278 } 279 280 str.clear(); 281 MO.setOffset(-12); 282 283 // Print a MachineOperand containing a global address and a negative offset. 284 { 285 raw_string_ostream OS(str); 286 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 287 ASSERT_TRUE(str == "@foo - 12"); 288 } 289 } 290 291 TEST(MachineOperandTest, PrintRegisterLiveOut) { 292 // Create a MachineOperand with a register live out list and print it. 293 uint32_t Mask = 0; 294 MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask); 295 296 // Checking some preconditions on the newly created 297 // MachineOperand. 298 ASSERT_TRUE(MO.isRegLiveOut()); 299 ASSERT_TRUE(MO.getRegLiveOut() == &Mask); 300 301 std::string str; 302 // Print a MachineOperand containing a register live out list without a TRI. 303 raw_string_ostream OS(str); 304 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 305 ASSERT_TRUE(str == "liveout(<unknown>)"); 306 } 307 308 TEST(MachineOperandTest, PrintMetadata) { 309 LLVMContext Ctx; 310 Module M("MachineOperandMDNodeTest", Ctx); 311 NamedMDNode *MD = M.getOrInsertNamedMetadata("namedmd"); 312 ModuleSlotTracker MST(&M); 313 Metadata *MDS = MDString::get(Ctx, "foo"); 314 MDNode *Node = MDNode::get(Ctx, MDS); 315 MD->addOperand(Node); 316 317 // Create a MachineOperand with a metadata and print it. 318 MachineOperand MO = MachineOperand::CreateMetadata(Node); 319 320 // Checking some preconditions on the newly created 321 // MachineOperand. 322 ASSERT_TRUE(MO.isMetadata()); 323 ASSERT_TRUE(MO.getMetadata() == Node); 324 325 std::string str; 326 // Print a MachineOperand containing a metadata node. 327 raw_string_ostream OS(str); 328 MO.print(OS, MST, LLT{}, /*OpIdx*/~0U, /*PrintDef=*/false, /*IsStandalone=*/false, 329 /*ShouldPrintRegisterTies=*/false, 0, /*TRI=*/nullptr, 330 /*IntrinsicInfo=*/nullptr); 331 ASSERT_TRUE(str == "!0"); 332 } 333 334 TEST(MachineOperandTest, PrintMCSymbol) { 335 MCAsmInfo MAI; 336 Triple T = Triple("unknown-unknown-unknown"); 337 MCContext Ctx(T, &MAI, /*MRI=*/nullptr, /*MSTI=*/nullptr); 338 MCSymbol *Sym = Ctx.getOrCreateSymbol("foo"); 339 340 // Create a MachineOperand with a metadata and print it. 341 MachineOperand MO = MachineOperand::CreateMCSymbol(Sym); 342 343 // Checking some preconditions on the newly created 344 // MachineOperand. 345 ASSERT_TRUE(MO.isMCSymbol()); 346 ASSERT_TRUE(MO.getMCSymbol() == Sym); 347 348 std::string str; 349 // Print a MachineOperand containing a metadata node. 350 raw_string_ostream OS(str); 351 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 352 ASSERT_TRUE(str == "<mcsymbol foo>"); 353 } 354 355 TEST(MachineOperandTest, PrintCFI) { 356 // Create a MachineOperand with a CFI index but no function and print it. 357 MachineOperand MO = MachineOperand::CreateCFIIndex(8); 358 359 // Checking some preconditions on the newly created 360 // MachineOperand. 361 ASSERT_TRUE(MO.isCFIIndex()); 362 ASSERT_TRUE(MO.getCFIIndex() == 8); 363 364 std::string str; 365 // Print a MachineOperand containing a CFI Index node but no machine function 366 // attached to it. 367 raw_string_ostream OS(str); 368 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 369 ASSERT_TRUE(str == "<cfi directive>"); 370 } 371 372 TEST(MachineOperandTest, PrintIntrinsicID) { 373 // Create a MachineOperand with a generic intrinsic ID. 374 MachineOperand MO = MachineOperand::CreateIntrinsicID(Intrinsic::bswap); 375 376 // Checking some preconditions on the newly created 377 // MachineOperand. 378 ASSERT_TRUE(MO.isIntrinsicID()); 379 ASSERT_TRUE(MO.getIntrinsicID() == Intrinsic::bswap); 380 381 std::string str; 382 { 383 // Print a MachineOperand containing a generic intrinsic ID. 384 raw_string_ostream OS(str); 385 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 386 ASSERT_TRUE(str == "intrinsic(@llvm.bswap)"); 387 } 388 389 str.clear(); 390 // Set a target-specific intrinsic. 391 MO = MachineOperand::CreateIntrinsicID((Intrinsic::ID)-1); 392 { 393 // Print a MachineOperand containing a target-specific intrinsic ID but not 394 // IntrinsicInfo. 395 raw_string_ostream OS(str); 396 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 397 ASSERT_TRUE(str == "intrinsic(4294967295)"); 398 } 399 } 400 401 TEST(MachineOperandTest, PrintPredicate) { 402 // Create a MachineOperand with a generic intrinsic ID. 403 MachineOperand MO = MachineOperand::CreatePredicate(CmpInst::ICMP_EQ); 404 405 // Checking some preconditions on the newly created 406 // MachineOperand. 407 ASSERT_TRUE(MO.isPredicate()); 408 ASSERT_TRUE(MO.getPredicate() == CmpInst::ICMP_EQ); 409 410 std::string str; 411 // Print a MachineOperand containing a int predicate ICMP_EQ. 412 raw_string_ostream OS(str); 413 MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); 414 ASSERT_TRUE(str == "intpred(eq)"); 415 } 416 417 TEST(MachineOperandTest, HashValue) { 418 char SymName1[] = "test"; 419 char SymName2[] = "test"; 420 MachineOperand MO1 = MachineOperand::CreateES(SymName1); 421 MachineOperand MO2 = MachineOperand::CreateES(SymName2); 422 ASSERT_NE(SymName1, SymName2); 423 ASSERT_EQ(hash_value(MO1), hash_value(MO2)); 424 ASSERT_TRUE(MO1.isIdenticalTo(MO2)); 425 } 426 427 } // end namespace 428