1 //===- ReducerWorkItem.cpp - Wrapper for Module and MachineFunction -------===// 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 "ReducerWorkItem.h" 10 #include "TestRunner.h" 11 #include "llvm/Analysis/ModuleSummaryAnalysis.h" 12 #include "llvm/Analysis/ProfileSummaryInfo.h" 13 #include "llvm/Bitcode/BitcodeReader.h" 14 #include "llvm/Bitcode/BitcodeWriter.h" 15 #include "llvm/CodeGen/CommandFlags.h" 16 #include "llvm/CodeGen/MIRParser/MIRParser.h" 17 #include "llvm/CodeGen/MIRPrinter.h" 18 #include "llvm/CodeGen/MachineDominators.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineFunctionPass.h" 22 #include "llvm/CodeGen/MachineModuleInfo.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/CodeGen/TargetInstrInfo.h" 25 #include "llvm/IR/Constants.h" 26 #include "llvm/IR/Instructions.h" 27 #include "llvm/IR/ModuleSummaryIndex.h" 28 #include "llvm/IR/Operator.h" 29 #include "llvm/IR/Verifier.h" 30 #include "llvm/IRReader/IRReader.h" 31 #include "llvm/MC/TargetRegistry.h" 32 #include "llvm/Passes/PassBuilder.h" 33 #include "llvm/Support/Host.h" 34 #include "llvm/Support/MemoryBufferRef.h" 35 #include "llvm/Support/SourceMgr.h" 36 #include "llvm/Support/TargetSelect.h" 37 #include "llvm/Support/ToolOutputFile.h" 38 #include "llvm/Support/WithColor.h" 39 #include "llvm/Target/TargetMachine.h" 40 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" 41 #include "llvm/Transforms/Utils/Cloning.h" 42 #include <optional> 43 44 using namespace llvm; 45 46 ReducerWorkItem::ReducerWorkItem() = default; 47 ReducerWorkItem::~ReducerWorkItem() = default; 48 49 extern cl::OptionCategory LLVMReduceOptions; 50 static cl::opt<std::string> TargetTriple("mtriple", 51 cl::desc("Set the target triple"), 52 cl::cat(LLVMReduceOptions)); 53 54 static cl::opt<bool> TmpFilesAsBitcode( 55 "write-tmp-files-as-bitcode", 56 cl::desc("Always write temporary files as bitcode instead of textual IR"), 57 cl::init(false), cl::cat(LLVMReduceOptions)); 58 59 static void cloneFrameInfo( 60 MachineFrameInfo &DstMFI, const MachineFrameInfo &SrcMFI, 61 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) { 62 DstMFI.setFrameAddressIsTaken(SrcMFI.isFrameAddressTaken()); 63 DstMFI.setReturnAddressIsTaken(SrcMFI.isReturnAddressTaken()); 64 DstMFI.setHasStackMap(SrcMFI.hasStackMap()); 65 DstMFI.setHasPatchPoint(SrcMFI.hasPatchPoint()); 66 DstMFI.setUseLocalStackAllocationBlock( 67 SrcMFI.getUseLocalStackAllocationBlock()); 68 DstMFI.setOffsetAdjustment(SrcMFI.getOffsetAdjustment()); 69 70 DstMFI.ensureMaxAlignment(SrcMFI.getMaxAlign()); 71 assert(DstMFI.getMaxAlign() == SrcMFI.getMaxAlign() && 72 "we need to set exact alignment"); 73 74 DstMFI.setAdjustsStack(SrcMFI.adjustsStack()); 75 DstMFI.setHasCalls(SrcMFI.hasCalls()); 76 DstMFI.setHasOpaqueSPAdjustment(SrcMFI.hasOpaqueSPAdjustment()); 77 DstMFI.setHasCopyImplyingStackAdjustment( 78 SrcMFI.hasCopyImplyingStackAdjustment()); 79 DstMFI.setHasVAStart(SrcMFI.hasVAStart()); 80 DstMFI.setHasMustTailInVarArgFunc(SrcMFI.hasMustTailInVarArgFunc()); 81 DstMFI.setHasTailCall(SrcMFI.hasTailCall()); 82 83 if (SrcMFI.isMaxCallFrameSizeComputed()) 84 DstMFI.setMaxCallFrameSize(SrcMFI.getMaxCallFrameSize()); 85 86 DstMFI.setCVBytesOfCalleeSavedRegisters( 87 SrcMFI.getCVBytesOfCalleeSavedRegisters()); 88 89 if (MachineBasicBlock *SavePt = SrcMFI.getSavePoint()) 90 DstMFI.setSavePoint(Src2DstMBB.find(SavePt)->second); 91 if (MachineBasicBlock *RestorePt = SrcMFI.getRestorePoint()) 92 DstMFI.setRestorePoint(Src2DstMBB.find(RestorePt)->second); 93 94 95 auto CopyObjectProperties = [](MachineFrameInfo &DstMFI, 96 const MachineFrameInfo &SrcMFI, int FI) { 97 if (SrcMFI.isStatepointSpillSlotObjectIndex(FI)) 98 DstMFI.markAsStatepointSpillSlotObjectIndex(FI); 99 DstMFI.setObjectSSPLayout(FI, SrcMFI.getObjectSSPLayout(FI)); 100 DstMFI.setObjectZExt(FI, SrcMFI.isObjectZExt(FI)); 101 DstMFI.setObjectSExt(FI, SrcMFI.isObjectSExt(FI)); 102 }; 103 104 for (int i = 0, e = SrcMFI.getNumObjects() - SrcMFI.getNumFixedObjects(); 105 i != e; ++i) { 106 int NewFI; 107 108 assert(!SrcMFI.isFixedObjectIndex(i)); 109 if (SrcMFI.isVariableSizedObjectIndex(i)) { 110 NewFI = DstMFI.CreateVariableSizedObject(SrcMFI.getObjectAlign(i), 111 SrcMFI.getObjectAllocation(i)); 112 } else { 113 NewFI = DstMFI.CreateStackObject( 114 SrcMFI.getObjectSize(i), SrcMFI.getObjectAlign(i), 115 SrcMFI.isSpillSlotObjectIndex(i), SrcMFI.getObjectAllocation(i), 116 SrcMFI.getStackID(i)); 117 DstMFI.setObjectOffset(NewFI, SrcMFI.getObjectOffset(i)); 118 } 119 120 CopyObjectProperties(DstMFI, SrcMFI, i); 121 122 (void)NewFI; 123 assert(i == NewFI && "expected to keep stable frame index numbering"); 124 } 125 126 // Copy the fixed frame objects backwards to preserve frame index numbers, 127 // since CreateFixedObject uses front insertion. 128 for (int i = -1; i >= (int)-SrcMFI.getNumFixedObjects(); --i) { 129 assert(SrcMFI.isFixedObjectIndex(i)); 130 int NewFI = DstMFI.CreateFixedObject( 131 SrcMFI.getObjectSize(i), SrcMFI.getObjectOffset(i), 132 SrcMFI.isImmutableObjectIndex(i), SrcMFI.isAliasedObjectIndex(i)); 133 CopyObjectProperties(DstMFI, SrcMFI, i); 134 135 (void)NewFI; 136 assert(i == NewFI && "expected to keep stable frame index numbering"); 137 } 138 139 for (unsigned I = 0, E = SrcMFI.getLocalFrameObjectCount(); I < E; ++I) { 140 auto LocalObject = SrcMFI.getLocalFrameObjectMap(I); 141 DstMFI.mapLocalFrameObject(LocalObject.first, LocalObject.second); 142 } 143 144 DstMFI.setCalleeSavedInfo(SrcMFI.getCalleeSavedInfo()); 145 146 if (SrcMFI.hasStackProtectorIndex()) { 147 DstMFI.setStackProtectorIndex(SrcMFI.getStackProtectorIndex()); 148 } 149 150 // FIXME: Needs test, missing MIR serialization. 151 if (SrcMFI.hasFunctionContextIndex()) { 152 DstMFI.setFunctionContextIndex(SrcMFI.getFunctionContextIndex()); 153 } 154 } 155 156 static void cloneMemOperands(MachineInstr &DstMI, MachineInstr &SrcMI, 157 MachineFunction &SrcMF, MachineFunction &DstMF) { 158 // The new MachineMemOperands should be owned by the new function's 159 // Allocator. 160 PseudoSourceValueManager &PSVMgr = DstMF.getPSVManager(); 161 162 // We also need to remap the PseudoSourceValues from the new function's 163 // PseudoSourceValueManager. 164 SmallVector<MachineMemOperand *, 2> NewMMOs; 165 for (MachineMemOperand *OldMMO : SrcMI.memoperands()) { 166 MachinePointerInfo NewPtrInfo(OldMMO->getPointerInfo()); 167 if (const PseudoSourceValue *PSV = 168 NewPtrInfo.V.dyn_cast<const PseudoSourceValue *>()) { 169 switch (PSV->kind()) { 170 case PseudoSourceValue::Stack: 171 NewPtrInfo.V = PSVMgr.getStack(); 172 break; 173 case PseudoSourceValue::GOT: 174 NewPtrInfo.V = PSVMgr.getGOT(); 175 break; 176 case PseudoSourceValue::JumpTable: 177 NewPtrInfo.V = PSVMgr.getJumpTable(); 178 break; 179 case PseudoSourceValue::ConstantPool: 180 NewPtrInfo.V = PSVMgr.getConstantPool(); 181 break; 182 case PseudoSourceValue::FixedStack: 183 NewPtrInfo.V = PSVMgr.getFixedStack( 184 cast<FixedStackPseudoSourceValue>(PSV)->getFrameIndex()); 185 break; 186 case PseudoSourceValue::GlobalValueCallEntry: 187 NewPtrInfo.V = PSVMgr.getGlobalValueCallEntry( 188 cast<GlobalValuePseudoSourceValue>(PSV)->getValue()); 189 break; 190 case PseudoSourceValue::ExternalSymbolCallEntry: 191 NewPtrInfo.V = PSVMgr.getExternalSymbolCallEntry( 192 cast<ExternalSymbolPseudoSourceValue>(PSV)->getSymbol()); 193 break; 194 case PseudoSourceValue::TargetCustom: 195 default: 196 // FIXME: We have no generic interface for allocating custom PSVs. 197 report_fatal_error("Cloning TargetCustom PSV not handled"); 198 } 199 } 200 201 MachineMemOperand *NewMMO = DstMF.getMachineMemOperand( 202 NewPtrInfo, OldMMO->getFlags(), OldMMO->getMemoryType(), 203 OldMMO->getBaseAlign(), OldMMO->getAAInfo(), OldMMO->getRanges(), 204 OldMMO->getSyncScopeID(), OldMMO->getSuccessOrdering(), 205 OldMMO->getFailureOrdering()); 206 NewMMOs.push_back(NewMMO); 207 } 208 209 DstMI.setMemRefs(DstMF, NewMMOs); 210 } 211 212 static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF, 213 MachineModuleInfo &DestMMI) { 214 auto DstMF = std::make_unique<MachineFunction>( 215 SrcMF->getFunction(), SrcMF->getTarget(), SrcMF->getSubtarget(), 216 SrcMF->getFunctionNumber(), DestMMI); 217 DenseMap<MachineBasicBlock *, MachineBasicBlock *> Src2DstMBB; 218 219 auto *SrcMRI = &SrcMF->getRegInfo(); 220 auto *DstMRI = &DstMF->getRegInfo(); 221 222 // Clone blocks. 223 for (MachineBasicBlock &SrcMBB : *SrcMF) { 224 MachineBasicBlock *DstMBB = 225 DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock()); 226 Src2DstMBB[&SrcMBB] = DstMBB; 227 228 if (SrcMBB.isIRBlockAddressTaken()) 229 DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock()); 230 if (SrcMBB.isMachineBlockAddressTaken()) 231 DstMBB->setMachineBlockAddressTaken(); 232 233 // FIXME: This is not serialized 234 if (SrcMBB.hasLabelMustBeEmitted()) 235 DstMBB->setLabelMustBeEmitted(); 236 237 DstMBB->setAlignment(SrcMBB.getAlignment()); 238 239 // FIXME: This is not serialized 240 DstMBB->setMaxBytesForAlignment(SrcMBB.getMaxBytesForAlignment()); 241 242 DstMBB->setIsEHPad(SrcMBB.isEHPad()); 243 DstMBB->setIsEHScopeEntry(SrcMBB.isEHScopeEntry()); 244 DstMBB->setIsEHCatchretTarget(SrcMBB.isEHCatchretTarget()); 245 DstMBB->setIsEHFuncletEntry(SrcMBB.isEHFuncletEntry()); 246 247 // FIXME: These are not serialized 248 DstMBB->setIsCleanupFuncletEntry(SrcMBB.isCleanupFuncletEntry()); 249 DstMBB->setIsBeginSection(SrcMBB.isBeginSection()); 250 DstMBB->setIsEndSection(SrcMBB.isEndSection()); 251 252 DstMBB->setSectionID(SrcMBB.getSectionID()); 253 DstMBB->setIsInlineAsmBrIndirectTarget( 254 SrcMBB.isInlineAsmBrIndirectTarget()); 255 256 // FIXME: This is not serialized 257 if (std::optional<uint64_t> Weight = SrcMBB.getIrrLoopHeaderWeight()) 258 DstMBB->setIrrLoopHeaderWeight(*Weight); 259 } 260 261 const MachineFrameInfo &SrcMFI = SrcMF->getFrameInfo(); 262 MachineFrameInfo &DstMFI = DstMF->getFrameInfo(); 263 264 // Copy stack objects and other info 265 cloneFrameInfo(DstMFI, SrcMFI, Src2DstMBB); 266 267 // Remap the debug info frame index references. 268 DstMF->VariableDbgInfos = SrcMF->VariableDbgInfos; 269 270 // Clone virtual registers 271 for (unsigned I = 0, E = SrcMRI->getNumVirtRegs(); I != E; ++I) { 272 Register Reg = Register::index2VirtReg(I); 273 Register NewReg = DstMRI->createIncompleteVirtualRegister( 274 SrcMRI->getVRegName(Reg)); 275 assert(NewReg == Reg && "expected to preserve virtreg number"); 276 277 DstMRI->setRegClassOrRegBank(NewReg, SrcMRI->getRegClassOrRegBank(Reg)); 278 279 LLT RegTy = SrcMRI->getType(Reg); 280 if (RegTy.isValid()) 281 DstMRI->setType(NewReg, RegTy); 282 283 // Copy register allocation hints. 284 const auto &Hints = SrcMRI->getRegAllocationHints(Reg); 285 for (Register PrefReg : Hints.second) 286 DstMRI->addRegAllocationHint(NewReg, PrefReg); 287 } 288 289 const TargetSubtargetInfo &STI = DstMF->getSubtarget(); 290 const TargetInstrInfo *TII = STI.getInstrInfo(); 291 const TargetRegisterInfo *TRI = STI.getRegisterInfo(); 292 293 // Link blocks. 294 for (auto &SrcMBB : *SrcMF) { 295 auto *DstMBB = Src2DstMBB[&SrcMBB]; 296 DstMF->push_back(DstMBB); 297 298 for (auto It = SrcMBB.succ_begin(), IterEnd = SrcMBB.succ_end(); 299 It != IterEnd; ++It) { 300 auto *SrcSuccMBB = *It; 301 auto *DstSuccMBB = Src2DstMBB[SrcSuccMBB]; 302 DstMBB->addSuccessor(DstSuccMBB, SrcMBB.getSuccProbability(It)); 303 } 304 305 for (auto &LI : SrcMBB.liveins_dbg()) 306 DstMBB->addLiveIn(LI); 307 308 // Make sure MRI knows about registers clobbered by unwinder. 309 if (DstMBB->isEHPad()) { 310 if (auto *RegMask = TRI->getCustomEHPadPreservedMask(*DstMF)) 311 DstMRI->addPhysRegsUsedFromRegMask(RegMask); 312 } 313 } 314 315 DenseSet<const uint32_t *> ConstRegisterMasks; 316 317 // Track predefined/named regmasks which we ignore. 318 for (const uint32_t *Mask : TRI->getRegMasks()) 319 ConstRegisterMasks.insert(Mask); 320 321 // Clone instructions. 322 for (auto &SrcMBB : *SrcMF) { 323 auto *DstMBB = Src2DstMBB[&SrcMBB]; 324 for (auto &SrcMI : SrcMBB) { 325 const auto &MCID = TII->get(SrcMI.getOpcode()); 326 auto *DstMI = DstMF->CreateMachineInstr(MCID, SrcMI.getDebugLoc(), 327 /*NoImplicit=*/true); 328 DstMI->setFlags(SrcMI.getFlags()); 329 DstMI->setAsmPrinterFlag(SrcMI.getAsmPrinterFlags()); 330 331 DstMBB->push_back(DstMI); 332 for (auto &SrcMO : SrcMI.operands()) { 333 MachineOperand DstMO(SrcMO); 334 DstMO.clearParent(); 335 336 // Update MBB. 337 if (DstMO.isMBB()) 338 DstMO.setMBB(Src2DstMBB[DstMO.getMBB()]); 339 else if (DstMO.isRegMask()) { 340 DstMRI->addPhysRegsUsedFromRegMask(DstMO.getRegMask()); 341 342 if (!ConstRegisterMasks.count(DstMO.getRegMask())) { 343 uint32_t *DstMask = DstMF->allocateRegMask(); 344 std::memcpy(DstMask, SrcMO.getRegMask(), 345 sizeof(*DstMask) * 346 MachineOperand::getRegMaskSize(TRI->getNumRegs())); 347 DstMO.setRegMask(DstMask); 348 } 349 } 350 351 DstMI->addOperand(DstMO); 352 } 353 354 cloneMemOperands(*DstMI, SrcMI, *SrcMF, *DstMF); 355 } 356 } 357 358 DstMF->setAlignment(SrcMF->getAlignment()); 359 DstMF->setExposesReturnsTwice(SrcMF->exposesReturnsTwice()); 360 DstMF->setHasInlineAsm(SrcMF->hasInlineAsm()); 361 DstMF->setHasWinCFI(SrcMF->hasWinCFI()); 362 363 DstMF->getProperties().reset().set(SrcMF->getProperties()); 364 365 if (!SrcMF->getFrameInstructions().empty() || 366 !SrcMF->getLongjmpTargets().empty() || 367 !SrcMF->getCatchretTargets().empty()) 368 report_fatal_error("cloning not implemented for machine function property"); 369 370 DstMF->setCallsEHReturn(SrcMF->callsEHReturn()); 371 DstMF->setCallsUnwindInit(SrcMF->callsUnwindInit()); 372 DstMF->setHasEHCatchret(SrcMF->hasEHCatchret()); 373 DstMF->setHasEHScopes(SrcMF->hasEHScopes()); 374 DstMF->setHasEHFunclets(SrcMF->hasEHFunclets()); 375 376 if (!SrcMF->getLandingPads().empty() || 377 !SrcMF->getCodeViewAnnotations().empty() || 378 !SrcMF->getTypeInfos().empty() || 379 !SrcMF->getFilterIds().empty() || 380 SrcMF->hasAnyWasmLandingPadIndex() || 381 SrcMF->hasAnyCallSiteLandingPad() || 382 SrcMF->hasAnyCallSiteLabel() || 383 !SrcMF->getCallSitesInfo().empty()) 384 report_fatal_error("cloning not implemented for machine function property"); 385 386 DstMF->setDebugInstrNumberingCount(SrcMF->DebugInstrNumberingCount); 387 388 if (!DstMF->cloneInfoFrom(*SrcMF, Src2DstMBB)) 389 report_fatal_error("target does not implement MachineFunctionInfo cloning"); 390 391 DstMRI->freezeReservedRegs(*DstMF); 392 393 DstMF->verify(nullptr, "", /*AbortOnError=*/true); 394 return DstMF; 395 } 396 397 static void initializeTargetInfo() { 398 InitializeAllTargets(); 399 InitializeAllTargetMCs(); 400 InitializeAllAsmPrinters(); 401 InitializeAllAsmParsers(); 402 } 403 404 void ReducerWorkItem::print(raw_ostream &ROS, void *p) const { 405 if (MMI) { 406 printMIR(ROS, *M); 407 for (Function &F : *M) { 408 if (auto *MF = MMI->getMachineFunction(F)) 409 printMIR(ROS, *MF); 410 } 411 } else { 412 M->print(ROS, /*AssemblyAnnotationWriter=*/nullptr, 413 /*ShouldPreserveUseListOrder=*/true); 414 } 415 } 416 417 bool ReducerWorkItem::verify(raw_fd_ostream *OS) const { 418 if (verifyModule(*M, OS)) 419 return true; 420 421 if (!MMI) 422 return false; 423 424 for (const Function &F : getModule()) { 425 if (const MachineFunction *MF = MMI->getMachineFunction(F)) { 426 if (!MF->verify(nullptr, "", /*AbortOnError=*/false)) 427 return true; 428 } 429 } 430 431 return false; 432 } 433 434 bool ReducerWorkItem::isReduced(const TestRunner &Test) const { 435 const bool UseBitcode = Test.inputIsBitcode() || TmpFilesAsBitcode; 436 437 SmallString<128> CurrentFilepath; 438 439 // Write ReducerWorkItem to tmp file 440 int FD; 441 std::error_code EC = sys::fs::createTemporaryFile( 442 "llvm-reduce", isMIR() ? "mir" : (UseBitcode ? "bc" : "ll"), FD, 443 CurrentFilepath, 444 UseBitcode && !isMIR() ? sys::fs::OF_None : sys::fs::OF_Text); 445 if (EC) { 446 WithColor::error(errs(), Test.getToolName()) 447 << "error making unique filename: " << EC.message() << '\n'; 448 exit(1); 449 } 450 451 ToolOutputFile Out(CurrentFilepath, FD); 452 453 writeOutput(Out.os(), UseBitcode); 454 455 Out.os().close(); 456 if (Out.os().has_error()) { 457 WithColor::error(errs(), Test.getToolName()) 458 << "error emitting bitcode to file '" << CurrentFilepath 459 << "': " << Out.os().error().message() << '\n'; 460 exit(1); 461 } 462 463 // Current Chunks aren't interesting 464 return Test.run(CurrentFilepath); 465 } 466 467 std::unique_ptr<ReducerWorkItem> 468 ReducerWorkItem::clone(const TargetMachine *TM) const { 469 auto CloneMMM = std::make_unique<ReducerWorkItem>(); 470 if (TM) { 471 // We're assuming the Module IR contents are always unchanged by MIR 472 // reductions, and can share it as a constant. 473 CloneMMM->M = M; 474 475 // MachineModuleInfo contains a lot of other state used during codegen which 476 // we won't be using here, but we should be able to ignore it (although this 477 // is pretty ugly). 478 const LLVMTargetMachine *LLVMTM = 479 static_cast<const LLVMTargetMachine *>(TM); 480 CloneMMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM); 481 482 for (const Function &F : getModule()) { 483 if (auto *MF = MMI->getMachineFunction(F)) 484 CloneMMM->MMI->insertFunction(F, cloneMF(MF, *CloneMMM->MMI)); 485 } 486 } else { 487 CloneMMM->M = CloneModule(*M); 488 } 489 return CloneMMM; 490 } 491 492 /// Try to produce some number that indicates a function is getting smaller / 493 /// simpler. 494 static uint64_t computeMIRComplexityScoreImpl(const MachineFunction &MF) { 495 uint64_t Score = 0; 496 const MachineFrameInfo &MFI = MF.getFrameInfo(); 497 498 // Add for stack objects 499 Score += MFI.getNumObjects(); 500 501 // Add in the block count. 502 Score += 2 * MF.size(); 503 504 const MachineRegisterInfo &MRI = MF.getRegInfo(); 505 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 506 Register Reg = Register::index2VirtReg(I); 507 Score += MRI.getRegAllocationHints(Reg).second.size(); 508 } 509 510 for (const MachineBasicBlock &MBB : MF) { 511 for (const MachineInstr &MI : MBB) { 512 const unsigned Opc = MI.getOpcode(); 513 514 // Reductions may want or need to introduce implicit_defs, so don't count 515 // them. 516 // TODO: These probably should count in some way. 517 if (Opc == TargetOpcode::IMPLICIT_DEF || 518 Opc == TargetOpcode::G_IMPLICIT_DEF) 519 continue; 520 521 // Each instruction adds to the score 522 Score += 4; 523 524 if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI || 525 Opc == TargetOpcode::INLINEASM || Opc == TargetOpcode::INLINEASM_BR) 526 ++Score; 527 528 if (MI.getFlags() != 0) 529 ++Score; 530 531 // Increase weight for more operands. 532 for (const MachineOperand &MO : MI.operands()) { 533 ++Score; 534 535 // Treat registers as more complex. 536 if (MO.isReg()) { 537 ++Score; 538 539 // And subregisters as even more complex. 540 if (MO.getSubReg()) { 541 ++Score; 542 if (MO.isDef()) 543 ++Score; 544 } 545 } else if (MO.isRegMask()) 546 ++Score; 547 } 548 } 549 } 550 551 return Score; 552 } 553 554 uint64_t ReducerWorkItem::computeMIRComplexityScore() const { 555 uint64_t Score = 0; 556 557 for (const Function &F : getModule()) { 558 if (auto *MF = MMI->getMachineFunction(F)) 559 Score += computeMIRComplexityScoreImpl(*MF); 560 } 561 562 return Score; 563 } 564 565 // FIXME: ReduceOperandsSkip has similar function, except it uses larger numbers 566 // for more reduced. 567 static unsigned classifyReductivePower(const Value *V) { 568 if (auto *C = dyn_cast<ConstantData>(V)) { 569 if (C->isNullValue()) 570 return 0; 571 if (C->isOneValue()) 572 return 1; 573 if (isa<UndefValue>(V)) 574 return 2; 575 return 3; 576 } 577 578 if (isa<GlobalValue>(V)) 579 return 4; 580 581 // TODO: Account for expression size 582 if (isa<ConstantExpr>(V)) 583 return 5; 584 585 if (isa<Constant>(V)) 586 return 1; 587 588 if (isa<Argument>(V)) 589 return 6; 590 591 if (isa<Instruction>(V)) 592 return 7; 593 594 return 0; 595 } 596 597 // TODO: Additional flags and attributes may be complexity reducing. If we start 598 // adding flags and attributes, they could have negative cost. 599 static uint64_t computeIRComplexityScoreImpl(const Function &F) { 600 uint64_t Score = 1; // Count the function itself 601 SmallVector<std::pair<unsigned, MDNode *>> MDs; 602 603 AttributeList Attrs = F.getAttributes(); 604 for (AttributeSet AttrSet : Attrs) 605 Score += AttrSet.getNumAttributes(); 606 607 for (const BasicBlock &BB : F) { 608 ++Score; 609 610 for (const Instruction &I : BB) { 611 ++Score; 612 613 if (const auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(&I)) { 614 if (OverflowOp->hasNoUnsignedWrap()) 615 ++Score; 616 if (OverflowOp->hasNoSignedWrap()) 617 ++Score; 618 } else if (const auto *GEP = dyn_cast<GEPOperator>(&I)) { 619 if (GEP->isInBounds()) 620 ++Score; 621 } else if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(&I)) { 622 if (ExactOp->isExact()) 623 ++Score; 624 } else if (const auto *FPOp = dyn_cast<FPMathOperator>(&I)) { 625 FastMathFlags FMF = FPOp->getFastMathFlags(); 626 if (FMF.allowReassoc()) 627 ++Score; 628 if (FMF.noNaNs()) 629 ++Score; 630 if (FMF.noInfs()) 631 ++Score; 632 if (FMF.noSignedZeros()) 633 ++Score; 634 if (FMF.allowReciprocal()) 635 ++Score; 636 if (FMF.allowContract()) 637 ++Score; 638 if (FMF.approxFunc()) 639 ++Score; 640 } 641 642 for (const Value *Operand : I.operands()) { 643 ++Score; 644 Score += classifyReductivePower(Operand); 645 } 646 647 I.getAllMetadata(MDs); 648 Score += MDs.size(); 649 MDs.clear(); 650 } 651 } 652 653 return Score; 654 } 655 656 uint64_t ReducerWorkItem::computeIRComplexityScore() const { 657 uint64_t Score = 0; 658 659 const Module &M = getModule(); 660 Score += M.named_metadata_size(); 661 662 SmallVector<std::pair<unsigned, MDNode *>, 32> GlobalMetadata; 663 for (const GlobalVariable &GV : M.globals()) { 664 ++Score; 665 666 if (GV.hasInitializer()) 667 Score += classifyReductivePower(GV.getInitializer()); 668 669 // TODO: Account for linkage? 670 671 GV.getAllMetadata(GlobalMetadata); 672 Score += GlobalMetadata.size(); 673 GlobalMetadata.clear(); 674 } 675 676 for (const GlobalAlias &GA : M.aliases()) 677 Score += classifyReductivePower(GA.getAliasee()); 678 679 for (const GlobalIFunc &GI : M.ifuncs()) 680 Score += classifyReductivePower(GI.getResolver()); 681 682 for (const Function &F : M) 683 Score += computeIRComplexityScoreImpl(F); 684 685 return Score; 686 } 687 688 void ReducerWorkItem::writeOutput(raw_ostream &OS, bool EmitBitcode) const { 689 // Requesting bitcode emission with mir is nonsense, so just ignore it. 690 if (EmitBitcode && !isMIR()) 691 writeBitcode(OS); 692 else 693 print(OS, /*AnnotationWriter=*/nullptr); 694 } 695 696 void ReducerWorkItem::readBitcode(MemoryBufferRef Data, LLVMContext &Ctx, 697 StringRef ToolName) { 698 Expected<BitcodeFileContents> IF = llvm::getBitcodeFileContents(Data); 699 if (!IF) { 700 WithColor::error(errs(), ToolName) << IF.takeError(); 701 exit(1); 702 } 703 BitcodeModule BM = IF->Mods[0]; 704 Expected<BitcodeLTOInfo> LI = BM.getLTOInfo(); 705 Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(Ctx); 706 if (!LI || !MOrErr) { 707 WithColor::error(errs(), ToolName) << IF.takeError(); 708 exit(1); 709 } 710 LTOInfo = std::make_unique<BitcodeLTOInfo>(*LI); 711 M = std::move(MOrErr.get()); 712 } 713 714 void ReducerWorkItem::writeBitcode(raw_ostream &OutStream) const { 715 if (LTOInfo && LTOInfo->IsThinLTO && LTOInfo->EnableSplitLTOUnit) { 716 PassBuilder PB; 717 LoopAnalysisManager LAM; 718 FunctionAnalysisManager FAM; 719 CGSCCAnalysisManager CGAM; 720 ModuleAnalysisManager MAM; 721 PB.registerModuleAnalyses(MAM); 722 PB.registerCGSCCAnalyses(CGAM); 723 PB.registerFunctionAnalyses(FAM); 724 PB.registerLoopAnalyses(LAM); 725 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); 726 ModulePassManager MPM; 727 MPM.addPass(ThinLTOBitcodeWriterPass(OutStream, nullptr)); 728 MPM.run(*M, MAM); 729 } else { 730 std::unique_ptr<ModuleSummaryIndex> Index; 731 if (LTOInfo && LTOInfo->HasSummary) { 732 ProfileSummaryInfo PSI(*M); 733 Index = std::make_unique<ModuleSummaryIndex>( 734 buildModuleSummaryIndex(*M, nullptr, &PSI)); 735 } 736 WriteBitcodeToFile(getModule(), OutStream, Index.get()); 737 } 738 } 739 740 std::pair<std::unique_ptr<ReducerWorkItem>, bool> 741 llvm::parseReducerWorkItem(StringRef ToolName, StringRef Filename, 742 LLVMContext &Ctxt, 743 std::unique_ptr<TargetMachine> &TM, bool IsMIR) { 744 bool IsBitcode = false; 745 Triple TheTriple; 746 747 auto MMM = std::make_unique<ReducerWorkItem>(); 748 749 if (IsMIR) { 750 initializeTargetInfo(); 751 752 auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true); 753 if (std::error_code EC = FileOrErr.getError()) { 754 WithColor::error(errs(), ToolName) << EC.message() << '\n'; 755 return {nullptr, false}; 756 } 757 758 std::unique_ptr<MIRParser> MParser = 759 createMIRParser(std::move(FileOrErr.get()), Ctxt); 760 761 auto SetDataLayout = [&](StringRef DataLayoutTargetTriple, 762 StringRef OldDLStr) -> std::optional<std::string> { 763 // If we are supposed to override the target triple, do so now. 764 std::string IRTargetTriple = DataLayoutTargetTriple.str(); 765 if (!TargetTriple.empty()) 766 IRTargetTriple = Triple::normalize(TargetTriple); 767 TheTriple = Triple(IRTargetTriple); 768 if (TheTriple.getTriple().empty()) 769 TheTriple.setTriple(sys::getDefaultTargetTriple()); 770 771 std::string Error; 772 const Target *TheTarget = 773 TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); 774 if (!TheTarget) { 775 WithColor::error(errs(), ToolName) << Error; 776 exit(1); 777 } 778 779 // Hopefully the MIR parsing doesn't depend on any options. 780 TargetOptions Options; 781 std::optional<Reloc::Model> RM = codegen::getExplicitRelocModel(); 782 std::string CPUStr = codegen::getCPUStr(); 783 std::string FeaturesStr = codegen::getFeaturesStr(); 784 TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine( 785 TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, 786 codegen::getExplicitCodeModel(), CodeGenOpt::Default)); 787 assert(TM && "Could not allocate target machine!"); 788 789 return TM->createDataLayout().getStringRepresentation(); 790 }; 791 792 std::unique_ptr<Module> M = MParser->parseIRModule(SetDataLayout); 793 LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get()); 794 795 MMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM); 796 MParser->parseMachineFunctions(*M, *MMM->MMI); 797 MMM->M = std::move(M); 798 } else { 799 SMDiagnostic Err; 800 ErrorOr<std::unique_ptr<MemoryBuffer>> MB = 801 MemoryBuffer::getFileOrSTDIN(Filename); 802 if (std::error_code EC = MB.getError()) { 803 WithColor::error(errs(), ToolName) 804 << Filename << ": " << EC.message() << "\n"; 805 return {nullptr, false}; 806 } 807 808 if (!isBitcode((const unsigned char *)(*MB)->getBufferStart(), 809 (const unsigned char *)(*MB)->getBufferEnd())) { 810 std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt); 811 if (!Result) { 812 Err.print(ToolName.data(), errs()); 813 return {nullptr, false}; 814 } 815 MMM->M = std::move(Result); 816 } else { 817 IsBitcode = true; 818 MMM->readBitcode(MemoryBufferRef(**MB), Ctxt, ToolName); 819 820 if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit) 821 initializeTargetInfo(); 822 } 823 } 824 if (MMM->verify(&errs())) { 825 WithColor::error(errs(), ToolName) 826 << Filename << " - input module is broken!\n"; 827 return {nullptr, false}; 828 } 829 return {std::move(MMM), IsBitcode}; 830 } 831