blob: afab23d94f0dbf3156e76c0720b33c2cbc3a7286 [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)
Volkan Keles685fbda2017-03-10 18:34:57 +000032 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
Tim Northover33b07d62016-07-22 20:03:43 +000033 MIRBuilder.setMF(MF);
34}
35
Tim Northover69fa84a2016-10-14 22:18:18 +000036LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000037LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
38 auto Action = LI.getAction(MI, MRI);
Tim Northovera01bece2016-08-23 19:30:42 +000039 switch (std::get<0>(Action)) {
Tim Northover69fa84a2016-10-14 22:18:18 +000040 case LegalizerInfo::Legal:
Tim Northover33b07d62016-07-22 20:03:43 +000041 return AlreadyLegal;
Tim Northover69fa84a2016-10-14 22:18:18 +000042 case LegalizerInfo::Libcall:
Tim Northoveredb3c8c2016-08-29 19:07:16 +000043 return libcall(MI);
Tim Northover69fa84a2016-10-14 22:18:18 +000044 case LegalizerInfo::NarrowScalar:
Tim Northovera01bece2016-08-23 19:30:42 +000045 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000046 case LegalizerInfo::WidenScalar:
Tim Northovera01bece2016-08-23 19:30:42 +000047 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000048 case LegalizerInfo::Lower:
Tim Northovercecee562016-08-26 17:46:13 +000049 return lower(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000050 case LegalizerInfo::FewerElements:
Tim Northovera01bece2016-08-23 19:30:42 +000051 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover91366172017-02-15 23:22:50 +000052 case LegalizerInfo::Custom:
Volkan Keles685fbda2017-03-10 18:34:57 +000053 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
54 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000055 default:
56 return UnableToLegalize;
57 }
58}
59
Tim Northover69fa84a2016-10-14 22:18:18 +000060void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
61 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000062 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000063 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000064 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000065}
66
Tim Northovere0418412017-02-08 23:23:39 +000067static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
68 switch (Opcode) {
69 case TargetOpcode::G_FREM:
70 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
71 case TargetOpcode::G_FPOW:
72 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
73 }
74 llvm_unreachable("Unknown libcall function");
75}
76
Tim Northover69fa84a2016-10-14 22:18:18 +000077LegalizerHelper::LegalizeResult
78LegalizerHelper::libcall(MachineInstr &MI) {
Tim Northover0f140c72016-09-09 11:46:34 +000079 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
80 unsigned Size = Ty.getSizeInBits();
Tim Northoveredb3c8c2016-08-29 19:07:16 +000081 MIRBuilder.setInstr(MI);
82
83 switch (MI.getOpcode()) {
84 default:
85 return UnableToLegalize;
Tim Northovere0418412017-02-08 23:23:39 +000086 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +000087 case TargetOpcode::G_FREM: {
Tim Northover11a23542016-08-31 21:24:02 +000088 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
89 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Tim Northoveredb3c8c2016-08-29 19:07:16 +000090 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
91 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picusd79253a2017-03-20 14:40:18 +000092 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
93 const char *Name = TLI.getLibcallName(Libcall);
Tim Northoverd1e951e2017-03-09 22:00:39 +000094 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northover9a467182016-09-21 12:57:45 +000095 CLI.lowerCall(
Diana Picusd79253a2017-03-20 14:40:18 +000096 MIRBuilder, TLI.getLibcallCallingConv(Libcall),
97 MachineOperand::CreateES(Name), {MI.getOperand(0).getReg(), Ty},
Tim Northover9a467182016-09-21 12:57:45 +000098 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
Tim Northoveredb3c8c2016-08-29 19:07:16 +000099 MI.eraseFromParent();
100 return Legalized;
101 }
102 }
103}
104
Tim Northover69fa84a2016-10-14 22:18:18 +0000105LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
106 unsigned TypeIdx,
107 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000108 // FIXME: Don't know how to handle secondary types yet.
109 if (TypeIdx != 0)
110 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000111
112 MIRBuilder.setInstr(MI);
113
Tim Northover9656f142016-08-04 20:54:13 +0000114 switch (MI.getOpcode()) {
115 default:
116 return UnableToLegalize;
117 case TargetOpcode::G_ADD: {
118 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Tim Northover0f140c72016-09-09 11:46:34 +0000119 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
120 NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000121
Tim Northoverb18ea162016-09-20 15:20:36 +0000122 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000123 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
124 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
125
Tim Northover0f140c72016-09-09 11:46:34 +0000126 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
127 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000128
129 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000130 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
131 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000132
Tim Northover0f140c72016-09-09 11:46:34 +0000133 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000134 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000135
136 DstRegs.push_back(DstReg);
137 CarryIn = CarryOut;
138 }
Tim Northover0f140c72016-09-09 11:46:34 +0000139 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000140 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000141 MI.eraseFromParent();
142 return Legalized;
143 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000144 case TargetOpcode::G_INSERT: {
145 if (TypeIdx != 0)
146 return UnableToLegalize;
147
Tim Northover75e0b912017-03-06 18:23:04 +0000148 int64_t NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000149 int NumParts =
150 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
151
152 SmallVector<unsigned, 2> SrcRegs, DstRegs;
153 SmallVector<uint64_t, 2> Indexes;
154 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
155
Tim Northover75e0b912017-03-06 18:23:04 +0000156 unsigned OpReg = MI.getOperand(2).getReg();
157 int64_t OpStart = MI.getOperand(3).getImm();
158 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000159 for (int i = 0; i < NumParts; ++i) {
160 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000161
Tim Northover75e0b912017-03-06 18:23:04 +0000162 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000163 // No part of the insert affects this subregister, forward the original.
164 DstRegs.push_back(SrcRegs[i]);
165 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000166 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000167 // The entire subregister is defined by this insert, forward the new
168 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000169 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000170 continue;
171 }
172
Tim Northover2eb18d32017-03-07 21:24:33 +0000173 // OpSegStart is where this destination segment would start in OpReg if it
174 // extended infinitely in both directions.
175 int64_t ExtractOffset, InsertOffset, SegSize;
176 if (OpStart < DstStart) {
177 InsertOffset = 0;
178 ExtractOffset = DstStart - OpStart;
179 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
180 } else {
181 InsertOffset = OpStart - DstStart;
182 ExtractOffset = 0;
183 SegSize =
184 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
185 }
186
187 unsigned SegReg = OpReg;
188 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000189 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000190 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
191 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000192 }
193
Tim Northover75e0b912017-03-06 18:23:04 +0000194 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000195 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000196 DstRegs.push_back(DstReg);
197 }
198
199 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000200 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000201 MI.eraseFromParent();
202 return Legalized;
203 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000204 case TargetOpcode::G_LOAD: {
205 unsigned NarrowSize = NarrowTy.getSizeInBits();
206 int NumParts =
207 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
208 LLT NarrowPtrTy = LLT::pointer(
209 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
210
211 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000212 for (int i = 0; i < NumParts; ++i) {
213 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
214 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
215 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
216
217 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
218 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000219 // TODO: This is conservatively correct, but we probably want to split the
220 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000221 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
222
223 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000224 }
225 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000226 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000227 MI.eraseFromParent();
228 return Legalized;
229 }
Justin Bognerfde01042017-01-18 17:29:54 +0000230 case TargetOpcode::G_STORE: {
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> SrcRegs;
238 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
239
240 for (int i = 0; i < NumParts; ++i) {
241 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
242 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
243 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
244 MIRBuilder.buildGEP(DstReg, 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 Bognerfde01042017-01-18 17:29:54 +0000247 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
248 }
249 MI.eraseFromParent();
250 return Legalized;
251 }
Igor Breger29537882017-04-07 14:41:59 +0000252 case TargetOpcode::G_CONSTANT: {
253 unsigned NarrowSize = NarrowTy.getSizeInBits();
254 int NumParts =
255 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
256 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
257 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
258
259 SmallVector<unsigned, 2> DstRegs;
260 for (int i = 0; i < NumParts; ++i) {
261 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
262 ConstantInt *CI =
263 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
264 MIRBuilder.buildConstant(DstReg, *CI);
265 DstRegs.push_back(DstReg);
266 }
267 unsigned DstReg = MI.getOperand(0).getReg();
268 MIRBuilder.buildMerge(DstReg, DstRegs);
269 MI.eraseFromParent();
270 return Legalized;
271 }
Tim Northover9656f142016-08-04 20:54:13 +0000272 }
Tim Northover33b07d62016-07-22 20:03:43 +0000273}
274
Tim Northover69fa84a2016-10-14 22:18:18 +0000275LegalizerHelper::LegalizeResult
276LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000277 MIRBuilder.setInstr(MI);
278
Tim Northover32335812016-08-04 18:35:11 +0000279 switch (MI.getOpcode()) {
280 default:
281 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000282 case TargetOpcode::G_ADD:
283 case TargetOpcode::G_AND:
284 case TargetOpcode::G_MUL:
285 case TargetOpcode::G_OR:
286 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000287 case TargetOpcode::G_SUB:
288 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000289 // Perform operation at larger width (any extension is fine here, high bits
290 // don't affect the result) and then truncate the result back to the
291 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000292 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
293 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
294 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
295 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000296
Tim Northover0f140c72016-09-09 11:46:34 +0000297 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
298 MIRBuilder.buildInstr(MI.getOpcode())
299 .addDef(DstExt)
300 .addUse(Src1Ext)
301 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000302
Tim Northover0f140c72016-09-09 11:46:34 +0000303 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000304 MI.eraseFromParent();
305 return Legalized;
306 }
Tim Northover7a753d92016-08-26 17:46:06 +0000307 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000308 case TargetOpcode::G_UDIV:
309 case TargetOpcode::G_ASHR:
310 case TargetOpcode::G_LSHR: {
311 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
312 MI.getOpcode() == TargetOpcode::G_ASHR
313 ? TargetOpcode::G_SEXT
314 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000315
Tim Northover0f140c72016-09-09 11:46:34 +0000316 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
317 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
318 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000319
Tim Northover0f140c72016-09-09 11:46:34 +0000320 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
321 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
322 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000323
Tim Northover0f140c72016-09-09 11:46:34 +0000324 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
325 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000326 .addDef(ResExt)
327 .addUse(LHSExt)
328 .addUse(RHSExt);
329
Tim Northover0f140c72016-09-09 11:46:34 +0000330 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000331 MI.eraseFromParent();
332 return Legalized;
333 }
Tim Northover868332d2017-02-06 23:41:27 +0000334 case TargetOpcode::G_SELECT: {
335 if (TypeIdx != 0)
336 return UnableToLegalize;
337
338 // Perform operation at larger width (any extension is fine here, high bits
339 // don't affect the result) and then truncate the result back to the
340 // original type.
341 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
342 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
343 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
344 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
345
346 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
347 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
348 .addDef(DstExt)
349 .addReg(MI.getOperand(1).getReg())
350 .addUse(Src1Ext)
351 .addUse(Src2Ext);
352
353 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
354 MI.eraseFromParent();
355 return Legalized;
356 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000357 case TargetOpcode::G_FPTOSI:
358 case TargetOpcode::G_FPTOUI: {
359 if (TypeIdx != 0)
360 return UnableToLegalize;
361
362 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
363 MIRBuilder.buildInstr(MI.getOpcode())
364 .addDef(DstExt)
365 .addUse(MI.getOperand(1).getReg());
366
367 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
368 MI.eraseFromParent();
369 return Legalized;
370 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000371 case TargetOpcode::G_SITOFP:
372 case TargetOpcode::G_UITOFP: {
373 if (TypeIdx != 1)
374 return UnableToLegalize;
375
376 unsigned Src = MI.getOperand(1).getReg();
377 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
378
379 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
380 MIRBuilder.buildSExt(SrcExt, Src);
381 } else {
382 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
383 MIRBuilder.buildZExt(SrcExt, Src);
384 }
385
386 MIRBuilder.buildInstr(MI.getOpcode())
387 .addDef(MI.getOperand(0).getReg())
388 .addUse(SrcExt);
389
390 MI.eraseFromParent();
391 return Legalized;
392 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000393 case TargetOpcode::G_INSERT: {
394 if (TypeIdx != 0)
395 return UnableToLegalize;
396
397 unsigned Src = MI.getOperand(1).getReg();
398 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
399 MIRBuilder.buildAnyExt(SrcExt, Src);
400
401 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
402 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
403 MI.getOperand(3).getImm());
404 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
405 MIB.addReg(MI.getOperand(OpNum).getReg());
406 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
407 }
408
409 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
410 MI.eraseFromParent();
411 return Legalized;
412 }
Tim Northover3c73e362016-08-23 18:20:09 +0000413 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000414 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
415 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000416 "illegal to increase number of bytes loaded");
417
Tim Northover0f140c72016-09-09 11:46:34 +0000418 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
419 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
420 **MI.memoperands_begin());
421 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000422 MI.eraseFromParent();
423 return Legalized;
424 }
425 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000426 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
427 WideTy != LLT::scalar(8))
428 return UnableToLegalize;
429
430 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
431 auto Content = TLI.getBooleanContents(false, false);
432
433 unsigned ExtOp = TargetOpcode::G_ANYEXT;
434 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
435 ExtOp = TargetOpcode::G_ZEXT;
436 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
437 ExtOp = TargetOpcode::G_SEXT;
438 else
439 ExtOp = TargetOpcode::G_ANYEXT;
Tim Northover3c73e362016-08-23 18:20:09 +0000440
Tim Northover0f140c72016-09-09 11:46:34 +0000441 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover548feee2017-03-21 22:22:05 +0000442 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
443 MI.getOperand(0).getReg());
Tim Northover0f140c72016-09-09 11:46:34 +0000444 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
445 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000446 MI.eraseFromParent();
447 return Legalized;
448 }
Tim Northoverea904f92016-08-19 22:40:00 +0000449 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000450 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000451 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000452 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000453 MI.eraseFromParent();
454 return Legalized;
455 }
Tim Northovera11be042016-08-19 22:40:08 +0000456 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000457 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
458 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
459 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000460 MI.eraseFromParent();
461 return Legalized;
462 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000463 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000464 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
465 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
466 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000467 MI.eraseFromParent();
468 return Legalized;
469 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000470 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000471 assert(TypeIdx == 1 && "unable to legalize predicate");
472 bool IsSigned = CmpInst::isSigned(
473 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Tim Northover0f140c72016-09-09 11:46:34 +0000474 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
475 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
Tim Northover051b8ad2016-08-26 17:46:17 +0000476 if (IsSigned) {
Tim Northover0f140c72016-09-09 11:46:34 +0000477 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
478 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000479 } else {
Tim Northover0f140c72016-09-09 11:46:34 +0000480 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
481 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000482 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000483 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000484 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
485 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
486 MI.eraseFromParent();
487 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000488 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000489 case TargetOpcode::G_GEP: {
490 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
491 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
492 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
493 MI.getOperand(2).setReg(OffsetExt);
494 return Legalized;
495 }
Tim Northover32335812016-08-04 18:35:11 +0000496 }
Tim Northover33b07d62016-07-22 20:03:43 +0000497}
498
Tim Northover69fa84a2016-10-14 22:18:18 +0000499LegalizerHelper::LegalizeResult
500LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000501 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000502 MIRBuilder.setInstr(MI);
503
504 switch(MI.getOpcode()) {
505 default:
506 return UnableToLegalize;
507 case TargetOpcode::G_SREM:
508 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000509 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
510 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000511 .addDef(QuotReg)
512 .addUse(MI.getOperand(1).getReg())
513 .addUse(MI.getOperand(2).getReg());
514
Tim Northover0f140c72016-09-09 11:46:34 +0000515 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
516 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
517 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
518 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000519 MI.eraseFromParent();
520 return Legalized;
521 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000522 case TargetOpcode::G_SMULO:
523 case TargetOpcode::G_UMULO: {
524 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
525 // result.
526 unsigned Res = MI.getOperand(0).getReg();
527 unsigned Overflow = MI.getOperand(1).getReg();
528 unsigned LHS = MI.getOperand(2).getReg();
529 unsigned RHS = MI.getOperand(3).getReg();
530
531 MIRBuilder.buildMul(Res, LHS, RHS);
532
533 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
534 ? TargetOpcode::G_SMULH
535 : TargetOpcode::G_UMULH;
536
537 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
538 MIRBuilder.buildInstr(Opcode)
539 .addDef(HiPart)
540 .addUse(LHS)
541 .addUse(RHS);
542
543 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
544 MIRBuilder.buildConstant(Zero, 0);
545 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
546 MI.eraseFromParent();
547 return Legalized;
548 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000549 case TargetOpcode::G_FNEG: {
550 // TODO: Handle vector types once we are able to
551 // represent them.
552 if (Ty.isVector())
553 return UnableToLegalize;
554 unsigned Res = MI.getOperand(0).getReg();
555 Type *ZeroTy;
556 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
557 switch (Ty.getSizeInBits()) {
558 case 16:
559 ZeroTy = Type::getHalfTy(Ctx);
560 break;
561 case 32:
562 ZeroTy = Type::getFloatTy(Ctx);
563 break;
564 case 64:
565 ZeroTy = Type::getDoubleTy(Ctx);
566 break;
567 default:
568 llvm_unreachable("unexpected floating-point type");
569 }
570 ConstantFP &ZeroForNegation =
571 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
572 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
573 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
574 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
575 .addDef(Res)
576 .addUse(Zero)
577 .addUse(MI.getOperand(1).getReg());
578 MI.eraseFromParent();
579 return Legalized;
580 }
Volkan Keles225921a2017-03-10 21:25:09 +0000581 case TargetOpcode::G_FSUB: {
582 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
583 // First, check if G_FNEG is marked as Lower. If so, we may
584 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
585 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
586 return UnableToLegalize;
587 unsigned Res = MI.getOperand(0).getReg();
588 unsigned LHS = MI.getOperand(1).getReg();
589 unsigned RHS = MI.getOperand(2).getReg();
590 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
591 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
592 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
593 .addDef(Res)
594 .addUse(LHS)
595 .addUse(Neg);
596 MI.eraseFromParent();
597 return Legalized;
598 }
Tim Northovercecee562016-08-26 17:46:13 +0000599 }
600}
601
Tim Northover69fa84a2016-10-14 22:18:18 +0000602LegalizerHelper::LegalizeResult
603LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
604 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000605 // FIXME: Don't know how to handle secondary types yet.
606 if (TypeIdx != 0)
607 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000608 switch (MI.getOpcode()) {
609 default:
610 return UnableToLegalize;
611 case TargetOpcode::G_ADD: {
612 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000613 unsigned DstReg = MI.getOperand(0).getReg();
614 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
Tim Northover33b07d62016-07-22 20:03:43 +0000615
616 MIRBuilder.setInstr(MI);
617
Tim Northoverb18ea162016-09-20 15:20:36 +0000618 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000619 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
620 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
621
622 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000623 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
624 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000625 DstRegs.push_back(DstReg);
626 }
627
Tim Northoverbf017292017-03-03 22:46:09 +0000628 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000629 MI.eraseFromParent();
630 return Legalized;
631 }
632 }
633}