123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828 |
- //===- ReducerWorkItem.cpp - Wrapper for Module and MachineFunction -------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "ReducerWorkItem.h"
- #include "TestRunner.h"
- #include "llvm/Analysis/ModuleSummaryAnalysis.h"
- #include "llvm/Analysis/ProfileSummaryInfo.h"
- #include "llvm/Bitcode/BitcodeReader.h"
- #include "llvm/Bitcode/BitcodeWriter.h"
- #include "llvm/CodeGen/CommandFlags.h"
- #include "llvm/CodeGen/MIRParser/MIRParser.h"
- #include "llvm/CodeGen/MIRPrinter.h"
- #include "llvm/CodeGen/MachineDominators.h"
- #include "llvm/CodeGen/MachineFrameInfo.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/MachineFunctionPass.h"
- #include "llvm/CodeGen/MachineModuleInfo.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- #include "llvm/CodeGen/TargetInstrInfo.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/ModuleSummaryIndex.h"
- #include "llvm/IR/Operator.h"
- #include "llvm/IR/Verifier.h"
- #include "llvm/IRReader/IRReader.h"
- #include "llvm/MC/TargetRegistry.h"
- #include "llvm/Passes/PassBuilder.h"
- #include "llvm/Support/Host.h"
- #include "llvm/Support/MemoryBufferRef.h"
- #include "llvm/Support/SourceMgr.h"
- #include "llvm/Support/TargetSelect.h"
- #include "llvm/Support/ToolOutputFile.h"
- #include "llvm/Support/WithColor.h"
- #include "llvm/Target/TargetMachine.h"
- #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
- #include "llvm/Transforms/Utils/Cloning.h"
- #include <optional>
- using namespace llvm;
- ReducerWorkItem::ReducerWorkItem() = default;
- ReducerWorkItem::~ReducerWorkItem() = default;
- extern cl::OptionCategory LLVMReduceOptions;
- static cl::opt<std::string> TargetTriple("mtriple",
- cl::desc("Set the target triple"),
- cl::cat(LLVMReduceOptions));
- static cl::opt<bool> TmpFilesAsBitcode(
- "write-tmp-files-as-bitcode",
- cl::desc("Always write temporary files as bitcode instead of textual IR"),
- cl::init(false), cl::cat(LLVMReduceOptions));
- static void cloneFrameInfo(
- MachineFrameInfo &DstMFI, const MachineFrameInfo &SrcMFI,
- const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) {
- DstMFI.setFrameAddressIsTaken(SrcMFI.isFrameAddressTaken());
- DstMFI.setReturnAddressIsTaken(SrcMFI.isReturnAddressTaken());
- DstMFI.setHasStackMap(SrcMFI.hasStackMap());
- DstMFI.setHasPatchPoint(SrcMFI.hasPatchPoint());
- DstMFI.setUseLocalStackAllocationBlock(
- SrcMFI.getUseLocalStackAllocationBlock());
- DstMFI.setOffsetAdjustment(SrcMFI.getOffsetAdjustment());
- DstMFI.ensureMaxAlignment(SrcMFI.getMaxAlign());
- assert(DstMFI.getMaxAlign() == SrcMFI.getMaxAlign() &&
- "we need to set exact alignment");
- DstMFI.setAdjustsStack(SrcMFI.adjustsStack());
- DstMFI.setHasCalls(SrcMFI.hasCalls());
- DstMFI.setHasOpaqueSPAdjustment(SrcMFI.hasOpaqueSPAdjustment());
- DstMFI.setHasCopyImplyingStackAdjustment(
- SrcMFI.hasCopyImplyingStackAdjustment());
- DstMFI.setHasVAStart(SrcMFI.hasVAStart());
- DstMFI.setHasMustTailInVarArgFunc(SrcMFI.hasMustTailInVarArgFunc());
- DstMFI.setHasTailCall(SrcMFI.hasTailCall());
- if (SrcMFI.isMaxCallFrameSizeComputed())
- DstMFI.setMaxCallFrameSize(SrcMFI.getMaxCallFrameSize());
- DstMFI.setCVBytesOfCalleeSavedRegisters(
- SrcMFI.getCVBytesOfCalleeSavedRegisters());
- if (MachineBasicBlock *SavePt = SrcMFI.getSavePoint())
- DstMFI.setSavePoint(Src2DstMBB.find(SavePt)->second);
- if (MachineBasicBlock *RestorePt = SrcMFI.getRestorePoint())
- DstMFI.setRestorePoint(Src2DstMBB.find(RestorePt)->second);
- auto CopyObjectProperties = [](MachineFrameInfo &DstMFI,
- const MachineFrameInfo &SrcMFI, int FI) {
- if (SrcMFI.isStatepointSpillSlotObjectIndex(FI))
- DstMFI.markAsStatepointSpillSlotObjectIndex(FI);
- DstMFI.setObjectSSPLayout(FI, SrcMFI.getObjectSSPLayout(FI));
- DstMFI.setObjectZExt(FI, SrcMFI.isObjectZExt(FI));
- DstMFI.setObjectSExt(FI, SrcMFI.isObjectSExt(FI));
- };
- for (int i = 0, e = SrcMFI.getNumObjects() - SrcMFI.getNumFixedObjects();
- i != e; ++i) {
- int NewFI;
- assert(!SrcMFI.isFixedObjectIndex(i));
- if (SrcMFI.isVariableSizedObjectIndex(i)) {
- NewFI = DstMFI.CreateVariableSizedObject(SrcMFI.getObjectAlign(i),
- SrcMFI.getObjectAllocation(i));
- } else {
- NewFI = DstMFI.CreateStackObject(
- SrcMFI.getObjectSize(i), SrcMFI.getObjectAlign(i),
- SrcMFI.isSpillSlotObjectIndex(i), SrcMFI.getObjectAllocation(i),
- SrcMFI.getStackID(i));
- DstMFI.setObjectOffset(NewFI, SrcMFI.getObjectOffset(i));
- }
- CopyObjectProperties(DstMFI, SrcMFI, i);
- (void)NewFI;
- assert(i == NewFI && "expected to keep stable frame index numbering");
- }
- // Copy the fixed frame objects backwards to preserve frame index numbers,
- // since CreateFixedObject uses front insertion.
- for (int i = -1; i >= (int)-SrcMFI.getNumFixedObjects(); --i) {
- assert(SrcMFI.isFixedObjectIndex(i));
- int NewFI = DstMFI.CreateFixedObject(
- SrcMFI.getObjectSize(i), SrcMFI.getObjectOffset(i),
- SrcMFI.isImmutableObjectIndex(i), SrcMFI.isAliasedObjectIndex(i));
- CopyObjectProperties(DstMFI, SrcMFI, i);
- (void)NewFI;
- assert(i == NewFI && "expected to keep stable frame index numbering");
- }
- for (unsigned I = 0, E = SrcMFI.getLocalFrameObjectCount(); I < E; ++I) {
- auto LocalObject = SrcMFI.getLocalFrameObjectMap(I);
- DstMFI.mapLocalFrameObject(LocalObject.first, LocalObject.second);
- }
- DstMFI.setCalleeSavedInfo(SrcMFI.getCalleeSavedInfo());
- if (SrcMFI.hasStackProtectorIndex()) {
- DstMFI.setStackProtectorIndex(SrcMFI.getStackProtectorIndex());
- }
- // FIXME: Needs test, missing MIR serialization.
- if (SrcMFI.hasFunctionContextIndex()) {
- DstMFI.setFunctionContextIndex(SrcMFI.getFunctionContextIndex());
- }
- }
- static void cloneMemOperands(MachineInstr &DstMI, MachineInstr &SrcMI,
- MachineFunction &SrcMF, MachineFunction &DstMF) {
- // The new MachineMemOperands should be owned by the new function's
- // Allocator.
- PseudoSourceValueManager &PSVMgr = DstMF.getPSVManager();
- // We also need to remap the PseudoSourceValues from the new function's
- // PseudoSourceValueManager.
- SmallVector<MachineMemOperand *, 2> NewMMOs;
- for (MachineMemOperand *OldMMO : SrcMI.memoperands()) {
- MachinePointerInfo NewPtrInfo(OldMMO->getPointerInfo());
- if (const PseudoSourceValue *PSV =
- NewPtrInfo.V.dyn_cast<const PseudoSourceValue *>()) {
- switch (PSV->kind()) {
- case PseudoSourceValue::Stack:
- NewPtrInfo.V = PSVMgr.getStack();
- break;
- case PseudoSourceValue::GOT:
- NewPtrInfo.V = PSVMgr.getGOT();
- break;
- case PseudoSourceValue::JumpTable:
- NewPtrInfo.V = PSVMgr.getJumpTable();
- break;
- case PseudoSourceValue::ConstantPool:
- NewPtrInfo.V = PSVMgr.getConstantPool();
- break;
- case PseudoSourceValue::FixedStack:
- NewPtrInfo.V = PSVMgr.getFixedStack(
- cast<FixedStackPseudoSourceValue>(PSV)->getFrameIndex());
- break;
- case PseudoSourceValue::GlobalValueCallEntry:
- NewPtrInfo.V = PSVMgr.getGlobalValueCallEntry(
- cast<GlobalValuePseudoSourceValue>(PSV)->getValue());
- break;
- case PseudoSourceValue::ExternalSymbolCallEntry:
- NewPtrInfo.V = PSVMgr.getExternalSymbolCallEntry(
- cast<ExternalSymbolPseudoSourceValue>(PSV)->getSymbol());
- break;
- case PseudoSourceValue::TargetCustom:
- default:
- // FIXME: We have no generic interface for allocating custom PSVs.
- report_fatal_error("Cloning TargetCustom PSV not handled");
- }
- }
- MachineMemOperand *NewMMO = DstMF.getMachineMemOperand(
- NewPtrInfo, OldMMO->getFlags(), OldMMO->getMemoryType(),
- OldMMO->getBaseAlign(), OldMMO->getAAInfo(), OldMMO->getRanges(),
- OldMMO->getSyncScopeID(), OldMMO->getSuccessOrdering(),
- OldMMO->getFailureOrdering());
- NewMMOs.push_back(NewMMO);
- }
- DstMI.setMemRefs(DstMF, NewMMOs);
- }
- static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF,
- MachineModuleInfo &DestMMI) {
- auto DstMF = std::make_unique<MachineFunction>(
- SrcMF->getFunction(), SrcMF->getTarget(), SrcMF->getSubtarget(),
- SrcMF->getFunctionNumber(), DestMMI);
- DenseMap<MachineBasicBlock *, MachineBasicBlock *> Src2DstMBB;
- auto *SrcMRI = &SrcMF->getRegInfo();
- auto *DstMRI = &DstMF->getRegInfo();
- // Clone blocks.
- for (MachineBasicBlock &SrcMBB : *SrcMF) {
- MachineBasicBlock *DstMBB =
- DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock());
- Src2DstMBB[&SrcMBB] = DstMBB;
- if (SrcMBB.isIRBlockAddressTaken())
- DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock());
- if (SrcMBB.isMachineBlockAddressTaken())
- DstMBB->setMachineBlockAddressTaken();
- // FIXME: This is not serialized
- if (SrcMBB.hasLabelMustBeEmitted())
- DstMBB->setLabelMustBeEmitted();
- DstMBB->setAlignment(SrcMBB.getAlignment());
- // FIXME: This is not serialized
- DstMBB->setMaxBytesForAlignment(SrcMBB.getMaxBytesForAlignment());
- DstMBB->setIsEHPad(SrcMBB.isEHPad());
- DstMBB->setIsEHScopeEntry(SrcMBB.isEHScopeEntry());
- DstMBB->setIsEHCatchretTarget(SrcMBB.isEHCatchretTarget());
- DstMBB->setIsEHFuncletEntry(SrcMBB.isEHFuncletEntry());
- // FIXME: These are not serialized
- DstMBB->setIsCleanupFuncletEntry(SrcMBB.isCleanupFuncletEntry());
- DstMBB->setIsBeginSection(SrcMBB.isBeginSection());
- DstMBB->setIsEndSection(SrcMBB.isEndSection());
- DstMBB->setSectionID(SrcMBB.getSectionID());
- DstMBB->setIsInlineAsmBrIndirectTarget(
- SrcMBB.isInlineAsmBrIndirectTarget());
- // FIXME: This is not serialized
- if (std::optional<uint64_t> Weight = SrcMBB.getIrrLoopHeaderWeight())
- DstMBB->setIrrLoopHeaderWeight(*Weight);
- }
- const MachineFrameInfo &SrcMFI = SrcMF->getFrameInfo();
- MachineFrameInfo &DstMFI = DstMF->getFrameInfo();
- // Copy stack objects and other info
- cloneFrameInfo(DstMFI, SrcMFI, Src2DstMBB);
- // Remap the debug info frame index references.
- DstMF->VariableDbgInfos = SrcMF->VariableDbgInfos;
- // Clone virtual registers
- for (unsigned I = 0, E = SrcMRI->getNumVirtRegs(); I != E; ++I) {
- Register Reg = Register::index2VirtReg(I);
- Register NewReg = DstMRI->createIncompleteVirtualRegister(
- SrcMRI->getVRegName(Reg));
- assert(NewReg == Reg && "expected to preserve virtreg number");
- DstMRI->setRegClassOrRegBank(NewReg, SrcMRI->getRegClassOrRegBank(Reg));
- LLT RegTy = SrcMRI->getType(Reg);
- if (RegTy.isValid())
- DstMRI->setType(NewReg, RegTy);
- // Copy register allocation hints.
- const auto &Hints = SrcMRI->getRegAllocationHints(Reg);
- for (Register PrefReg : Hints.second)
- DstMRI->addRegAllocationHint(NewReg, PrefReg);
- }
- const TargetSubtargetInfo &STI = DstMF->getSubtarget();
- const TargetInstrInfo *TII = STI.getInstrInfo();
- const TargetRegisterInfo *TRI = STI.getRegisterInfo();
- // Link blocks.
- for (auto &SrcMBB : *SrcMF) {
- auto *DstMBB = Src2DstMBB[&SrcMBB];
- DstMF->push_back(DstMBB);
- for (auto It = SrcMBB.succ_begin(), IterEnd = SrcMBB.succ_end();
- It != IterEnd; ++It) {
- auto *SrcSuccMBB = *It;
- auto *DstSuccMBB = Src2DstMBB[SrcSuccMBB];
- DstMBB->addSuccessor(DstSuccMBB, SrcMBB.getSuccProbability(It));
- }
- for (auto &LI : SrcMBB.liveins_dbg())
- DstMBB->addLiveIn(LI);
- // Make sure MRI knows about registers clobbered by unwinder.
- if (DstMBB->isEHPad()) {
- if (auto *RegMask = TRI->getCustomEHPadPreservedMask(*DstMF))
- DstMRI->addPhysRegsUsedFromRegMask(RegMask);
- }
- }
- DenseSet<const uint32_t *> ConstRegisterMasks;
- // Track predefined/named regmasks which we ignore.
- for (const uint32_t *Mask : TRI->getRegMasks())
- ConstRegisterMasks.insert(Mask);
- // Clone instructions.
- for (auto &SrcMBB : *SrcMF) {
- auto *DstMBB = Src2DstMBB[&SrcMBB];
- for (auto &SrcMI : SrcMBB) {
- const auto &MCID = TII->get(SrcMI.getOpcode());
- auto *DstMI = DstMF->CreateMachineInstr(MCID, SrcMI.getDebugLoc(),
- /*NoImplicit=*/true);
- DstMI->setFlags(SrcMI.getFlags());
- DstMI->setAsmPrinterFlag(SrcMI.getAsmPrinterFlags());
- DstMBB->push_back(DstMI);
- for (auto &SrcMO : SrcMI.operands()) {
- MachineOperand DstMO(SrcMO);
- DstMO.clearParent();
- // Update MBB.
- if (DstMO.isMBB())
- DstMO.setMBB(Src2DstMBB[DstMO.getMBB()]);
- else if (DstMO.isRegMask()) {
- DstMRI->addPhysRegsUsedFromRegMask(DstMO.getRegMask());
- if (!ConstRegisterMasks.count(DstMO.getRegMask())) {
- uint32_t *DstMask = DstMF->allocateRegMask();
- std::memcpy(DstMask, SrcMO.getRegMask(),
- sizeof(*DstMask) *
- MachineOperand::getRegMaskSize(TRI->getNumRegs()));
- DstMO.setRegMask(DstMask);
- }
- }
- DstMI->addOperand(DstMO);
- }
- cloneMemOperands(*DstMI, SrcMI, *SrcMF, *DstMF);
- }
- }
- DstMF->setAlignment(SrcMF->getAlignment());
- DstMF->setExposesReturnsTwice(SrcMF->exposesReturnsTwice());
- DstMF->setHasInlineAsm(SrcMF->hasInlineAsm());
- DstMF->setHasWinCFI(SrcMF->hasWinCFI());
- DstMF->getProperties().reset().set(SrcMF->getProperties());
- if (!SrcMF->getFrameInstructions().empty() ||
- !SrcMF->getLongjmpTargets().empty() ||
- !SrcMF->getCatchretTargets().empty())
- report_fatal_error("cloning not implemented for machine function property");
- DstMF->setCallsEHReturn(SrcMF->callsEHReturn());
- DstMF->setCallsUnwindInit(SrcMF->callsUnwindInit());
- DstMF->setHasEHCatchret(SrcMF->hasEHCatchret());
- DstMF->setHasEHScopes(SrcMF->hasEHScopes());
- DstMF->setHasEHFunclets(SrcMF->hasEHFunclets());
- if (!SrcMF->getLandingPads().empty() ||
- !SrcMF->getCodeViewAnnotations().empty() ||
- !SrcMF->getTypeInfos().empty() ||
- !SrcMF->getFilterIds().empty() ||
- SrcMF->hasAnyWasmLandingPadIndex() ||
- SrcMF->hasAnyCallSiteLandingPad() ||
- SrcMF->hasAnyCallSiteLabel() ||
- !SrcMF->getCallSitesInfo().empty())
- report_fatal_error("cloning not implemented for machine function property");
- DstMF->setDebugInstrNumberingCount(SrcMF->DebugInstrNumberingCount);
- if (!DstMF->cloneInfoFrom(*SrcMF, Src2DstMBB))
- report_fatal_error("target does not implement MachineFunctionInfo cloning");
- DstMRI->freezeReservedRegs(*DstMF);
- DstMF->verify(nullptr, "", /*AbortOnError=*/true);
- return DstMF;
- }
- static void initializeTargetInfo() {
- InitializeAllTargets();
- InitializeAllTargetMCs();
- InitializeAllAsmPrinters();
- InitializeAllAsmParsers();
- }
- void ReducerWorkItem::print(raw_ostream &ROS, void *p) const {
- if (MMI) {
- printMIR(ROS, *M);
- for (Function &F : *M) {
- if (auto *MF = MMI->getMachineFunction(F))
- printMIR(ROS, *MF);
- }
- } else {
- M->print(ROS, /*AssemblyAnnotationWriter=*/nullptr,
- /*ShouldPreserveUseListOrder=*/true);
- }
- }
- bool ReducerWorkItem::verify(raw_fd_ostream *OS) const {
- if (verifyModule(*M, OS))
- return true;
- if (!MMI)
- return false;
- for (const Function &F : getModule()) {
- if (const MachineFunction *MF = MMI->getMachineFunction(F)) {
- if (!MF->verify(nullptr, "", /*AbortOnError=*/false))
- return true;
- }
- }
- return false;
- }
- bool ReducerWorkItem::isReduced(const TestRunner &Test) const {
- const bool UseBitcode = Test.inputIsBitcode() || TmpFilesAsBitcode;
- SmallString<128> CurrentFilepath;
- // Write ReducerWorkItem to tmp file
- int FD;
- std::error_code EC = sys::fs::createTemporaryFile(
- "llvm-reduce", isMIR() ? "mir" : (UseBitcode ? "bc" : "ll"), FD,
- CurrentFilepath,
- UseBitcode && !isMIR() ? sys::fs::OF_None : sys::fs::OF_Text);
- if (EC) {
- errs() << "Error making unique filename: " << EC.message() << "!\n";
- exit(1);
- }
- ToolOutputFile Out(CurrentFilepath, FD);
- writeOutput(Out.os(), UseBitcode);
- Out.os().close();
- if (Out.os().has_error()) {
- errs() << "Error emitting bitcode to file '" << CurrentFilepath
- << "': " << Out.os().error().message();
- exit(1);
- }
- // Current Chunks aren't interesting
- return Test.run(CurrentFilepath);
- }
- std::unique_ptr<ReducerWorkItem>
- ReducerWorkItem::clone(const TargetMachine *TM) const {
- auto CloneMMM = std::make_unique<ReducerWorkItem>();
- if (TM) {
- // We're assuming the Module IR contents are always unchanged by MIR
- // reductions, and can share it as a constant.
- CloneMMM->M = M;
- // MachineModuleInfo contains a lot of other state used during codegen which
- // we won't be using here, but we should be able to ignore it (although this
- // is pretty ugly).
- const LLVMTargetMachine *LLVMTM =
- static_cast<const LLVMTargetMachine *>(TM);
- CloneMMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM);
- for (const Function &F : getModule()) {
- if (auto *MF = MMI->getMachineFunction(F))
- CloneMMM->MMI->insertFunction(F, cloneMF(MF, *CloneMMM->MMI));
- }
- } else {
- CloneMMM->M = CloneModule(*M);
- }
- return CloneMMM;
- }
- /// Try to produce some number that indicates a function is getting smaller /
- /// simpler.
- static uint64_t computeMIRComplexityScoreImpl(const MachineFunction &MF) {
- uint64_t Score = 0;
- const MachineFrameInfo &MFI = MF.getFrameInfo();
- // Add for stack objects
- Score += MFI.getNumObjects();
- // Add in the block count.
- Score += 2 * MF.size();
- const MachineRegisterInfo &MRI = MF.getRegInfo();
- for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
- Register Reg = Register::index2VirtReg(I);
- Score += MRI.getRegAllocationHints(Reg).second.size();
- }
- for (const MachineBasicBlock &MBB : MF) {
- for (const MachineInstr &MI : MBB) {
- const unsigned Opc = MI.getOpcode();
- // Reductions may want or need to introduce implicit_defs, so don't count
- // them.
- // TODO: These probably should count in some way.
- if (Opc == TargetOpcode::IMPLICIT_DEF ||
- Opc == TargetOpcode::G_IMPLICIT_DEF)
- continue;
- // Each instruction adds to the score
- Score += 4;
- if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI ||
- Opc == TargetOpcode::INLINEASM || Opc == TargetOpcode::INLINEASM_BR)
- ++Score;
- if (MI.getFlags() != 0)
- ++Score;
- // Increase weight for more operands.
- for (const MachineOperand &MO : MI.operands()) {
- ++Score;
- // Treat registers as more complex.
- if (MO.isReg()) {
- ++Score;
- // And subregisters as even more complex.
- if (MO.getSubReg()) {
- ++Score;
- if (MO.isDef())
- ++Score;
- }
- } else if (MO.isRegMask())
- ++Score;
- }
- }
- }
- return Score;
- }
- uint64_t ReducerWorkItem::computeMIRComplexityScore() const {
- uint64_t Score = 0;
- for (const Function &F : getModule()) {
- if (auto *MF = MMI->getMachineFunction(F))
- Score += computeMIRComplexityScoreImpl(*MF);
- }
- return Score;
- }
- // FIXME: ReduceOperandsSkip has similar function, except it uses larger numbers
- // for more reduced.
- static unsigned classifyReductivePower(const Value *V) {
- if (auto *C = dyn_cast<ConstantData>(V)) {
- if (C->isNullValue())
- return 0;
- if (C->isOneValue())
- return 1;
- if (isa<UndefValue>(V))
- return 2;
- return 3;
- }
- if (isa<GlobalValue>(V))
- return 4;
- // TODO: Account for expression size
- if (isa<ConstantExpr>(V))
- return 5;
- if (isa<Constant>(V))
- return 1;
- if (isa<Argument>(V))
- return 6;
- if (isa<Instruction>(V))
- return 7;
- return 0;
- }
- // TODO: Additional flags and attributes may be complexity reducing. If we start
- // adding flags and attributes, they could have negative cost.
- static uint64_t computeIRComplexityScoreImpl(const Function &F) {
- uint64_t Score = 1; // Count the function itself
- SmallVector<std::pair<unsigned, MDNode *>> MDs;
- AttributeList Attrs = F.getAttributes();
- for (AttributeSet AttrSet : Attrs)
- Score += AttrSet.getNumAttributes();
- for (const BasicBlock &BB : F) {
- ++Score;
- for (const Instruction &I : BB) {
- ++Score;
- if (const auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(&I)) {
- if (OverflowOp->hasNoUnsignedWrap())
- ++Score;
- if (OverflowOp->hasNoSignedWrap())
- ++Score;
- } else if (const auto *GEP = dyn_cast<GEPOperator>(&I)) {
- if (GEP->isInBounds())
- ++Score;
- } else if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(&I)) {
- if (ExactOp->isExact())
- ++Score;
- } else if (const auto *FPOp = dyn_cast<FPMathOperator>(&I)) {
- FastMathFlags FMF = FPOp->getFastMathFlags();
- if (FMF.allowReassoc())
- ++Score;
- if (FMF.noNaNs())
- ++Score;
- if (FMF.noInfs())
- ++Score;
- if (FMF.noSignedZeros())
- ++Score;
- if (FMF.allowReciprocal())
- ++Score;
- if (FMF.allowContract())
- ++Score;
- if (FMF.approxFunc())
- ++Score;
- }
- for (const Value *Operand : I.operands()) {
- ++Score;
- Score += classifyReductivePower(Operand);
- }
- I.getAllMetadata(MDs);
- Score += MDs.size();
- MDs.clear();
- }
- }
- return Score;
- }
- uint64_t ReducerWorkItem::computeIRComplexityScore() const {
- uint64_t Score = 0;
- const Module &M = getModule();
- Score += M.named_metadata_size();
- SmallVector<std::pair<unsigned, MDNode *>, 32> GlobalMetadata;
- for (const GlobalVariable &GV : M.globals()) {
- ++Score;
- if (GV.hasInitializer())
- Score += classifyReductivePower(GV.getInitializer());
- // TODO: Account for linkage?
- GV.getAllMetadata(GlobalMetadata);
- Score += GlobalMetadata.size();
- GlobalMetadata.clear();
- }
- for (const GlobalAlias &GA : M.aliases())
- Score += classifyReductivePower(GA.getAliasee());
- for (const GlobalIFunc &GI : M.ifuncs())
- Score += classifyReductivePower(GI.getResolver());
- for (const Function &F : M)
- Score += computeIRComplexityScoreImpl(F);
- return Score;
- }
- void ReducerWorkItem::writeOutput(raw_ostream &OS, bool EmitBitcode) const {
- // Requesting bitcode emission with mir is nonsense, so just ignore it.
- if (EmitBitcode && !isMIR())
- writeBitcode(OS);
- else
- print(OS, /*AnnotationWriter=*/nullptr);
- }
- void ReducerWorkItem::readBitcode(MemoryBufferRef Data, LLVMContext &Ctx,
- StringRef ToolName) {
- Expected<BitcodeFileContents> IF = llvm::getBitcodeFileContents(Data);
- if (!IF) {
- WithColor::error(errs(), ToolName) << IF.takeError();
- exit(1);
- }
- BitcodeModule BM = IF->Mods[0];
- Expected<BitcodeLTOInfo> LI = BM.getLTOInfo();
- Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(Ctx);
- if (!LI || !MOrErr) {
- WithColor::error(errs(), ToolName) << IF.takeError();
- exit(1);
- }
- LTOInfo = std::make_unique<BitcodeLTOInfo>(*LI);
- M = std::move(MOrErr.get());
- }
- void ReducerWorkItem::writeBitcode(raw_ostream &OutStream) const {
- if (LTOInfo && LTOInfo->IsThinLTO && LTOInfo->EnableSplitLTOUnit) {
- PassBuilder PB;
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
- PB.registerModuleAnalyses(MAM);
- PB.registerCGSCCAnalyses(CGAM);
- PB.registerFunctionAnalyses(FAM);
- PB.registerLoopAnalyses(LAM);
- PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
- ModulePassManager MPM;
- MPM.addPass(ThinLTOBitcodeWriterPass(OutStream, nullptr));
- MPM.run(*M, MAM);
- } else {
- std::unique_ptr<ModuleSummaryIndex> Index;
- if (LTOInfo && LTOInfo->HasSummary) {
- ProfileSummaryInfo PSI(*M);
- Index = std::make_unique<ModuleSummaryIndex>(
- buildModuleSummaryIndex(*M, nullptr, &PSI));
- }
- WriteBitcodeToFile(getModule(), OutStream, Index.get());
- }
- }
- std::pair<std::unique_ptr<ReducerWorkItem>, bool>
- llvm::parseReducerWorkItem(StringRef ToolName, StringRef Filename,
- LLVMContext &Ctxt,
- std::unique_ptr<TargetMachine> &TM, bool IsMIR) {
- bool IsBitcode = false;
- Triple TheTriple;
- auto MMM = std::make_unique<ReducerWorkItem>();
- if (IsMIR) {
- initializeTargetInfo();
- auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
- if (std::error_code EC = FileOrErr.getError()) {
- WithColor::error(errs(), ToolName) << EC.message() << '\n';
- return {nullptr, false};
- }
- std::unique_ptr<MIRParser> MParser =
- createMIRParser(std::move(FileOrErr.get()), Ctxt);
- auto SetDataLayout = [&](StringRef DataLayoutTargetTriple,
- StringRef OldDLStr) -> std::optional<std::string> {
- // If we are supposed to override the target triple, do so now.
- std::string IRTargetTriple = DataLayoutTargetTriple.str();
- if (!TargetTriple.empty())
- IRTargetTriple = Triple::normalize(TargetTriple);
- TheTriple = Triple(IRTargetTriple);
- if (TheTriple.getTriple().empty())
- TheTriple.setTriple(sys::getDefaultTargetTriple());
- std::string Error;
- const Target *TheTarget =
- TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);
- if (!TheTarget) {
- WithColor::error(errs(), ToolName) << Error;
- exit(1);
- }
- // Hopefully the MIR parsing doesn't depend on any options.
- TargetOptions Options;
- std::optional<Reloc::Model> RM = codegen::getExplicitRelocModel();
- std::string CPUStr = codegen::getCPUStr();
- std::string FeaturesStr = codegen::getFeaturesStr();
- TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
- TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM,
- codegen::getExplicitCodeModel(), CodeGenOpt::Default));
- assert(TM && "Could not allocate target machine!");
- return TM->createDataLayout().getStringRepresentation();
- };
- std::unique_ptr<Module> M = MParser->parseIRModule(SetDataLayout);
- LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
- MMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM);
- MParser->parseMachineFunctions(*M, *MMM->MMI);
- MMM->M = std::move(M);
- } else {
- SMDiagnostic Err;
- ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
- MemoryBuffer::getFileOrSTDIN(Filename);
- if (std::error_code EC = MB.getError()) {
- WithColor::error(errs(), ToolName)
- << Filename << ": " << EC.message() << "\n";
- return {nullptr, false};
- }
- if (!isBitcode((const unsigned char *)(*MB)->getBufferStart(),
- (const unsigned char *)(*MB)->getBufferEnd())) {
- std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
- if (!Result) {
- Err.print(ToolName.data(), errs());
- return {nullptr, false};
- }
- MMM->M = std::move(Result);
- } else {
- IsBitcode = true;
- MMM->readBitcode(MemoryBufferRef(**MB), Ctxt, ToolName);
- if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit)
- initializeTargetInfo();
- }
- }
- if (MMM->verify(&errs())) {
- WithColor::error(errs(), ToolName)
- << Filename << " - input module is broken!\n";
- return {nullptr, false};
- }
- return {std::move(MMM), IsBitcode};
- }
|