blob: 59f34d730d00856ecc663b9ce52b390e23dec458 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Tim Northover69fa84a2016-10-14 22:18:18 +000010/// \file This file implements the LegalizerHelper class to legalize individual
11/// instructions and the LegalizePass wrapper pass for the primary
Tim Northover33b07d62016-07-22 20:03:43 +000012/// legalization.
13//
14//===----------------------------------------------------------------------===//
15
Tim Northover69fa84a2016-10-14 22:18:18 +000016#include "llvm/CodeGen/GlobalISel/Legalizer.h"
Aditya Nandakumarc6615f52017-08-30 19:32:59 +000017#include "llvm/ADT/SetVector.h"
18#include "llvm/CodeGen/GlobalISel/LegalizerCombiner.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000019#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Ahmed Bougachaae9dade2017-02-23 21:05:42 +000020#include "llvm/CodeGen/GlobalISel/Utils.h"
21#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
Quentin Colombet5e60bcd2016-08-27 02:38:21 +000022#include "llvm/CodeGen/MachineRegisterInfo.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000023#include "llvm/CodeGen/TargetInstrInfo.h"
Quentin Colombet5e60bcd2016-08-27 02:38:21 +000024#include "llvm/CodeGen/TargetPassConfig.h"
Tim Northover33b07d62016-07-22 20:03:43 +000025#include "llvm/Support/Debug.h"
26#include "llvm/Target/TargetSubtargetInfo.h"
27
Daniel Sanders5377fb32017-04-20 15:46:12 +000028#include <iterator>
29
Tim Northover69fa84a2016-10-14 22:18:18 +000030#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000031
32using namespace llvm;
33
Tim Northover69fa84a2016-10-14 22:18:18 +000034char Legalizer::ID = 0;
35INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
Quentin Colombet5e60bcd2016-08-27 02:38:21 +000036 "Legalize the Machine IR a function's Machine IR", false,
37 false)
38INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
Tim Northover69fa84a2016-10-14 22:18:18 +000039INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
Quentin Colombet5e60bcd2016-08-27 02:38:21 +000040 "Legalize the Machine IR a function's Machine IR", false,
41 false)
Tim Northover33b07d62016-07-22 20:03:43 +000042
Tim Northover69fa84a2016-10-14 22:18:18 +000043Legalizer::Legalizer() : MachineFunctionPass(ID) {
44 initializeLegalizerPass(*PassRegistry::getPassRegistry());
Tim Northover33b07d62016-07-22 20:03:43 +000045}
46
Tim Northover69fa84a2016-10-14 22:18:18 +000047void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +000048 AU.addRequired<TargetPassConfig>();
49 MachineFunctionPass::getAnalysisUsage(AU);
50}
51
Tim Northover69fa84a2016-10-14 22:18:18 +000052void Legalizer::init(MachineFunction &MF) {
Tim Northover33b07d62016-07-22 20:03:43 +000053}
54
Tim Northover69fa84a2016-10-14 22:18:18 +000055bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
Quentin Colombet60495242016-08-27 00:18:24 +000056 // If the ISel pipeline failed, do not bother running that pass.
57 if (MF.getProperties().hasProperty(
58 MachineFunctionProperties::Property::FailedISel))
59 return false;
Tim Northover33b07d62016-07-22 20:03:43 +000060 DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
61 init(MF);
Quentin Colombet5e60bcd2016-08-27 02:38:21 +000062 const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
Ahmed Bougachaae9dade2017-02-23 21:05:42 +000063 MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
Tim Northover69fa84a2016-10-14 22:18:18 +000064 LegalizerHelper Helper(MF);
Tim Northover33b07d62016-07-22 20:03:43 +000065
66 // FIXME: an instruction may need more than one pass before it is legal. For
67 // example on most architectures <3 x i3> is doubly-illegal. It would
68 // typically proceed along a path like: <3 x i3> -> <3 x i8> -> <8 x i8>. We
69 // probably want a worklist of instructions rather than naive iterate until
70 // convergence for performance reasons.
71 bool Changed = false;
72 MachineBasicBlock::iterator NextMI;
Quentin Colombetd58265a2017-10-13 21:16:14 +000073 using VecType = SmallSetVector<MachineInstr *, 8>;
Quentin Colombet86220482017-10-13 21:16:05 +000074 VecType WorkList;
75 VecType CombineList;
Daniel Sanders5377fb32017-04-20 15:46:12 +000076 for (auto &MBB : MF) {
Tim Northover33b07d62016-07-22 20:03:43 +000077 for (auto MI = MBB.begin(); MI != MBB.end(); MI = NextMI) {
78 // Get the next Instruction before we try to legalize, because there's a
79 // good chance MI will be deleted.
80 NextMI = std::next(MI);
Ahmed Bougachafaf8e9f2016-08-02 11:41:09 +000081
82 // Only legalize pre-isel generic instructions: others don't have types
83 // and are assumed to be legal.
84 if (!isPreISelGenericOpcode(MI->getOpcode()))
85 continue;
Daniel Sanders5377fb32017-04-20 15:46:12 +000086 unsigned NumNewInsns = 0;
Quentin Colombet86220482017-10-13 21:16:05 +000087 WorkList.clear();
88 CombineList.clear();
Daniel Sanders5377fb32017-04-20 15:46:12 +000089 Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
Aditya Nandakumar21d8d312017-05-04 22:00:42 +000090 // Only legalize pre-isel generic instructions.
91 // Legalization process could generate Target specific pseudo
92 // instructions with generic types. Don't record them
93 if (isPreISelGenericOpcode(MI->getOpcode())) {
94 ++NumNewInsns;
Aditya Nandakumarc6615f52017-08-30 19:32:59 +000095 WorkList.insert(MI);
96 CombineList.insert(MI);
Aditya Nandakumar21d8d312017-05-04 22:00:42 +000097 }
Daniel Sanders5377fb32017-04-20 15:46:12 +000098 });
Aditya Nandakumarc6615f52017-08-30 19:32:59 +000099 WorkList.insert(&*MI);
Aditya Nandakumard2a954d2017-10-25 18:49:18 +0000100 LegalizerCombiner C(Helper.MIRBuilder, MF.getRegInfo(),
101 Helper.getLegalizerInfo());
Daniel Sanders5377fb32017-04-20 15:46:12 +0000102 bool Changed = false;
Aditya Nandakumareb80a512017-04-07 21:49:30 +0000103 LegalizerHelper::LegalizeResult Res;
Aditya Nandakumareb80a512017-04-07 21:49:30 +0000104 do {
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000105 assert(!WorkList.empty() && "Expecting illegal ops");
106 while (!WorkList.empty()) {
107 NumNewInsns = 0;
108 MachineInstr *CurrInst = WorkList.pop_back_val();
109 Res = Helper.legalizeInstrStep(*CurrInst);
110 // Error out if we couldn't legalize this instruction. We may want to
111 // fall back to DAG ISel instead in the future.
Aditya Nandakumareb80a512017-04-07 21:49:30 +0000112 if (Res == LegalizerHelper::UnableToLegalize) {
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000113 Helper.MIRBuilder.stopRecordingInsertions();
114 if (Res == LegalizerHelper::UnableToLegalize) {
115 reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
116 "unable to legalize instruction", *CurrInst);
117 return false;
118 }
Aditya Nandakumareb80a512017-04-07 21:49:30 +0000119 }
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000120 Changed |= Res == LegalizerHelper::Legalized;
121 // If CurrInst was legalized, there's a good chance that it might have
122 // been erased. So remove it from the Combine List.
123 if (Res == LegalizerHelper::Legalized)
124 CombineList.remove(CurrInst);
Daniel Sanders5377fb32017-04-20 15:46:12 +0000125
126#ifndef NDEBUG
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000127 if (NumNewInsns)
128 for (unsigned I = WorkList.size() - NumNewInsns,
129 E = WorkList.size();
130 I != E; ++I)
131 DEBUG(dbgs() << ".. .. New MI: " << *WorkList[I];);
Daniel Sanders5377fb32017-04-20 15:46:12 +0000132#endif
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000133 }
134 // Do the combines.
135 while (!CombineList.empty()) {
136 NumNewInsns = 0;
137 MachineInstr *CurrInst = CombineList.pop_back_val();
138 SmallVector<MachineInstr *, 4> DeadInstructions;
139 Changed |= C.tryCombineInstruction(*CurrInst, DeadInstructions);
140 for (auto *DeadMI : DeadInstructions) {
141 DEBUG(dbgs() << ".. Erasing Dead Instruction " << *DeadMI);
142 CombineList.remove(DeadMI);
143 WorkList.remove(DeadMI);
144 DeadMI->eraseFromParent();
145 }
146#ifndef NDEBUG
147 if (NumNewInsns)
148 for (unsigned I = CombineList.size() - NumNewInsns,
149 E = CombineList.size();
150 I != E; ++I)
151 DEBUG(dbgs() << ".. .. Combine New MI: " << *CombineList[I];);
152#endif
153 }
154 } while (!WorkList.empty());
Tim Northover33b07d62016-07-22 20:03:43 +0000155
Aditya Nandakumareb80a512017-04-07 21:49:30 +0000156 Helper.MIRBuilder.stopRecordingInsertions();
Tim Northover33b07d62016-07-22 20:03:43 +0000157 }
Daniel Sanders5377fb32017-04-20 15:46:12 +0000158 }
Tim Northover991b12b2016-08-30 20:51:25 +0000159
Tim Northover991b12b2016-08-30 20:51:25 +0000160 MachineRegisterInfo &MRI = MF.getRegInfo();
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000161 MachineIRBuilder MIRBuilder(MF);
Aditya Nandakumard2a954d2017-10-25 18:49:18 +0000162 LegalizerCombiner C(MIRBuilder, MRI, Helper.getLegalizerInfo());
Tim Northover991b12b2016-08-30 20:51:25 +0000163 for (auto &MBB : MF) {
164 for (auto MI = MBB.begin(); MI != MBB.end(); MI = NextMI) {
165 // Get the next Instruction before we try to legalize, because there's a
166 // good chance MI will be deleted.
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000167 // TOOD: Perhaps move this to a combiner pass later?.
Tim Northover991b12b2016-08-30 20:51:25 +0000168 NextMI = std::next(MI);
Aditya Nandakumarc6615f52017-08-30 19:32:59 +0000169 SmallVector<MachineInstr *, 4> DeadInsts;
170 Changed |= C.tryCombineMerges(*MI, DeadInsts);
171 for (auto *DeadMI : DeadInsts)
172 DeadMI->eraseFromParent();
Tim Northover991b12b2016-08-30 20:51:25 +0000173 }
174 }
175
Tim Northover33b07d62016-07-22 20:03:43 +0000176 return Changed;
177}