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