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