blob: 6bb64e068ec2c528f7523483f063d4d0482753d6 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.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
Tim Northover33b07d62016-07-22 20:03:43 +000011/// individual instructions and the LegalizeMachineIR wrapper pass for the
12/// primary legalization.
13//
14//===----------------------------------------------------------------------===//
15
Tim Northover69fa84a2016-10-14 22:18:18 +000016#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000017#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000018#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
20#include "llvm/Support/Debug.h"
21#include "llvm/Support/raw_ostream.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000022#include "llvm/Target/TargetLowering.h"
Tim Northover33b07d62016-07-22 20:03:43 +000023#include "llvm/Target/TargetSubtargetInfo.h"
24
25#include <sstream>
26
27#define DEBUG_TYPE "legalize-mir"
28
29using namespace llvm;
30
Tim Northover69fa84a2016-10-14 22:18:18 +000031LegalizerHelper::LegalizerHelper(MachineFunction &MF)
Tim Northover33b07d62016-07-22 20:03:43 +000032 : MRI(MF.getRegInfo()) {
33 MIRBuilder.setMF(MF);
34}
35
Tim Northover69fa84a2016-10-14 22:18:18 +000036LegalizerHelper::LegalizeResult
37LegalizerHelper::legalizeInstrStep(MachineInstr &MI,
38 const LegalizerInfo &LegalizerInfo) {
39 auto Action = LegalizerInfo.getAction(MI, MRI);
Tim Northovera01bece2016-08-23 19:30:42 +000040 switch (std::get<0>(Action)) {
Tim Northover69fa84a2016-10-14 22:18:18 +000041 case LegalizerInfo::Legal:
Tim Northover33b07d62016-07-22 20:03:43 +000042 return AlreadyLegal;
Tim Northover69fa84a2016-10-14 22:18:18 +000043 case LegalizerInfo::Libcall:
Tim Northoveredb3c8c2016-08-29 19:07:16 +000044 return libcall(MI);
Tim Northover69fa84a2016-10-14 22:18:18 +000045 case LegalizerInfo::NarrowScalar:
Tim Northovera01bece2016-08-23 19:30:42 +000046 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000047 case LegalizerInfo::WidenScalar:
Tim Northovera01bece2016-08-23 19:30:42 +000048 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000049 case LegalizerInfo::Lower:
Tim Northovercecee562016-08-26 17:46:13 +000050 return lower(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000051 case LegalizerInfo::FewerElements:
Tim Northovera01bece2016-08-23 19:30:42 +000052 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover91366172017-02-15 23:22:50 +000053 case LegalizerInfo::Custom:
54 return LegalizerInfo.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
55 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000056 default:
57 return UnableToLegalize;
58 }
59}
60
Tim Northover69fa84a2016-10-14 22:18:18 +000061LegalizerHelper::LegalizeResult
62LegalizerHelper::legalizeInstr(MachineInstr &MI,
63 const LegalizerInfo &LegalizerInfo) {
Tim Northoverac5148e2016-08-29 19:27:20 +000064 SmallVector<MachineInstr *, 4> WorkList;
65 MIRBuilder.recordInsertions(
66 [&](MachineInstr *MI) { WorkList.push_back(MI); });
67 WorkList.push_back(&MI);
Tim Northover438c77c2016-08-25 17:37:32 +000068
69 bool Changed = false;
70 LegalizeResult Res;
Tim Northoverac5148e2016-08-29 19:27:20 +000071 unsigned Idx = 0;
Tim Northover438c77c2016-08-25 17:37:32 +000072 do {
Tim Northover69fa84a2016-10-14 22:18:18 +000073 Res = legalizeInstrStep(*WorkList[Idx], LegalizerInfo);
Tim Northover438c77c2016-08-25 17:37:32 +000074 if (Res == UnableToLegalize) {
75 MIRBuilder.stopRecordingInsertions();
76 return UnableToLegalize;
77 }
78 Changed |= Res == Legalized;
Tim Northoverac5148e2016-08-29 19:27:20 +000079 ++Idx;
80 } while (Idx < WorkList.size());
Tim Northover438c77c2016-08-25 17:37:32 +000081
82 MIRBuilder.stopRecordingInsertions();
83
84 return Changed ? Legalized : AlreadyLegal;
85}
86
Tim Northover69fa84a2016-10-14 22:18:18 +000087void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
88 SmallVectorImpl<unsigned> &VRegs) {
Tim Northover33b07d62016-07-22 20:03:43 +000089 unsigned Size = Ty.getSizeInBits();
Tim Northover6f80b082016-08-19 17:47:05 +000090 SmallVector<uint64_t, 4> Indexes;
Tim Northover33b07d62016-07-22 20:03:43 +000091 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +000092 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northover33b07d62016-07-22 20:03:43 +000093 Indexes.push_back(i * Size);
94 }
Tim Northover0f140c72016-09-09 11:46:34 +000095 MIRBuilder.buildExtract(VRegs, Indexes, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000096}
97
Tim Northovere0418412017-02-08 23:23:39 +000098static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
99 switch (Opcode) {
100 case TargetOpcode::G_FREM:
101 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
102 case TargetOpcode::G_FPOW:
103 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
104 }
105 llvm_unreachable("Unknown libcall function");
106}
107
Tim Northover69fa84a2016-10-14 22:18:18 +0000108LegalizerHelper::LegalizeResult
109LegalizerHelper::libcall(MachineInstr &MI) {
Tim Northover0f140c72016-09-09 11:46:34 +0000110 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
111 unsigned Size = Ty.getSizeInBits();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000112 MIRBuilder.setInstr(MI);
113
114 switch (MI.getOpcode()) {
115 default:
116 return UnableToLegalize;
Tim Northovere0418412017-02-08 23:23:39 +0000117 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000118 case TargetOpcode::G_FREM: {
Tim Northover11a23542016-08-31 21:24:02 +0000119 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
120 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000121 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
122 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Tim Northovere0418412017-02-08 23:23:39 +0000123 const char *Name = TLI.getLibcallName(getRTLibDesc(MI.getOpcode(), Size));
Tim Northover9a467182016-09-21 12:57:45 +0000124 CLI.lowerCall(
125 MIRBuilder, MachineOperand::CreateES(Name),
126 {MI.getOperand(0).getReg(), Ty},
127 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000128 MI.eraseFromParent();
129 return Legalized;
130 }
131 }
132}
133
Tim Northover0e6afbd2017-02-06 21:56:47 +0000134void LegalizerHelper::findInsertionsForRange(
135 int64_t DstStart, int64_t DstEnd, MachineInstr::mop_iterator &CurOp,
136 MachineInstr::mop_iterator &EndOp, MachineInstr &MI) {
137 while (CurOp != MI.operands_end() && std::next(CurOp)->getImm() < DstStart)
138 CurOp += 2;
139
140 EndOp = CurOp;
141 while (EndOp != MI.operands_end() && std::next(EndOp)->getImm() < DstEnd)
142 EndOp += 2;
143}
144
Tim Northover69fa84a2016-10-14 22:18:18 +0000145LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
146 unsigned TypeIdx,
147 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000148 // FIXME: Don't know how to handle secondary types yet.
149 if (TypeIdx != 0)
150 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000151
152 MIRBuilder.setInstr(MI);
153
Tim Northover9656f142016-08-04 20:54:13 +0000154 switch (MI.getOpcode()) {
155 default:
156 return UnableToLegalize;
157 case TargetOpcode::G_ADD: {
158 // Expand in terms of carry-setting/consuming G_ADDE instructions.
159 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000160 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
161 NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000162
Tim Northoverb18ea162016-09-20 15:20:36 +0000163 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
164 SmallVector<uint64_t, 2> Indexes;
Tim Northover9656f142016-08-04 20:54:13 +0000165 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
166 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
167
Tim Northover0f140c72016-09-09 11:46:34 +0000168 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
169 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000170
171 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000172 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
173 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000174
Tim Northover0f140c72016-09-09 11:46:34 +0000175 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000176 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000177
178 DstRegs.push_back(DstReg);
Tim Northover91c81732016-08-19 17:17:06 +0000179 Indexes.push_back(i * NarrowSize);
Tim Northover9656f142016-08-04 20:54:13 +0000180 CarryIn = CarryOut;
181 }
Tim Northover0f140c72016-09-09 11:46:34 +0000182 unsigned DstReg = MI.getOperand(0).getReg();
183 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
Tim Northover9656f142016-08-04 20:54:13 +0000184 MI.eraseFromParent();
185 return Legalized;
186 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000187 case TargetOpcode::G_INSERT: {
188 if (TypeIdx != 0)
189 return UnableToLegalize;
190
191 unsigned NarrowSize = NarrowTy.getSizeInBits();
192 int NumParts =
193 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
194
195 SmallVector<unsigned, 2> SrcRegs, DstRegs;
196 SmallVector<uint64_t, 2> Indexes;
197 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
198
199 MachineInstr::mop_iterator CurOp = MI.operands_begin() + 2, EndOp;
200 for (int i = 0; i < NumParts; ++i) {
201 unsigned DstStart = i * NarrowSize;
202 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
203 Indexes.push_back(DstStart);
204
205 findInsertionsForRange(DstStart, DstStart + NarrowSize, CurOp, EndOp, MI);
206
207 if (CurOp == EndOp) {
208 // No part of the insert affects this subregister, forward the original.
209 DstRegs.push_back(SrcRegs[i]);
210 continue;
211 } else if (MRI.getType(CurOp->getReg()) == NarrowTy &&
212 std::next(CurOp)->getImm() == DstStart) {
213 // The entire subregister is defined by this insert, forward the new
214 // value.
215 DstRegs.push_back(CurOp->getReg());
216 continue;
217 }
218
219 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_INSERT)
220 .addDef(DstReg)
221 .addUse(SrcRegs[i]);
222
223 for (; CurOp != EndOp; CurOp += 2) {
224 unsigned Reg = CurOp->getReg();
225 uint64_t Offset = std::next(CurOp)->getImm() - DstStart;
226
227 // Make sure we don't have a cross-register insert.
228 if (Offset + MRI.getType(Reg).getSizeInBits() > NarrowSize) {
229 // FIXME: we should handle this case, though it's unlikely to be
230 // common given ABI-related layout restrictions.
231 return UnableToLegalize;
232 }
233
234 MIB.addUse(Reg);
235 MIB.addImm(Offset);
236 }
237
238 DstRegs.push_back(DstReg);
239 }
240
241 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
242 MIRBuilder.buildSequence(MI.getOperand(0).getReg(), DstRegs, Indexes);
243 MI.eraseFromParent();
244 return Legalized;
245 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000246 case TargetOpcode::G_LOAD: {
247 unsigned NarrowSize = NarrowTy.getSizeInBits();
248 int NumParts =
249 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
250 LLT NarrowPtrTy = LLT::pointer(
251 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
252
253 SmallVector<unsigned, 2> DstRegs;
254 SmallVector<uint64_t, 2> Indexes;
255 for (int i = 0; i < NumParts; ++i) {
256 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
257 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
258 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
259
260 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
261 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000262 // TODO: This is conservatively correct, but we probably want to split the
263 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000264 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
265
266 DstRegs.push_back(DstReg);
267 Indexes.push_back(i * NarrowSize);
268 }
269 unsigned DstReg = MI.getOperand(0).getReg();
270 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
271 MI.eraseFromParent();
272 return Legalized;
273 }
Justin Bognerfde01042017-01-18 17:29:54 +0000274 case TargetOpcode::G_STORE: {
275 unsigned NarrowSize = NarrowTy.getSizeInBits();
276 int NumParts =
277 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
278 LLT NarrowPtrTy = LLT::pointer(
279 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
280
281 SmallVector<unsigned, 2> SrcRegs;
282 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
283
284 for (int i = 0; i < NumParts; ++i) {
285 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
286 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
287 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
288 MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000289 // TODO: This is conservatively correct, but we probably want to split the
290 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000291 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
292 }
293 MI.eraseFromParent();
294 return Legalized;
295 }
Tim Northover9656f142016-08-04 20:54:13 +0000296 }
Tim Northover33b07d62016-07-22 20:03:43 +0000297}
298
Tim Northover69fa84a2016-10-14 22:18:18 +0000299LegalizerHelper::LegalizeResult
300LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000301 MIRBuilder.setInstr(MI);
302
Tim Northover32335812016-08-04 18:35:11 +0000303 switch (MI.getOpcode()) {
304 default:
305 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000306 case TargetOpcode::G_ADD:
307 case TargetOpcode::G_AND:
308 case TargetOpcode::G_MUL:
309 case TargetOpcode::G_OR:
310 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000311 case TargetOpcode::G_SUB:
312 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000313 // Perform operation at larger width (any extension is fine here, high bits
314 // don't affect the result) and then truncate the result back to the
315 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000316 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
317 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
318 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
319 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000320
Tim Northover0f140c72016-09-09 11:46:34 +0000321 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
322 MIRBuilder.buildInstr(MI.getOpcode())
323 .addDef(DstExt)
324 .addUse(Src1Ext)
325 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000326
Tim Northover0f140c72016-09-09 11:46:34 +0000327 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000328 MI.eraseFromParent();
329 return Legalized;
330 }
Tim Northover7a753d92016-08-26 17:46:06 +0000331 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000332 case TargetOpcode::G_UDIV:
333 case TargetOpcode::G_ASHR:
334 case TargetOpcode::G_LSHR: {
335 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
336 MI.getOpcode() == TargetOpcode::G_ASHR
337 ? TargetOpcode::G_SEXT
338 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000339
Tim Northover0f140c72016-09-09 11:46:34 +0000340 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
341 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
342 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000343
Tim Northover0f140c72016-09-09 11:46:34 +0000344 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
345 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
346 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000347
Tim Northover0f140c72016-09-09 11:46:34 +0000348 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
349 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000350 .addDef(ResExt)
351 .addUse(LHSExt)
352 .addUse(RHSExt);
353
Tim Northover0f140c72016-09-09 11:46:34 +0000354 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000355 MI.eraseFromParent();
356 return Legalized;
357 }
Tim Northover868332d2017-02-06 23:41:27 +0000358 case TargetOpcode::G_SELECT: {
359 if (TypeIdx != 0)
360 return UnableToLegalize;
361
362 // Perform operation at larger width (any extension is fine here, high bits
363 // don't affect the result) and then truncate the result back to the
364 // original type.
365 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
366 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
367 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
368 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
369
370 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
371 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
372 .addDef(DstExt)
373 .addReg(MI.getOperand(1).getReg())
374 .addUse(Src1Ext)
375 .addUse(Src2Ext);
376
377 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
378 MI.eraseFromParent();
379 return Legalized;
380 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000381 case TargetOpcode::G_FPTOSI:
382 case TargetOpcode::G_FPTOUI: {
383 if (TypeIdx != 0)
384 return UnableToLegalize;
385
386 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
387 MIRBuilder.buildInstr(MI.getOpcode())
388 .addDef(DstExt)
389 .addUse(MI.getOperand(1).getReg());
390
391 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
392 MI.eraseFromParent();
393 return Legalized;
394 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000395 case TargetOpcode::G_SITOFP:
396 case TargetOpcode::G_UITOFP: {
397 if (TypeIdx != 1)
398 return UnableToLegalize;
399
400 unsigned Src = MI.getOperand(1).getReg();
401 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
402
403 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
404 MIRBuilder.buildSExt(SrcExt, Src);
405 } else {
406 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
407 MIRBuilder.buildZExt(SrcExt, Src);
408 }
409
410 MIRBuilder.buildInstr(MI.getOpcode())
411 .addDef(MI.getOperand(0).getReg())
412 .addUse(SrcExt);
413
414 MI.eraseFromParent();
415 return Legalized;
416 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000417 case TargetOpcode::G_INSERT: {
418 if (TypeIdx != 0)
419 return UnableToLegalize;
420
421 unsigned Src = MI.getOperand(1).getReg();
422 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
423 MIRBuilder.buildAnyExt(SrcExt, Src);
424
425 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
426 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
427 MI.getOperand(3).getImm());
428 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
429 MIB.addReg(MI.getOperand(OpNum).getReg());
430 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
431 }
432
433 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
434 MI.eraseFromParent();
435 return Legalized;
436 }
Tim Northover3c73e362016-08-23 18:20:09 +0000437 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000438 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
439 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000440 "illegal to increase number of bytes loaded");
441
Tim Northover0f140c72016-09-09 11:46:34 +0000442 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
443 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
444 **MI.memoperands_begin());
445 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000446 MI.eraseFromParent();
447 return Legalized;
448 }
449 case TargetOpcode::G_STORE: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000450 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
451 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000452 "illegal to increase number of bytes modified by a store");
453
Tim Northover0f140c72016-09-09 11:46:34 +0000454 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
455 MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
456 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
457 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000458 MI.eraseFromParent();
459 return Legalized;
460 }
Tim Northoverea904f92016-08-19 22:40:00 +0000461 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000462 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000463 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000464 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000465 MI.eraseFromParent();
466 return Legalized;
467 }
Tim Northovera11be042016-08-19 22:40:08 +0000468 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000469 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
470 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
471 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000472 MI.eraseFromParent();
473 return Legalized;
474 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000475 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000476 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
477 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
478 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000479 MI.eraseFromParent();
480 return Legalized;
481 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000482 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000483 assert(TypeIdx == 1 && "unable to legalize predicate");
484 bool IsSigned = CmpInst::isSigned(
485 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Tim Northover0f140c72016-09-09 11:46:34 +0000486 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
487 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
Tim Northover051b8ad2016-08-26 17:46:17 +0000488 if (IsSigned) {
Tim Northover0f140c72016-09-09 11:46:34 +0000489 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
490 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000491 } else {
Tim Northover0f140c72016-09-09 11:46:34 +0000492 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
493 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000494 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000495 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000496 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
497 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
498 MI.eraseFromParent();
499 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000500 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000501 case TargetOpcode::G_GEP: {
502 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
503 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
504 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
505 MI.getOperand(2).setReg(OffsetExt);
506 return Legalized;
507 }
Tim Northover32335812016-08-04 18:35:11 +0000508 }
Tim Northover33b07d62016-07-22 20:03:43 +0000509}
510
Tim Northover69fa84a2016-10-14 22:18:18 +0000511LegalizerHelper::LegalizeResult
512LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000513 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000514 MIRBuilder.setInstr(MI);
515
516 switch(MI.getOpcode()) {
517 default:
518 return UnableToLegalize;
519 case TargetOpcode::G_SREM:
520 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000521 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
522 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000523 .addDef(QuotReg)
524 .addUse(MI.getOperand(1).getReg())
525 .addUse(MI.getOperand(2).getReg());
526
Tim Northover0f140c72016-09-09 11:46:34 +0000527 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
528 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
529 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
530 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000531 MI.eraseFromParent();
532 return Legalized;
533 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000534 case TargetOpcode::G_SMULO:
535 case TargetOpcode::G_UMULO: {
536 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
537 // result.
538 unsigned Res = MI.getOperand(0).getReg();
539 unsigned Overflow = MI.getOperand(1).getReg();
540 unsigned LHS = MI.getOperand(2).getReg();
541 unsigned RHS = MI.getOperand(3).getReg();
542
543 MIRBuilder.buildMul(Res, LHS, RHS);
544
545 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
546 ? TargetOpcode::G_SMULH
547 : TargetOpcode::G_UMULH;
548
549 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
550 MIRBuilder.buildInstr(Opcode)
551 .addDef(HiPart)
552 .addUse(LHS)
553 .addUse(RHS);
554
555 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
556 MIRBuilder.buildConstant(Zero, 0);
557 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
558 MI.eraseFromParent();
559 return Legalized;
560 }
Tim Northovercecee562016-08-26 17:46:13 +0000561 }
562}
563
Tim Northover69fa84a2016-10-14 22:18:18 +0000564LegalizerHelper::LegalizeResult
565LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
566 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000567 // FIXME: Don't know how to handle secondary types yet.
568 if (TypeIdx != 0)
569 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000570 switch (MI.getOpcode()) {
571 default:
572 return UnableToLegalize;
573 case TargetOpcode::G_ADD: {
574 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000575 unsigned DstReg = MI.getOperand(0).getReg();
576 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
Tim Northover33b07d62016-07-22 20:03:43 +0000577
578 MIRBuilder.setInstr(MI);
579
Tim Northoverb18ea162016-09-20 15:20:36 +0000580 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
581 SmallVector<uint64_t, 2> Indexes;
Tim Northover33b07d62016-07-22 20:03:43 +0000582 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
583 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
584
585 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000586 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
587 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000588 DstRegs.push_back(DstReg);
Tim Northover91c81732016-08-19 17:17:06 +0000589 Indexes.push_back(i * NarrowSize);
Tim Northover33b07d62016-07-22 20:03:43 +0000590 }
591
Tim Northover0f140c72016-09-09 11:46:34 +0000592 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
Tim Northover33b07d62016-07-22 20:03:43 +0000593 MI.eraseFromParent();
594 return Legalized;
595 }
596 }
597}