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 "llvm/CodeGen/MIRParser/MIRParser.h"
11 #include "llvm/CodeGen/MIRPrinter.h"
12 #include "llvm/CodeGen/MachineDominators.h"
13 #include "llvm/CodeGen/MachineFunction.h"
14 #include "llvm/CodeGen/MachineFunctionPass.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/TargetInstrInfo.h"
17 #include "llvm/IR/Verifier.h"
18 #include "llvm/IRReader/IRReader.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "llvm/Target/TargetMachine.h"
21 #include "llvm/Transforms/Utils/Cloning.h"
22 
23 static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF) {
24   auto DstMF = std::make_unique<MachineFunction>(
25       SrcMF->getFunction(), SrcMF->getTarget(), SrcMF->getSubtarget(),
26       SrcMF->getFunctionNumber(), SrcMF->getMMI());
27   DenseMap<MachineBasicBlock *, MachineBasicBlock *> Src2DstMBB;
28   DenseMap<Register, Register> Src2DstReg;
29 
30   auto *SrcMRI = &SrcMF->getRegInfo();
31   auto *DstMRI = &DstMF->getRegInfo();
32 
33   // Create vregs.
34   for (auto &SrcMBB : *SrcMF) {
35     for (auto &SrcMI : SrcMBB) {
36       for (unsigned I = 0, E = SrcMI.getNumOperands(); I < E; ++I) {
37         auto &DMO = SrcMI.getOperand(I);
38         if (!DMO.isReg() || !DMO.isDef())
39           continue;
40         Register SrcReg = DMO.getReg();
41         if (Register::isPhysicalRegister(SrcReg))
42           continue;
43         auto SrcRC = SrcMRI->getRegClass(SrcReg);
44         auto DstReg = DstMRI->createVirtualRegister(SrcRC);
45         Src2DstReg[SrcReg] = DstReg;
46       }
47     }
48   }
49 
50   // Clone blocks.
51   for (auto &SrcMBB : *SrcMF)
52     Src2DstMBB[&SrcMBB] = DstMF->CreateMachineBasicBlock();
53   // Link blocks.
54   for (auto &SrcMBB : *SrcMF) {
55     auto *DstMBB = Src2DstMBB[&SrcMBB];
56     DstMF->push_back(DstMBB);
57     for (auto It = SrcMBB.succ_begin(), IterEnd = SrcMBB.succ_end();
58          It != IterEnd; ++It) {
59       auto *SrcSuccMBB = *It;
60       auto *DstSuccMBB = Src2DstMBB[SrcSuccMBB];
61       DstMBB->addSuccessor(DstSuccMBB);
62     }
63     for (auto &LI : SrcMBB.liveins())
64       DstMBB->addLiveIn(LI);
65   }
66   // Clone instructions.
67   for (auto &SrcMBB : *SrcMF) {
68     auto *DstMBB = Src2DstMBB[&SrcMBB];
69     for (auto &SrcMI : SrcMBB) {
70       const auto &MCID =
71           DstMF->getSubtarget().getInstrInfo()->get(SrcMI.getOpcode());
72       auto *DstMI = DstMF->CreateMachineInstr(MCID, SrcMI.getDebugLoc(),
73                                               /*NoImplicit=*/true);
74       DstMBB->push_back(DstMI);
75       for (auto &SrcMO : SrcMI.operands()) {
76         MachineOperand DstMO(SrcMO);
77         DstMO.clearParent();
78         // Update vreg.
79         if (DstMO.isReg() && Src2DstReg.count(DstMO.getReg())) {
80           DstMO.setReg(Src2DstReg[DstMO.getReg()]);
81         }
82         // Update MBB.
83         if (DstMO.isMBB()) {
84           DstMO.setMBB(Src2DstMBB[DstMO.getMBB()]);
85         }
86         DstMI->addOperand(DstMO);
87       }
88       DstMI->setMemRefs(*DstMF, SrcMI.memoperands());
89     }
90   }
91 
92   DstMF->verify(nullptr, "", /*AbortOnError=*/true);
93   return DstMF;
94 }
95 
96 std::unique_ptr<ReducerWorkItem> parseReducerWorkItem(StringRef Filename,
97                                                       LLVMContext &Ctxt,
98                                                       MachineModuleInfo *MMI) {
99   auto MMM = std::make_unique<ReducerWorkItem>();
100   if (MMI) {
101     auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
102     std::unique_ptr<MIRParser> MParser =
103         createMIRParser(std::move(FileOrErr.get()), Ctxt);
104 
105     auto SetDataLayout =
106         [&](StringRef DataLayoutTargetTriple) -> Optional<std::string> {
107       return MMI->getTarget().createDataLayout().getStringRepresentation();
108     };
109 
110     std::unique_ptr<Module> M = MParser->parseIRModule(SetDataLayout);
111     MParser->parseMachineFunctions(*M, *MMI);
112     MachineFunction *MF = nullptr;
113     for (auto &F : *M) {
114       if (auto *MF4F = MMI->getMachineFunction(F)) {
115         // XXX: Maybe it would not be a lot of effort to handle multiple MFs by
116         // simply storing them in a ReducerWorkItem::SmallVector or similar. The
117         // single MF use-case seems a lot more common though so that will do for
118         // now.
119         assert(!MF && "Only single MF supported!");
120         MF = MF4F;
121       }
122     }
123     assert(MF && "No MF found!");
124 
125     MMM->M = std::move(M);
126     MMM->MF = cloneMF(MF);
127   } else {
128     SMDiagnostic Err;
129     std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
130     if (!Result) {
131       Err.print("llvm-reduce", errs());
132       return std::unique_ptr<ReducerWorkItem>();
133     }
134     MMM->M = std::move(Result);
135   }
136   if (verifyReducerWorkItem(*MMM, &errs())) {
137     errs() << "Error: " << Filename << " - input module is broken!\n";
138     return std::unique_ptr<ReducerWorkItem>();
139   }
140   return MMM;
141 }
142 
143 std::unique_ptr<ReducerWorkItem>
144 cloneReducerWorkItem(const ReducerWorkItem &MMM) {
145   auto CloneMMM = std::make_unique<ReducerWorkItem>();
146   if (MMM.MF) {
147     // Note that we cannot clone the Module as then we would need a way to
148     // updated the cloned MachineFunction's IR references.
149     // XXX: Actually have a look at
150     // std::unique_ptr<Module> CloneModule(const Module &M, ValueToValueMapTy
151     // &VMap);
152     CloneMMM->M = MMM.M;
153     CloneMMM->MF = cloneMF(MMM.MF.get());
154   } else {
155     CloneMMM->M = CloneModule(*MMM.M);
156   }
157   return CloneMMM;
158 }
159 
160 bool verifyReducerWorkItem(const ReducerWorkItem &MMM, raw_fd_ostream *OS) {
161   if (verifyModule(*MMM.M, OS))
162     return true;
163   if (MMM.MF && !MMM.MF->verify(nullptr, "", /*AbortOnError=*/false))
164     return true;
165   return false;
166 }
167 
168 void ReducerWorkItem::print(raw_ostream &ROS, void *p) const {
169   if (MF) {
170     printMIR(ROS, *M);
171     printMIR(ROS, *MF);
172   } else {
173     M->print(ROS, /*AssemblyAnnotationWriter=*/nullptr,
174              /*ShouldPreserveUseListOrder=*/true);
175   }
176 }
177