blob: da7e9595eed7db3ec0976744db97fe67f3353ef0 [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 Northoverd1e951e2017-03-09 22:00:39 +0000120 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northover9a467182016-09-21 12:57:45 +0000121 CLI.lowerCall(
122 MIRBuilder, MachineOperand::CreateES(Name),
123 {MI.getOperand(0).getReg(), Ty},
124 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000125 MI.eraseFromParent();
126 return Legalized;
127 }
128 }
129}
130
Tim Northover69fa84a2016-10-14 22:18:18 +0000131LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
132 unsigned TypeIdx,
133 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000134 // FIXME: Don't know how to handle secondary types yet.
135 if (TypeIdx != 0)
136 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000137
138 MIRBuilder.setInstr(MI);
139
Tim Northover9656f142016-08-04 20:54:13 +0000140 switch (MI.getOpcode()) {
141 default:
142 return UnableToLegalize;
143 case TargetOpcode::G_ADD: {
144 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Tim Northover0f140c72016-09-09 11:46:34 +0000145 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
146 NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000147
Tim Northoverb18ea162016-09-20 15:20:36 +0000148 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000149 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
150 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
151
Tim Northover0f140c72016-09-09 11:46:34 +0000152 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
153 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000154
155 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000156 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
157 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000158
Tim Northover0f140c72016-09-09 11:46:34 +0000159 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000160 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000161
162 DstRegs.push_back(DstReg);
163 CarryIn = CarryOut;
164 }
Tim Northover0f140c72016-09-09 11:46:34 +0000165 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000166 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000167 MI.eraseFromParent();
168 return Legalized;
169 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000170 case TargetOpcode::G_INSERT: {
171 if (TypeIdx != 0)
172 return UnableToLegalize;
173
Tim Northover75e0b912017-03-06 18:23:04 +0000174 int64_t NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000175 int NumParts =
176 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
177
178 SmallVector<unsigned, 2> SrcRegs, DstRegs;
179 SmallVector<uint64_t, 2> Indexes;
180 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
181
Tim Northover75e0b912017-03-06 18:23:04 +0000182 unsigned OpReg = MI.getOperand(2).getReg();
183 int64_t OpStart = MI.getOperand(3).getImm();
184 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000185 for (int i = 0; i < NumParts; ++i) {
186 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000187
Tim Northover75e0b912017-03-06 18:23:04 +0000188 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000189 // No part of the insert affects this subregister, forward the original.
190 DstRegs.push_back(SrcRegs[i]);
191 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000192 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000193 // The entire subregister is defined by this insert, forward the new
194 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000195 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000196 continue;
197 }
198
Tim Northover2eb18d32017-03-07 21:24:33 +0000199 // OpSegStart is where this destination segment would start in OpReg if it
200 // extended infinitely in both directions.
201 int64_t ExtractOffset, InsertOffset, SegSize;
202 if (OpStart < DstStart) {
203 InsertOffset = 0;
204 ExtractOffset = DstStart - OpStart;
205 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
206 } else {
207 InsertOffset = OpStart - DstStart;
208 ExtractOffset = 0;
209 SegSize =
210 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
211 }
212
213 unsigned SegReg = OpReg;
214 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000215 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000216 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
217 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000218 }
219
Tim Northover75e0b912017-03-06 18:23:04 +0000220 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000221 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000222 DstRegs.push_back(DstReg);
223 }
224
225 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000226 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000227 MI.eraseFromParent();
228 return Legalized;
229 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000230 case TargetOpcode::G_LOAD: {
231 unsigned NarrowSize = NarrowTy.getSizeInBits();
232 int NumParts =
233 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
234 LLT NarrowPtrTy = LLT::pointer(
235 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
236
237 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000238 for (int i = 0; i < NumParts; ++i) {
239 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
240 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
241 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
242
243 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
244 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000245 // TODO: This is conservatively correct, but we probably want to split the
246 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000247 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
248
249 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000250 }
251 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000252 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000253 MI.eraseFromParent();
254 return Legalized;
255 }
Justin Bognerfde01042017-01-18 17:29:54 +0000256 case TargetOpcode::G_STORE: {
257 unsigned NarrowSize = NarrowTy.getSizeInBits();
258 int NumParts =
259 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
260 LLT NarrowPtrTy = LLT::pointer(
261 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
262
263 SmallVector<unsigned, 2> SrcRegs;
264 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
265
266 for (int i = 0; i < NumParts; ++i) {
267 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
268 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
269 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
270 MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000271 // TODO: This is conservatively correct, but we probably want to split the
272 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000273 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
274 }
275 MI.eraseFromParent();
276 return Legalized;
277 }
Tim Northover9656f142016-08-04 20:54:13 +0000278 }
Tim Northover33b07d62016-07-22 20:03:43 +0000279}
280
Tim Northover69fa84a2016-10-14 22:18:18 +0000281LegalizerHelper::LegalizeResult
282LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000283 MIRBuilder.setInstr(MI);
284
Tim Northover32335812016-08-04 18:35:11 +0000285 switch (MI.getOpcode()) {
286 default:
287 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000288 case TargetOpcode::G_ADD:
289 case TargetOpcode::G_AND:
290 case TargetOpcode::G_MUL:
291 case TargetOpcode::G_OR:
292 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000293 case TargetOpcode::G_SUB:
294 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000295 // Perform operation at larger width (any extension is fine here, high bits
296 // don't affect the result) and then truncate the result back to the
297 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000298 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
299 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
300 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
301 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000302
Tim Northover0f140c72016-09-09 11:46:34 +0000303 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
304 MIRBuilder.buildInstr(MI.getOpcode())
305 .addDef(DstExt)
306 .addUse(Src1Ext)
307 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000308
Tim Northover0f140c72016-09-09 11:46:34 +0000309 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000310 MI.eraseFromParent();
311 return Legalized;
312 }
Tim Northover7a753d92016-08-26 17:46:06 +0000313 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000314 case TargetOpcode::G_UDIV:
315 case TargetOpcode::G_ASHR:
316 case TargetOpcode::G_LSHR: {
317 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
318 MI.getOpcode() == TargetOpcode::G_ASHR
319 ? TargetOpcode::G_SEXT
320 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000321
Tim Northover0f140c72016-09-09 11:46:34 +0000322 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
323 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
324 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000325
Tim Northover0f140c72016-09-09 11:46:34 +0000326 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
327 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
328 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000329
Tim Northover0f140c72016-09-09 11:46:34 +0000330 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
331 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000332 .addDef(ResExt)
333 .addUse(LHSExt)
334 .addUse(RHSExt);
335
Tim Northover0f140c72016-09-09 11:46:34 +0000336 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000337 MI.eraseFromParent();
338 return Legalized;
339 }
Tim Northover868332d2017-02-06 23:41:27 +0000340 case TargetOpcode::G_SELECT: {
341 if (TypeIdx != 0)
342 return UnableToLegalize;
343
344 // Perform operation at larger width (any extension is fine here, high bits
345 // don't affect the result) and then truncate the result back to the
346 // original type.
347 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
348 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
349 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
350 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
351
352 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
353 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
354 .addDef(DstExt)
355 .addReg(MI.getOperand(1).getReg())
356 .addUse(Src1Ext)
357 .addUse(Src2Ext);
358
359 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
360 MI.eraseFromParent();
361 return Legalized;
362 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000363 case TargetOpcode::G_FPTOSI:
364 case TargetOpcode::G_FPTOUI: {
365 if (TypeIdx != 0)
366 return UnableToLegalize;
367
368 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
369 MIRBuilder.buildInstr(MI.getOpcode())
370 .addDef(DstExt)
371 .addUse(MI.getOperand(1).getReg());
372
373 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
374 MI.eraseFromParent();
375 return Legalized;
376 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000377 case TargetOpcode::G_SITOFP:
378 case TargetOpcode::G_UITOFP: {
379 if (TypeIdx != 1)
380 return UnableToLegalize;
381
382 unsigned Src = MI.getOperand(1).getReg();
383 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
384
385 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
386 MIRBuilder.buildSExt(SrcExt, Src);
387 } else {
388 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
389 MIRBuilder.buildZExt(SrcExt, Src);
390 }
391
392 MIRBuilder.buildInstr(MI.getOpcode())
393 .addDef(MI.getOperand(0).getReg())
394 .addUse(SrcExt);
395
396 MI.eraseFromParent();
397 return Legalized;
398 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000399 case TargetOpcode::G_INSERT: {
400 if (TypeIdx != 0)
401 return UnableToLegalize;
402
403 unsigned Src = MI.getOperand(1).getReg();
404 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
405 MIRBuilder.buildAnyExt(SrcExt, Src);
406
407 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
408 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
409 MI.getOperand(3).getImm());
410 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
411 MIB.addReg(MI.getOperand(OpNum).getReg());
412 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
413 }
414
415 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
416 MI.eraseFromParent();
417 return Legalized;
418 }
Tim Northover3c73e362016-08-23 18:20:09 +0000419 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000420 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
421 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000422 "illegal to increase number of bytes loaded");
423
Tim Northover0f140c72016-09-09 11:46:34 +0000424 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
425 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
426 **MI.memoperands_begin());
427 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000428 MI.eraseFromParent();
429 return Legalized;
430 }
431 case TargetOpcode::G_STORE: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000432 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
433 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000434 "illegal to increase number of bytes modified by a store");
435
Tim Northover0f140c72016-09-09 11:46:34 +0000436 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
437 MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
438 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
439 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000440 MI.eraseFromParent();
441 return Legalized;
442 }
Tim Northoverea904f92016-08-19 22:40:00 +0000443 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000444 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000445 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000446 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000447 MI.eraseFromParent();
448 return Legalized;
449 }
Tim Northovera11be042016-08-19 22:40:08 +0000450 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000451 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
452 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
453 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000454 MI.eraseFromParent();
455 return Legalized;
456 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000457 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000458 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
459 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
460 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000461 MI.eraseFromParent();
462 return Legalized;
463 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000464 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000465 assert(TypeIdx == 1 && "unable to legalize predicate");
466 bool IsSigned = CmpInst::isSigned(
467 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Tim Northover0f140c72016-09-09 11:46:34 +0000468 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
469 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
Tim Northover051b8ad2016-08-26 17:46:17 +0000470 if (IsSigned) {
Tim Northover0f140c72016-09-09 11:46:34 +0000471 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
472 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000473 } else {
Tim Northover0f140c72016-09-09 11:46:34 +0000474 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
475 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000476 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000477 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000478 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
479 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
480 MI.eraseFromParent();
481 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000482 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000483 case TargetOpcode::G_GEP: {
484 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
485 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
486 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
487 MI.getOperand(2).setReg(OffsetExt);
488 return Legalized;
489 }
Tim Northover32335812016-08-04 18:35:11 +0000490 }
Tim Northover33b07d62016-07-22 20:03:43 +0000491}
492
Tim Northover69fa84a2016-10-14 22:18:18 +0000493LegalizerHelper::LegalizeResult
494LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000495 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000496 MIRBuilder.setInstr(MI);
497
498 switch(MI.getOpcode()) {
499 default:
500 return UnableToLegalize;
501 case TargetOpcode::G_SREM:
502 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000503 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
504 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000505 .addDef(QuotReg)
506 .addUse(MI.getOperand(1).getReg())
507 .addUse(MI.getOperand(2).getReg());
508
Tim Northover0f140c72016-09-09 11:46:34 +0000509 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
510 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
511 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
512 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000513 MI.eraseFromParent();
514 return Legalized;
515 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000516 case TargetOpcode::G_SMULO:
517 case TargetOpcode::G_UMULO: {
518 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
519 // result.
520 unsigned Res = MI.getOperand(0).getReg();
521 unsigned Overflow = MI.getOperand(1).getReg();
522 unsigned LHS = MI.getOperand(2).getReg();
523 unsigned RHS = MI.getOperand(3).getReg();
524
525 MIRBuilder.buildMul(Res, LHS, RHS);
526
527 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
528 ? TargetOpcode::G_SMULH
529 : TargetOpcode::G_UMULH;
530
531 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
532 MIRBuilder.buildInstr(Opcode)
533 .addDef(HiPart)
534 .addUse(LHS)
535 .addUse(RHS);
536
537 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
538 MIRBuilder.buildConstant(Zero, 0);
539 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
540 MI.eraseFromParent();
541 return Legalized;
542 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000543 case TargetOpcode::G_FNEG: {
544 // TODO: Handle vector types once we are able to
545 // represent them.
546 if (Ty.isVector())
547 return UnableToLegalize;
548 unsigned Res = MI.getOperand(0).getReg();
549 Type *ZeroTy;
550 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
551 switch (Ty.getSizeInBits()) {
552 case 16:
553 ZeroTy = Type::getHalfTy(Ctx);
554 break;
555 case 32:
556 ZeroTy = Type::getFloatTy(Ctx);
557 break;
558 case 64:
559 ZeroTy = Type::getDoubleTy(Ctx);
560 break;
561 default:
562 llvm_unreachable("unexpected floating-point type");
563 }
564 ConstantFP &ZeroForNegation =
565 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
566 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
567 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
568 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
569 .addDef(Res)
570 .addUse(Zero)
571 .addUse(MI.getOperand(1).getReg());
572 MI.eraseFromParent();
573 return Legalized;
574 }
Tim Northovercecee562016-08-26 17:46:13 +0000575 }
576}
577
Tim Northover69fa84a2016-10-14 22:18:18 +0000578LegalizerHelper::LegalizeResult
579LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
580 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000581 // FIXME: Don't know how to handle secondary types yet.
582 if (TypeIdx != 0)
583 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000584 switch (MI.getOpcode()) {
585 default:
586 return UnableToLegalize;
587 case TargetOpcode::G_ADD: {
588 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000589 unsigned DstReg = MI.getOperand(0).getReg();
590 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
Tim Northover33b07d62016-07-22 20:03:43 +0000591
592 MIRBuilder.setInstr(MI);
593
Tim Northoverb18ea162016-09-20 15:20:36 +0000594 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000595 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
596 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
597
598 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000599 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
600 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000601 DstRegs.push_back(DstReg);
602 }
603
Tim Northoverbf017292017-03-03 22:46:09 +0000604 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000605 MI.eraseFromParent();
606 return Legalized;
607 }
608 }
609}