brintos

brintos / llvm-project-archived public Read only

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