blob: 2d28a42c7979682b552d820b2224a793067e3f63 [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 Northoverbf017292017-03-03 22:46:09 +000089 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000090 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000091 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000092}
93
Tim Northovere0418412017-02-08 23:23:39 +000094static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
95 switch (Opcode) {
96 case TargetOpcode::G_FREM:
97 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
98 case TargetOpcode::G_FPOW:
99 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
100 }
101 llvm_unreachable("Unknown libcall function");
102}
103
Tim Northover69fa84a2016-10-14 22:18:18 +0000104LegalizerHelper::LegalizeResult
105LegalizerHelper::libcall(MachineInstr &MI) {
Tim Northover0f140c72016-09-09 11:46:34 +0000106 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
107 unsigned Size = Ty.getSizeInBits();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000108 MIRBuilder.setInstr(MI);
109
110 switch (MI.getOpcode()) {
111 default:
112 return UnableToLegalize;
Tim Northovere0418412017-02-08 23:23:39 +0000113 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000114 case TargetOpcode::G_FREM: {
Tim Northover11a23542016-08-31 21:24:02 +0000115 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
116 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000117 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
118 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Tim Northovere0418412017-02-08 23:23:39 +0000119 const char *Name = TLI.getLibcallName(getRTLibDesc(MI.getOpcode(), Size));
Tim Northover9a467182016-09-21 12:57:45 +0000120 CLI.lowerCall(
121 MIRBuilder, MachineOperand::CreateES(Name),
122 {MI.getOperand(0).getReg(), Ty},
123 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000124 MI.eraseFromParent();
125 return Legalized;
126 }
127 }
128}
129
Tim Northover0e6afbd2017-02-06 21:56:47 +0000130void LegalizerHelper::findInsertionsForRange(
131 int64_t DstStart, int64_t DstEnd, MachineInstr::mop_iterator &CurOp,
132 MachineInstr::mop_iterator &EndOp, MachineInstr &MI) {
133 while (CurOp != MI.operands_end() && std::next(CurOp)->getImm() < DstStart)
134 CurOp += 2;
135
136 EndOp = CurOp;
137 while (EndOp != MI.operands_end() && std::next(EndOp)->getImm() < DstEnd)
138 EndOp += 2;
139}
140
Tim Northover69fa84a2016-10-14 22:18:18 +0000141LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
142 unsigned TypeIdx,
143 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000144 // FIXME: Don't know how to handle secondary types yet.
145 if (TypeIdx != 0)
146 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000147
148 MIRBuilder.setInstr(MI);
149
Tim Northover9656f142016-08-04 20:54:13 +0000150 switch (MI.getOpcode()) {
151 default:
152 return UnableToLegalize;
153 case TargetOpcode::G_ADD: {
154 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Tim Northover0f140c72016-09-09 11:46:34 +0000155 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
156 NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000157
Tim Northoverb18ea162016-09-20 15:20:36 +0000158 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000159 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
160 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
161
Tim Northover0f140c72016-09-09 11:46:34 +0000162 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
163 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000164
165 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000166 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
167 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000168
Tim Northover0f140c72016-09-09 11:46:34 +0000169 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000170 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000171
172 DstRegs.push_back(DstReg);
173 CarryIn = CarryOut;
174 }
Tim Northover0f140c72016-09-09 11:46:34 +0000175 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000176 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000177 MI.eraseFromParent();
178 return Legalized;
179 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000180 case TargetOpcode::G_INSERT: {
181 if (TypeIdx != 0)
182 return UnableToLegalize;
183
184 unsigned NarrowSize = NarrowTy.getSizeInBits();
185 int NumParts =
186 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
187
188 SmallVector<unsigned, 2> SrcRegs, DstRegs;
189 SmallVector<uint64_t, 2> Indexes;
190 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
191
192 MachineInstr::mop_iterator CurOp = MI.operands_begin() + 2, EndOp;
193 for (int i = 0; i < NumParts; ++i) {
194 unsigned DstStart = i * NarrowSize;
195 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000196
197 findInsertionsForRange(DstStart, DstStart + NarrowSize, CurOp, EndOp, MI);
198
199 if (CurOp == EndOp) {
200 // No part of the insert affects this subregister, forward the original.
201 DstRegs.push_back(SrcRegs[i]);
202 continue;
203 } else if (MRI.getType(CurOp->getReg()) == NarrowTy &&
204 std::next(CurOp)->getImm() == DstStart) {
205 // The entire subregister is defined by this insert, forward the new
206 // value.
207 DstRegs.push_back(CurOp->getReg());
208 continue;
209 }
210
211 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_INSERT)
212 .addDef(DstReg)
213 .addUse(SrcRegs[i]);
214
215 for (; CurOp != EndOp; CurOp += 2) {
216 unsigned Reg = CurOp->getReg();
217 uint64_t Offset = std::next(CurOp)->getImm() - DstStart;
218
219 // Make sure we don't have a cross-register insert.
220 if (Offset + MRI.getType(Reg).getSizeInBits() > NarrowSize) {
221 // FIXME: we should handle this case, though it's unlikely to be
222 // common given ABI-related layout restrictions.
223 return UnableToLegalize;
224 }
225
226 MIB.addUse(Reg);
227 MIB.addImm(Offset);
228 }
229
230 DstRegs.push_back(DstReg);
231 }
232
233 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000234 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000235 MI.eraseFromParent();
236 return Legalized;
237 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000238 case TargetOpcode::G_LOAD: {
239 unsigned NarrowSize = NarrowTy.getSizeInBits();
240 int NumParts =
241 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
242 LLT NarrowPtrTy = LLT::pointer(
243 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
244
245 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000246 for (int i = 0; i < NumParts; ++i) {
247 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
248 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
249 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
250
251 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
252 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000253 // TODO: This is conservatively correct, but we probably want to split the
254 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000255 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
256
257 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000258 }
259 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000260 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000261 MI.eraseFromParent();
262 return Legalized;
263 }
Justin Bognerfde01042017-01-18 17:29:54 +0000264 case TargetOpcode::G_STORE: {
265 unsigned NarrowSize = NarrowTy.getSizeInBits();
266 int NumParts =
267 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
268 LLT NarrowPtrTy = LLT::pointer(
269 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
270
271 SmallVector<unsigned, 2> SrcRegs;
272 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
273
274 for (int i = 0; i < NumParts; ++i) {
275 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
276 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
277 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
278 MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000279 // TODO: This is conservatively correct, but we probably want to split the
280 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000281 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
282 }
283 MI.eraseFromParent();
284 return Legalized;
285 }
Tim Northover9656f142016-08-04 20:54:13 +0000286 }
Tim Northover33b07d62016-07-22 20:03:43 +0000287}
288
Tim Northover69fa84a2016-10-14 22:18:18 +0000289LegalizerHelper::LegalizeResult
290LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000291 MIRBuilder.setInstr(MI);
292
Tim Northover32335812016-08-04 18:35:11 +0000293 switch (MI.getOpcode()) {
294 default:
295 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000296 case TargetOpcode::G_ADD:
297 case TargetOpcode::G_AND:
298 case TargetOpcode::G_MUL:
299 case TargetOpcode::G_OR:
300 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000301 case TargetOpcode::G_SUB:
302 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000303 // Perform operation at larger width (any extension is fine here, high bits
304 // don't affect the result) and then truncate the result back to the
305 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000306 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
307 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
308 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
309 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000310
Tim Northover0f140c72016-09-09 11:46:34 +0000311 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
312 MIRBuilder.buildInstr(MI.getOpcode())
313 .addDef(DstExt)
314 .addUse(Src1Ext)
315 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000316
Tim Northover0f140c72016-09-09 11:46:34 +0000317 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000318 MI.eraseFromParent();
319 return Legalized;
320 }
Tim Northover7a753d92016-08-26 17:46:06 +0000321 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000322 case TargetOpcode::G_UDIV:
323 case TargetOpcode::G_ASHR:
324 case TargetOpcode::G_LSHR: {
325 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
326 MI.getOpcode() == TargetOpcode::G_ASHR
327 ? TargetOpcode::G_SEXT
328 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000329
Tim Northover0f140c72016-09-09 11:46:34 +0000330 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
331 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
332 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000333
Tim Northover0f140c72016-09-09 11:46:34 +0000334 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
335 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
336 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000337
Tim Northover0f140c72016-09-09 11:46:34 +0000338 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
339 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000340 .addDef(ResExt)
341 .addUse(LHSExt)
342 .addUse(RHSExt);
343
Tim Northover0f140c72016-09-09 11:46:34 +0000344 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000345 MI.eraseFromParent();
346 return Legalized;
347 }
Tim Northover868332d2017-02-06 23:41:27 +0000348 case TargetOpcode::G_SELECT: {
349 if (TypeIdx != 0)
350 return UnableToLegalize;
351
352 // Perform operation at larger width (any extension is fine here, high bits
353 // don't affect the result) and then truncate the result back to the
354 // original type.
355 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
356 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
357 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
358 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
359
360 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
361 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
362 .addDef(DstExt)
363 .addReg(MI.getOperand(1).getReg())
364 .addUse(Src1Ext)
365 .addUse(Src2Ext);
366
367 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
368 MI.eraseFromParent();
369 return Legalized;
370 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000371 case TargetOpcode::G_FPTOSI:
372 case TargetOpcode::G_FPTOUI: {
373 if (TypeIdx != 0)
374 return UnableToLegalize;
375
376 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
377 MIRBuilder.buildInstr(MI.getOpcode())
378 .addDef(DstExt)
379 .addUse(MI.getOperand(1).getReg());
380
381 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
382 MI.eraseFromParent();
383 return Legalized;
384 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000385 case TargetOpcode::G_SITOFP:
386 case TargetOpcode::G_UITOFP: {
387 if (TypeIdx != 1)
388 return UnableToLegalize;
389
390 unsigned Src = MI.getOperand(1).getReg();
391 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
392
393 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
394 MIRBuilder.buildSExt(SrcExt, Src);
395 } else {
396 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
397 MIRBuilder.buildZExt(SrcExt, Src);
398 }
399
400 MIRBuilder.buildInstr(MI.getOpcode())
401 .addDef(MI.getOperand(0).getReg())
402 .addUse(SrcExt);
403
404 MI.eraseFromParent();
405 return Legalized;
406 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000407 case TargetOpcode::G_INSERT: {
408 if (TypeIdx != 0)
409 return UnableToLegalize;
410
411 unsigned Src = MI.getOperand(1).getReg();
412 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
413 MIRBuilder.buildAnyExt(SrcExt, Src);
414
415 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
416 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
417 MI.getOperand(3).getImm());
418 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
419 MIB.addReg(MI.getOperand(OpNum).getReg());
420 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
421 }
422
423 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
424 MI.eraseFromParent();
425 return Legalized;
426 }
Tim Northover3c73e362016-08-23 18:20:09 +0000427 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000428 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
429 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000430 "illegal to increase number of bytes loaded");
431
Tim Northover0f140c72016-09-09 11:46:34 +0000432 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
433 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
434 **MI.memoperands_begin());
435 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000436 MI.eraseFromParent();
437 return Legalized;
438 }
439 case TargetOpcode::G_STORE: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000440 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
441 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000442 "illegal to increase number of bytes modified by a store");
443
Tim Northover0f140c72016-09-09 11:46:34 +0000444 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
445 MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
446 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
447 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000448 MI.eraseFromParent();
449 return Legalized;
450 }
Tim Northoverea904f92016-08-19 22:40:00 +0000451 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000452 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000453 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000454 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000455 MI.eraseFromParent();
456 return Legalized;
457 }
Tim Northovera11be042016-08-19 22:40:08 +0000458 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000459 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
460 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
461 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000462 MI.eraseFromParent();
463 return Legalized;
464 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000465 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000466 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
467 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
468 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000469 MI.eraseFromParent();
470 return Legalized;
471 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000472 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000473 assert(TypeIdx == 1 && "unable to legalize predicate");
474 bool IsSigned = CmpInst::isSigned(
475 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Tim Northover0f140c72016-09-09 11:46:34 +0000476 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
477 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
Tim Northover051b8ad2016-08-26 17:46:17 +0000478 if (IsSigned) {
Tim Northover0f140c72016-09-09 11:46:34 +0000479 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
480 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000481 } else {
Tim Northover0f140c72016-09-09 11:46:34 +0000482 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
483 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000484 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000485 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000486 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
487 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
488 MI.eraseFromParent();
489 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000490 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000491 case TargetOpcode::G_GEP: {
492 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
493 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
494 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
495 MI.getOperand(2).setReg(OffsetExt);
496 return Legalized;
497 }
Tim Northover32335812016-08-04 18:35:11 +0000498 }
Tim Northover33b07d62016-07-22 20:03:43 +0000499}
500
Tim Northover69fa84a2016-10-14 22:18:18 +0000501LegalizerHelper::LegalizeResult
502LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000503 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000504 MIRBuilder.setInstr(MI);
505
506 switch(MI.getOpcode()) {
507 default:
508 return UnableToLegalize;
509 case TargetOpcode::G_SREM:
510 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000511 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
512 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000513 .addDef(QuotReg)
514 .addUse(MI.getOperand(1).getReg())
515 .addUse(MI.getOperand(2).getReg());
516
Tim Northover0f140c72016-09-09 11:46:34 +0000517 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
518 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
519 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
520 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000521 MI.eraseFromParent();
522 return Legalized;
523 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000524 case TargetOpcode::G_SMULO:
525 case TargetOpcode::G_UMULO: {
526 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
527 // result.
528 unsigned Res = MI.getOperand(0).getReg();
529 unsigned Overflow = MI.getOperand(1).getReg();
530 unsigned LHS = MI.getOperand(2).getReg();
531 unsigned RHS = MI.getOperand(3).getReg();
532
533 MIRBuilder.buildMul(Res, LHS, RHS);
534
535 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
536 ? TargetOpcode::G_SMULH
537 : TargetOpcode::G_UMULH;
538
539 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
540 MIRBuilder.buildInstr(Opcode)
541 .addDef(HiPart)
542 .addUse(LHS)
543 .addUse(RHS);
544
545 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
546 MIRBuilder.buildConstant(Zero, 0);
547 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
548 MI.eraseFromParent();
549 return Legalized;
550 }
Tim Northovercecee562016-08-26 17:46:13 +0000551 }
552}
553
Tim Northover69fa84a2016-10-14 22:18:18 +0000554LegalizerHelper::LegalizeResult
555LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
556 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000557 // FIXME: Don't know how to handle secondary types yet.
558 if (TypeIdx != 0)
559 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000560 switch (MI.getOpcode()) {
561 default:
562 return UnableToLegalize;
563 case TargetOpcode::G_ADD: {
564 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000565 unsigned DstReg = MI.getOperand(0).getReg();
566 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
Tim Northover33b07d62016-07-22 20:03:43 +0000567
568 MIRBuilder.setInstr(MI);
569
Tim Northoverb18ea162016-09-20 15:20:36 +0000570 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000571 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
572 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
573
574 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000575 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
576 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000577 DstRegs.push_back(DstReg);
578 }
579
Tim Northoverbf017292017-03-03 22:46:09 +0000580 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000581 MI.eraseFromParent();
582 return Legalized;
583 }
584 }
585}