blob: 66b71668820bf00f9ae5d8b67e2dd43685c7e375 [file] [log] [blame]
Tim Northover33b07d62016-07-22 20:03:43 +00001//===-- llvm/CodeGen/GlobalISel/MachineLegalizeHelper.cpp -----------------===//
2//
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//
10/// \file This file implements the MachineLegalizeHelper class to legalize
11/// individual instructions and the LegalizeMachineIR wrapper pass for the
12/// primary legalization.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h"
17#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h"
18#include "llvm/CodeGen/MachineRegisterInfo.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/raw_ostream.h"
21#include "llvm/Target/TargetSubtargetInfo.h"
22
23#include <sstream>
24
25#define DEBUG_TYPE "legalize-mir"
26
27using namespace llvm;
28
29MachineLegalizeHelper::MachineLegalizeHelper(MachineFunction &MF)
30 : MRI(MF.getRegInfo()) {
31 MIRBuilder.setMF(MF);
32}
33
Tim Northover438c77c2016-08-25 17:37:32 +000034MachineLegalizeHelper::LegalizeResult
35MachineLegalizeHelper::legalizeInstrStep(MachineInstr &MI,
36 const MachineLegalizer &Legalizer) {
Tim Northover33b07d62016-07-22 20:03:43 +000037 auto Action = Legalizer.getAction(MI);
Tim Northovera01bece2016-08-23 19:30:42 +000038 switch (std::get<0>(Action)) {
Tim Northover33b07d62016-07-22 20:03:43 +000039 case MachineLegalizer::Legal:
40 return AlreadyLegal;
41 case MachineLegalizer::NarrowScalar:
Tim Northovera01bece2016-08-23 19:30:42 +000042 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover33b07d62016-07-22 20:03:43 +000043 case MachineLegalizer::WidenScalar:
Tim Northovera01bece2016-08-23 19:30:42 +000044 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover33b07d62016-07-22 20:03:43 +000045 case MachineLegalizer::FewerElements:
Tim Northovera01bece2016-08-23 19:30:42 +000046 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover33b07d62016-07-22 20:03:43 +000047 default:
48 return UnableToLegalize;
49 }
50}
51
Tim Northover438c77c2016-08-25 17:37:32 +000052MachineLegalizeHelper::LegalizeResult
53MachineLegalizeHelper::legalizeInstr(MachineInstr &MI,
54 const MachineLegalizer &Legalizer) {
55 std::queue<MachineInstr *> WorkList;
56 MIRBuilder.recordInsertions([&](MachineInstr *MI) { WorkList.push(MI); });
57 WorkList.push(&MI);
58
59 bool Changed = false;
60 LegalizeResult Res;
61 do {
62 Res = legalizeInstrStep(*WorkList.front(), Legalizer);
63 if (Res == UnableToLegalize) {
64 MIRBuilder.stopRecordingInsertions();
65 return UnableToLegalize;
66 }
67 Changed |= Res == Legalized;
68 WorkList.pop();
69 } while (!WorkList.empty());
70
71 MIRBuilder.stopRecordingInsertions();
72
73 return Changed ? Legalized : AlreadyLegal;
74}
75
Tim Northover33b07d62016-07-22 20:03:43 +000076void MachineLegalizeHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
77 SmallVectorImpl<unsigned> &VRegs) {
78 unsigned Size = Ty.getSizeInBits();
Tim Northover6f80b082016-08-19 17:47:05 +000079 SmallVector<uint64_t, 4> Indexes;
Tim Northover26b76f22016-08-19 18:32:14 +000080 SmallVector<LLT, 4> ResTys;
Tim Northover33b07d62016-07-22 20:03:43 +000081 for (int i = 0; i < NumParts; ++i) {
82 VRegs.push_back(MRI.createGenericVirtualRegister(Size));
83 Indexes.push_back(i * Size);
Tim Northover26b76f22016-08-19 18:32:14 +000084 ResTys.push_back(Ty);
Tim Northover33b07d62016-07-22 20:03:43 +000085 }
Tim Northover26b76f22016-08-19 18:32:14 +000086 MIRBuilder.buildExtract(ResTys, VRegs, Indexes,
87 LLT::scalar(Ty.getSizeInBits() * NumParts), Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000088}
89
90MachineLegalizeHelper::LegalizeResult
Tim Northovera01bece2016-08-23 19:30:42 +000091MachineLegalizeHelper::narrowScalar(MachineInstr &MI, unsigned TypeIdx,
92 LLT NarrowTy) {
93 assert(TypeIdx == 0 && "don't know how to handle secondary types yet");
Tim Northover9656f142016-08-04 20:54:13 +000094 switch (MI.getOpcode()) {
95 default:
96 return UnableToLegalize;
97 case TargetOpcode::G_ADD: {
98 // Expand in terms of carry-setting/consuming G_ADDE instructions.
99 unsigned NarrowSize = NarrowTy.getSizeInBits();
100 int NumParts = MI.getType().getSizeInBits() / NarrowSize;
101
102 MIRBuilder.setInstr(MI);
103
Tim Northover91c81732016-08-19 17:17:06 +0000104 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs, Indexes;
Tim Northover9656f142016-08-04 20:54:13 +0000105 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
106 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
107
108 unsigned CarryIn = MRI.createGenericVirtualRegister(1);
109 MIRBuilder.buildConstant(LLT::scalar(1), CarryIn, 0);
110
Tim Northover26b76f22016-08-19 18:32:14 +0000111 SmallVector<LLT, 2> DstTys;
Tim Northover9656f142016-08-04 20:54:13 +0000112 for (int i = 0; i < NumParts; ++i) {
113 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
114 unsigned CarryOut = MRI.createGenericVirtualRegister(1);
115
Tim Northover91c81732016-08-19 17:17:06 +0000116 MIRBuilder.buildUAdde(NarrowTy, DstReg, CarryOut, Src1Regs[i],
117 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000118
Tim Northover26b76f22016-08-19 18:32:14 +0000119 DstTys.push_back(NarrowTy);
Tim Northover9656f142016-08-04 20:54:13 +0000120 DstRegs.push_back(DstReg);
Tim Northover91c81732016-08-19 17:17:06 +0000121 Indexes.push_back(i * NarrowSize);
Tim Northover9656f142016-08-04 20:54:13 +0000122 CarryIn = CarryOut;
123 }
Tim Northover26b76f22016-08-19 18:32:14 +0000124 MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstTys,
125 DstRegs, Indexes);
Tim Northover9656f142016-08-04 20:54:13 +0000126 MI.eraseFromParent();
127 return Legalized;
128 }
129 }
Tim Northover33b07d62016-07-22 20:03:43 +0000130}
131
132MachineLegalizeHelper::LegalizeResult
Tim Northovera01bece2016-08-23 19:30:42 +0000133MachineLegalizeHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx,
134 LLT WideTy) {
Tim Northoverbdf67c92016-08-23 21:01:33 +0000135 LLT Ty = MI.getType();
Tim Northoverea904f92016-08-19 22:40:00 +0000136 unsigned WideSize = WideTy.getSizeInBits();
Tim Northover3c73e362016-08-23 18:20:09 +0000137 MIRBuilder.setInstr(MI);
138
Tim Northover32335812016-08-04 18:35:11 +0000139 switch (MI.getOpcode()) {
140 default:
141 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000142 case TargetOpcode::G_ADD:
143 case TargetOpcode::G_AND:
144 case TargetOpcode::G_MUL:
145 case TargetOpcode::G_OR:
146 case TargetOpcode::G_XOR:
147 case TargetOpcode::G_SUB: {
Tim Northover32335812016-08-04 18:35:11 +0000148 // Perform operation at larger width (any extension is fine here, high bits
149 // don't affect the result) and then truncate the result back to the
150 // original type.
Tim Northover32335812016-08-04 18:35:11 +0000151 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideSize);
152 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideSize);
Tim Northoverbdf67c92016-08-23 21:01:33 +0000153 MIRBuilder.buildAnyExt({WideTy, Ty}, Src1Ext, MI.getOperand(1).getReg());
154 MIRBuilder.buildAnyExt({WideTy, Ty}, Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000155
156 unsigned DstExt = MRI.createGenericVirtualRegister(WideSize);
Tim Northover61c16142016-08-04 21:39:49 +0000157 MIRBuilder.buildInstr(MI.getOpcode(), WideTy)
158 .addDef(DstExt).addUse(Src1Ext).addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000159
Tim Northoverbdf67c92016-08-23 21:01:33 +0000160 MIRBuilder.buildTrunc({Ty, WideTy}, MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000161 MI.eraseFromParent();
162 return Legalized;
163 }
Tim Northover3c73e362016-08-23 18:20:09 +0000164 case TargetOpcode::G_LOAD: {
Tim Northoverbdf67c92016-08-23 21:01:33 +0000165 assert(alignTo(Ty.getSizeInBits(), 8) == WideSize &&
Tim Northover3c73e362016-08-23 18:20:09 +0000166 "illegal to increase number of bytes loaded");
167
168 unsigned DstExt = MRI.createGenericVirtualRegister(WideSize);
169 MIRBuilder.buildLoad(WideTy, MI.getType(1), DstExt,
170 MI.getOperand(1).getReg(), **MI.memoperands_begin());
Tim Northoverbdf67c92016-08-23 21:01:33 +0000171 MIRBuilder.buildTrunc({Ty, WideTy}, MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000172 MI.eraseFromParent();
173 return Legalized;
174 }
175 case TargetOpcode::G_STORE: {
Tim Northoverbdf67c92016-08-23 21:01:33 +0000176 assert(alignTo(Ty.getSizeInBits(), 8) == WideSize &&
Tim Northover3c73e362016-08-23 18:20:09 +0000177 "illegal to increase number of bytes modified by a store");
178
179 unsigned SrcExt = MRI.createGenericVirtualRegister(WideSize);
Tim Northoverbdf67c92016-08-23 21:01:33 +0000180 MIRBuilder.buildAnyExt({WideTy, Ty}, SrcExt, MI.getOperand(0).getReg());
Tim Northover3c73e362016-08-23 18:20:09 +0000181 MIRBuilder.buildStore(WideTy, MI.getType(1), SrcExt,
182 MI.getOperand(1).getReg(), **MI.memoperands_begin());
183 MI.eraseFromParent();
184 return Legalized;
185 }
Tim Northoverea904f92016-08-19 22:40:00 +0000186 case TargetOpcode::G_CONSTANT: {
Tim Northoverea904f92016-08-19 22:40:00 +0000187 unsigned DstExt = MRI.createGenericVirtualRegister(WideSize);
188 MIRBuilder.buildConstant(WideTy, DstExt, MI.getOperand(1).getImm());
Tim Northoverbdf67c92016-08-23 21:01:33 +0000189 MIRBuilder.buildTrunc({Ty, WideTy}, MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000190 MI.eraseFromParent();
191 return Legalized;
192 }
Tim Northovera11be042016-08-19 22:40:08 +0000193 case TargetOpcode::G_FCONSTANT: {
Tim Northovera11be042016-08-19 22:40:08 +0000194 unsigned DstExt = MRI.createGenericVirtualRegister(WideSize);
195 MIRBuilder.buildFConstant(WideTy, DstExt, *MI.getOperand(1).getFPImm());
Tim Northoverbdf67c92016-08-23 21:01:33 +0000196 MIRBuilder.buildFPTrunc({Ty, WideTy}, MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000197 MI.eraseFromParent();
198 return Legalized;
199 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000200 case TargetOpcode::G_BRCOND: {
201 unsigned TstExt = MRI.createGenericVirtualRegister(WideSize);
Tim Northoverbdf67c92016-08-23 21:01:33 +0000202 MIRBuilder.buildAnyExt({WideTy, Ty}, TstExt, MI.getOperand(0).getReg());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000203 MIRBuilder.buildBrCond(WideTy, TstExt, *MI.getOperand(1).getMBB());
204 MI.eraseFromParent();
205 return Legalized;
206 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000207 case TargetOpcode::G_ICMP: {
208 if (TypeIdx == 0) {
209 unsigned TstExt = MRI.createGenericVirtualRegister(WideSize);
210 MIRBuilder.buildICmp(
211 {WideTy, MI.getType(1)},
212 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
213 TstExt, MI.getOperand(2).getReg(), MI.getOperand(3).getReg());
Tim Northoverbdf67c92016-08-23 21:01:33 +0000214 MIRBuilder.buildTrunc({Ty, WideTy}, MI.getOperand(0).getReg(), TstExt);
Tim Northover6cd4b232016-08-23 21:01:26 +0000215 MI.eraseFromParent();
216 return Legalized;
217 } else {
218 bool IsSigned = CmpInst::isSigned(
219 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
220 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideSize);
221 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideSize);
222 if (IsSigned) {
223 MIRBuilder.buildSExt({WideTy, MI.getType(1)}, Op0Ext,
224 MI.getOperand(2).getReg());
225 MIRBuilder.buildSExt({WideTy, MI.getType(1)}, Op1Ext,
226 MI.getOperand(3).getReg());
227 } else {
228 MIRBuilder.buildZExt({WideTy, MI.getType(1)}, Op0Ext,
229 MI.getOperand(2).getReg());
230 MIRBuilder.buildZExt({WideTy, MI.getType(1)}, Op1Ext,
231 MI.getOperand(3).getReg());
232 }
233 MIRBuilder.buildICmp(
234 {MI.getType(0), WideTy},
235 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
236 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
237 MI.eraseFromParent();
238 return Legalized;
239 }
240 }
Tim Northover32335812016-08-04 18:35:11 +0000241 }
Tim Northover33b07d62016-07-22 20:03:43 +0000242}
243
244MachineLegalizeHelper::LegalizeResult
Tim Northovera01bece2016-08-23 19:30:42 +0000245MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
246 LLT NarrowTy) {
247 assert(TypeIdx == 0 && "don't know how to handle secondary types yet");
Tim Northover33b07d62016-07-22 20:03:43 +0000248 switch (MI.getOpcode()) {
249 default:
250 return UnableToLegalize;
251 case TargetOpcode::G_ADD: {
252 unsigned NarrowSize = NarrowTy.getSizeInBits();
253 int NumParts = MI.getType().getSizeInBits() / NarrowSize;
254
255 MIRBuilder.setInstr(MI);
256
Tim Northover91c81732016-08-19 17:17:06 +0000257 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs, Indexes;
Tim Northover33b07d62016-07-22 20:03:43 +0000258 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
259 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
260
Tim Northover26b76f22016-08-19 18:32:14 +0000261 SmallVector<LLT, 2> DstTys;
Tim Northover33b07d62016-07-22 20:03:43 +0000262 for (int i = 0; i < NumParts; ++i) {
263 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
264 MIRBuilder.buildAdd(NarrowTy, DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover26b76f22016-08-19 18:32:14 +0000265 DstTys.push_back(NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +0000266 DstRegs.push_back(DstReg);
Tim Northover91c81732016-08-19 17:17:06 +0000267 Indexes.push_back(i * NarrowSize);
Tim Northover33b07d62016-07-22 20:03:43 +0000268 }
269
Tim Northover26b76f22016-08-19 18:32:14 +0000270 MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstTys,
271 DstRegs, Indexes);
Tim Northover33b07d62016-07-22 20:03:43 +0000272 MI.eraseFromParent();
273 return Legalized;
274 }
275 }
276}