blob: 20358f7ee6c2ed99f5cc0890d1a94854b91b573a [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) {
Diana Picus1314a282017-04-11 10:52:34 +000069 case TargetOpcode::G_FADD:
70 assert((Size == 32 || Size == 64) && "Unsupported size");
71 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Tim Northovere0418412017-02-08 23:23:39 +000072 case TargetOpcode::G_FREM:
73 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
74 case TargetOpcode::G_FPOW:
75 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
76 }
77 llvm_unreachable("Unknown libcall function");
78}
79
Tim Northover69fa84a2016-10-14 22:18:18 +000080LegalizerHelper::LegalizeResult
81LegalizerHelper::libcall(MachineInstr &MI) {
Tim Northover0f140c72016-09-09 11:46:34 +000082 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
83 unsigned Size = Ty.getSizeInBits();
Tim Northoveredb3c8c2016-08-29 19:07:16 +000084 MIRBuilder.setInstr(MI);
85
86 switch (MI.getOpcode()) {
87 default:
88 return UnableToLegalize;
Diana Picus1314a282017-04-11 10:52:34 +000089 case TargetOpcode::G_FADD:
Tim Northovere0418412017-02-08 23:23:39 +000090 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +000091 case TargetOpcode::G_FREM: {
Tim Northover11a23542016-08-31 21:24:02 +000092 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
93 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Tim Northoveredb3c8c2016-08-29 19:07:16 +000094 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
95 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picusd79253a2017-03-20 14:40:18 +000096 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
97 const char *Name = TLI.getLibcallName(Libcall);
Tim Northoverd1e951e2017-03-09 22:00:39 +000098 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northover9a467182016-09-21 12:57:45 +000099 CLI.lowerCall(
Diana Picusd79253a2017-03-20 14:40:18 +0000100 MIRBuilder, TLI.getLibcallCallingConv(Libcall),
101 MachineOperand::CreateES(Name), {MI.getOperand(0).getReg(), Ty},
Tim Northover9a467182016-09-21 12:57:45 +0000102 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000103 MI.eraseFromParent();
104 return Legalized;
105 }
106 }
107}
108
Tim Northover69fa84a2016-10-14 22:18:18 +0000109LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
110 unsigned TypeIdx,
111 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000112 // FIXME: Don't know how to handle secondary types yet.
113 if (TypeIdx != 0)
114 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000115
116 MIRBuilder.setInstr(MI);
117
Tim Northover9656f142016-08-04 20:54:13 +0000118 switch (MI.getOpcode()) {
119 default:
120 return UnableToLegalize;
121 case TargetOpcode::G_ADD: {
122 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Tim Northover0f140c72016-09-09 11:46:34 +0000123 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
124 NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000125
Tim Northoverb18ea162016-09-20 15:20:36 +0000126 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000127 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
128 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
129
Tim Northover0f140c72016-09-09 11:46:34 +0000130 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
131 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000132
133 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000134 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
135 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000136
Tim Northover0f140c72016-09-09 11:46:34 +0000137 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000138 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000139
140 DstRegs.push_back(DstReg);
Tim Northover9656f142016-08-04 20:54:13 +0000141 CarryIn = CarryOut;
142 }
Tim Northover0f140c72016-09-09 11:46:34 +0000143 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000144 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000145 MI.eraseFromParent();
146 return Legalized;
147 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000148 case TargetOpcode::G_INSERT: {
149 if (TypeIdx != 0)
150 return UnableToLegalize;
151
Tim Northover75e0b912017-03-06 18:23:04 +0000152 int64_t NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000153 int NumParts =
154 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
155
156 SmallVector<unsigned, 2> SrcRegs, DstRegs;
157 SmallVector<uint64_t, 2> Indexes;
158 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
159
Tim Northover75e0b912017-03-06 18:23:04 +0000160 unsigned OpReg = MI.getOperand(2).getReg();
161 int64_t OpStart = MI.getOperand(3).getImm();
162 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000163 for (int i = 0; i < NumParts; ++i) {
164 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000165
Tim Northover75e0b912017-03-06 18:23:04 +0000166 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000167 // No part of the insert affects this subregister, forward the original.
168 DstRegs.push_back(SrcRegs[i]);
169 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000170 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000171 // The entire subregister is defined by this insert, forward the new
172 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000173 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000174 continue;
175 }
176
Tim Northover2eb18d32017-03-07 21:24:33 +0000177 // OpSegStart is where this destination segment would start in OpReg if it
178 // extended infinitely in both directions.
179 int64_t ExtractOffset, InsertOffset, SegSize;
180 if (OpStart < DstStart) {
181 InsertOffset = 0;
182 ExtractOffset = DstStart - OpStart;
183 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
184 } else {
185 InsertOffset = OpStart - DstStart;
186 ExtractOffset = 0;
187 SegSize =
188 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
189 }
190
191 unsigned SegReg = OpReg;
192 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000193 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000194 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
195 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000196 }
197
Tim Northover75e0b912017-03-06 18:23:04 +0000198 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000199 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000200 DstRegs.push_back(DstReg);
201 }
202
203 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000204 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000205 MI.eraseFromParent();
206 return Legalized;
207 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000208 case TargetOpcode::G_LOAD: {
209 unsigned NarrowSize = NarrowTy.getSizeInBits();
210 int NumParts =
211 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
212 LLT NarrowPtrTy = LLT::pointer(
213 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
214
215 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000216 for (int i = 0; i < NumParts; ++i) {
217 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
218 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
219 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
220
221 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
222 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000223 // TODO: This is conservatively correct, but we probably want to split the
224 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000225 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
226
227 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000228 }
229 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000230 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000231 MI.eraseFromParent();
232 return Legalized;
233 }
Justin Bognerfde01042017-01-18 17:29:54 +0000234 case TargetOpcode::G_STORE: {
235 unsigned NarrowSize = NarrowTy.getSizeInBits();
236 int NumParts =
237 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
238 LLT NarrowPtrTy = LLT::pointer(
239 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
240
241 SmallVector<unsigned, 2> SrcRegs;
242 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
243
244 for (int i = 0; i < NumParts; ++i) {
245 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
246 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
247 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
248 MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
Justin Bognere094cc42017-01-20 00:30:17 +0000249 // TODO: This is conservatively correct, but we probably want to split the
250 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000251 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
252 }
253 MI.eraseFromParent();
254 return Legalized;
255 }
Igor Breger29537882017-04-07 14:41:59 +0000256 case TargetOpcode::G_CONSTANT: {
257 unsigned NarrowSize = NarrowTy.getSizeInBits();
258 int NumParts =
259 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
260 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
261 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
262
263 SmallVector<unsigned, 2> DstRegs;
264 for (int i = 0; i < NumParts; ++i) {
265 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
266 ConstantInt *CI =
267 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
268 MIRBuilder.buildConstant(DstReg, *CI);
269 DstRegs.push_back(DstReg);
270 }
271 unsigned DstReg = MI.getOperand(0).getReg();
272 MIRBuilder.buildMerge(DstReg, DstRegs);
273 MI.eraseFromParent();
274 return Legalized;
275 }
Tim Northover9656f142016-08-04 20:54:13 +0000276 }
Tim Northover33b07d62016-07-22 20:03:43 +0000277}
278
Tim Northover69fa84a2016-10-14 22:18:18 +0000279LegalizerHelper::LegalizeResult
280LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000281 MIRBuilder.setInstr(MI);
282
Tim Northover32335812016-08-04 18:35:11 +0000283 switch (MI.getOpcode()) {
284 default:
285 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000286 case TargetOpcode::G_ADD:
287 case TargetOpcode::G_AND:
288 case TargetOpcode::G_MUL:
289 case TargetOpcode::G_OR:
290 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000291 case TargetOpcode::G_SUB:
292 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000293 // Perform operation at larger width (any extension is fine here, high bits
294 // don't affect the result) and then truncate the result back to the
295 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000296 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
297 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
298 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
299 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000300
Tim Northover0f140c72016-09-09 11:46:34 +0000301 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
302 MIRBuilder.buildInstr(MI.getOpcode())
303 .addDef(DstExt)
304 .addUse(Src1Ext)
305 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000306
Tim Northover0f140c72016-09-09 11:46:34 +0000307 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000308 MI.eraseFromParent();
309 return Legalized;
310 }
Tim Northover7a753d92016-08-26 17:46:06 +0000311 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000312 case TargetOpcode::G_UDIV:
313 case TargetOpcode::G_ASHR:
314 case TargetOpcode::G_LSHR: {
315 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
316 MI.getOpcode() == TargetOpcode::G_ASHR
317 ? TargetOpcode::G_SEXT
318 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000319
Tim Northover0f140c72016-09-09 11:46:34 +0000320 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
321 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
322 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000323
Tim Northover0f140c72016-09-09 11:46:34 +0000324 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
325 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
326 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000327
Tim Northover0f140c72016-09-09 11:46:34 +0000328 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
329 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000330 .addDef(ResExt)
331 .addUse(LHSExt)
332 .addUse(RHSExt);
333
Tim Northover0f140c72016-09-09 11:46:34 +0000334 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000335 MI.eraseFromParent();
336 return Legalized;
337 }
Tim Northover868332d2017-02-06 23:41:27 +0000338 case TargetOpcode::G_SELECT: {
339 if (TypeIdx != 0)
340 return UnableToLegalize;
341
342 // Perform operation at larger width (any extension is fine here, high bits
343 // don't affect the result) and then truncate the result back to the
344 // original type.
345 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
346 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
347 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
348 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
349
350 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
351 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
352 .addDef(DstExt)
353 .addReg(MI.getOperand(1).getReg())
354 .addUse(Src1Ext)
355 .addUse(Src2Ext);
356
357 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
358 MI.eraseFromParent();
359 return Legalized;
360 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000361 case TargetOpcode::G_FPTOSI:
362 case TargetOpcode::G_FPTOUI: {
363 if (TypeIdx != 0)
364 return UnableToLegalize;
365
366 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
367 MIRBuilder.buildInstr(MI.getOpcode())
368 .addDef(DstExt)
369 .addUse(MI.getOperand(1).getReg());
370
371 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
372 MI.eraseFromParent();
373 return Legalized;
374 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000375 case TargetOpcode::G_SITOFP:
376 case TargetOpcode::G_UITOFP: {
377 if (TypeIdx != 1)
378 return UnableToLegalize;
379
380 unsigned Src = MI.getOperand(1).getReg();
381 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
382
383 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
384 MIRBuilder.buildSExt(SrcExt, Src);
385 } else {
386 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
387 MIRBuilder.buildZExt(SrcExt, Src);
388 }
389
390 MIRBuilder.buildInstr(MI.getOpcode())
391 .addDef(MI.getOperand(0).getReg())
392 .addUse(SrcExt);
393
394 MI.eraseFromParent();
395 return Legalized;
396 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000397 case TargetOpcode::G_INSERT: {
398 if (TypeIdx != 0)
399 return UnableToLegalize;
400
401 unsigned Src = MI.getOperand(1).getReg();
402 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
403 MIRBuilder.buildAnyExt(SrcExt, Src);
404
405 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
406 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
407 MI.getOperand(3).getImm());
408 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
409 MIB.addReg(MI.getOperand(OpNum).getReg());
410 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
411 }
412
413 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
414 MI.eraseFromParent();
415 return Legalized;
416 }
Tim Northover3c73e362016-08-23 18:20:09 +0000417 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000418 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
419 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000420 "illegal to increase number of bytes loaded");
421
Tim Northover0f140c72016-09-09 11:46:34 +0000422 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
423 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
424 **MI.memoperands_begin());
425 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000426 MI.eraseFromParent();
427 return Legalized;
428 }
429 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000430 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
431 WideTy != LLT::scalar(8))
432 return UnableToLegalize;
433
434 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
435 auto Content = TLI.getBooleanContents(false, false);
436
437 unsigned ExtOp = TargetOpcode::G_ANYEXT;
438 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
439 ExtOp = TargetOpcode::G_ZEXT;
440 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
441 ExtOp = TargetOpcode::G_SEXT;
442 else
443 ExtOp = TargetOpcode::G_ANYEXT;
Tim Northover3c73e362016-08-23 18:20:09 +0000444
Tim Northover0f140c72016-09-09 11:46:34 +0000445 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover548feee2017-03-21 22:22:05 +0000446 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
447 MI.getOperand(0).getReg());
Tim Northover0f140c72016-09-09 11:46:34 +0000448 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
449 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000450 MI.eraseFromParent();
451 return Legalized;
452 }
Tim Northoverea904f92016-08-19 22:40:00 +0000453 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000454 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000455 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000456 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000457 MI.eraseFromParent();
458 return Legalized;
459 }
Tim Northovera11be042016-08-19 22:40:08 +0000460 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000461 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
462 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
463 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000464 MI.eraseFromParent();
465 return Legalized;
466 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000467 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000468 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
469 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
470 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000471 MI.eraseFromParent();
472 return Legalized;
473 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000474 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000475 assert(TypeIdx == 1 && "unable to legalize predicate");
476 bool IsSigned = CmpInst::isSigned(
477 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Tim Northover0f140c72016-09-09 11:46:34 +0000478 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
479 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
Tim Northover051b8ad2016-08-26 17:46:17 +0000480 if (IsSigned) {
Tim Northover0f140c72016-09-09 11:46:34 +0000481 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
482 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000483 } else {
Tim Northover0f140c72016-09-09 11:46:34 +0000484 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
485 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
Tim Northover6cd4b232016-08-23 21:01:26 +0000486 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000487 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000488 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
489 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
490 MI.eraseFromParent();
491 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000492 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000493 case TargetOpcode::G_GEP: {
494 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
495 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
496 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
497 MI.getOperand(2).setReg(OffsetExt);
498 return Legalized;
499 }
Tim Northover32335812016-08-04 18:35:11 +0000500 }
Tim Northover33b07d62016-07-22 20:03:43 +0000501}
502
Tim Northover69fa84a2016-10-14 22:18:18 +0000503LegalizerHelper::LegalizeResult
504LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000505 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000506 MIRBuilder.setInstr(MI);
507
508 switch(MI.getOpcode()) {
509 default:
510 return UnableToLegalize;
511 case TargetOpcode::G_SREM:
512 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000513 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
514 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000515 .addDef(QuotReg)
516 .addUse(MI.getOperand(1).getReg())
517 .addUse(MI.getOperand(2).getReg());
518
Tim Northover0f140c72016-09-09 11:46:34 +0000519 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
520 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
521 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
522 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000523 MI.eraseFromParent();
524 return Legalized;
525 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000526 case TargetOpcode::G_SMULO:
527 case TargetOpcode::G_UMULO: {
528 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
529 // result.
530 unsigned Res = MI.getOperand(0).getReg();
531 unsigned Overflow = MI.getOperand(1).getReg();
532 unsigned LHS = MI.getOperand(2).getReg();
533 unsigned RHS = MI.getOperand(3).getReg();
534
535 MIRBuilder.buildMul(Res, LHS, RHS);
536
537 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
538 ? TargetOpcode::G_SMULH
539 : TargetOpcode::G_UMULH;
540
541 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
542 MIRBuilder.buildInstr(Opcode)
543 .addDef(HiPart)
544 .addUse(LHS)
545 .addUse(RHS);
546
547 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
548 MIRBuilder.buildConstant(Zero, 0);
549 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
550 MI.eraseFromParent();
551 return Legalized;
552 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000553 case TargetOpcode::G_FNEG: {
554 // TODO: Handle vector types once we are able to
555 // represent them.
556 if (Ty.isVector())
557 return UnableToLegalize;
558 unsigned Res = MI.getOperand(0).getReg();
559 Type *ZeroTy;
560 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
561 switch (Ty.getSizeInBits()) {
562 case 16:
563 ZeroTy = Type::getHalfTy(Ctx);
564 break;
565 case 32:
566 ZeroTy = Type::getFloatTy(Ctx);
567 break;
568 case 64:
569 ZeroTy = Type::getDoubleTy(Ctx);
570 break;
571 default:
572 llvm_unreachable("unexpected floating-point type");
573 }
574 ConstantFP &ZeroForNegation =
575 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
576 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
577 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
578 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
579 .addDef(Res)
580 .addUse(Zero)
581 .addUse(MI.getOperand(1).getReg());
582 MI.eraseFromParent();
583 return Legalized;
584 }
Volkan Keles225921a2017-03-10 21:25:09 +0000585 case TargetOpcode::G_FSUB: {
586 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
587 // First, check if G_FNEG is marked as Lower. If so, we may
588 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
589 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
590 return UnableToLegalize;
591 unsigned Res = MI.getOperand(0).getReg();
592 unsigned LHS = MI.getOperand(1).getReg();
593 unsigned RHS = MI.getOperand(2).getReg();
594 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
595 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
596 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
597 .addDef(Res)
598 .addUse(LHS)
599 .addUse(Neg);
600 MI.eraseFromParent();
601 return Legalized;
602 }
Tim Northovercecee562016-08-26 17:46:13 +0000603 }
604}
605
Tim Northover69fa84a2016-10-14 22:18:18 +0000606LegalizerHelper::LegalizeResult
607LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
608 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000609 // FIXME: Don't know how to handle secondary types yet.
610 if (TypeIdx != 0)
611 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000612 switch (MI.getOpcode()) {
613 default:
614 return UnableToLegalize;
615 case TargetOpcode::G_ADD: {
616 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000617 unsigned DstReg = MI.getOperand(0).getReg();
618 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
Tim Northover33b07d62016-07-22 20:03:43 +0000619
620 MIRBuilder.setInstr(MI);
621
Tim Northoverb18ea162016-09-20 15:20:36 +0000622 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000623 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
624 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
625
626 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000627 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
628 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000629 DstRegs.push_back(DstReg);
Tim Northover33b07d62016-07-22 20:03:43 +0000630 }
631
Tim Northoverbf017292017-03-03 22:46:09 +0000632 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000633 MI.eraseFromParent();
634 return Legalized;
635 }
636 }
637}