blob: a70e46e67df600dee2fdc83197d3791b5a26e2d6 [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
Daniel Sanders5377fb32017-04-20 15:46:12 +000027#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000028
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) {
Daniel Sanders5377fb32017-04-20 15:46:12 +000038 DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
39
Volkan Keles685fbda2017-03-10 18:34:57 +000040 auto Action = LI.getAction(MI, MRI);
Tim Northovera01bece2016-08-23 19:30:42 +000041 switch (std::get<0>(Action)) {
Tim Northover69fa84a2016-10-14 22:18:18 +000042 case LegalizerInfo::Legal:
Daniel Sanders5377fb32017-04-20 15:46:12 +000043 DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000044 return AlreadyLegal;
Tim Northover69fa84a2016-10-14 22:18:18 +000045 case LegalizerInfo::Libcall:
Daniel Sanders5377fb32017-04-20 15:46:12 +000046 DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000047 return libcall(MI);
Tim Northover69fa84a2016-10-14 22:18:18 +000048 case LegalizerInfo::NarrowScalar:
Daniel Sanders5377fb32017-04-20 15:46:12 +000049 DEBUG(dbgs() << ".. Narrow scalar\n");
Tim Northovera01bece2016-08-23 19:30:42 +000050 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000051 case LegalizerInfo::WidenScalar:
Daniel Sanders5377fb32017-04-20 15:46:12 +000052 DEBUG(dbgs() << ".. Widen scalar\n");
Tim Northovera01bece2016-08-23 19:30:42 +000053 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000054 case LegalizerInfo::Lower:
Daniel Sanders5377fb32017-04-20 15:46:12 +000055 DEBUG(dbgs() << ".. Lower\n");
Tim Northovercecee562016-08-26 17:46:13 +000056 return lower(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000057 case LegalizerInfo::FewerElements:
Daniel Sanders5377fb32017-04-20 15:46:12 +000058 DEBUG(dbgs() << ".. Reduce number of elements\n");
Tim Northovera01bece2016-08-23 19:30:42 +000059 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover91366172017-02-15 23:22:50 +000060 case LegalizerInfo::Custom:
Daniel Sanders5377fb32017-04-20 15:46:12 +000061 DEBUG(dbgs() << ".. Custom legalization\n");
Volkan Keles685fbda2017-03-10 18:34:57 +000062 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
63 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000064 default:
Daniel Sanders5377fb32017-04-20 15:46:12 +000065 DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000066 return UnableToLegalize;
67 }
68}
69
Tim Northover69fa84a2016-10-14 22:18:18 +000070void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
71 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000072 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000073 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000074 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000075}
76
Tim Northovere0418412017-02-08 23:23:39 +000077static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
78 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000079 case TargetOpcode::G_SDIV:
80 assert(Size == 32 && "Unsupported size");
81 return RTLIB::SDIV_I32;
82 case TargetOpcode::G_UDIV:
83 assert(Size == 32 && "Unsupported size");
84 return RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000085 case TargetOpcode::G_SREM:
86 assert(Size == 32 && "Unsupported size");
87 return RTLIB::SREM_I32;
88 case TargetOpcode::G_UREM:
89 assert(Size == 32 && "Unsupported size");
90 return RTLIB::UREM_I32;
Diana Picus1314a282017-04-11 10:52:34 +000091 case TargetOpcode::G_FADD:
92 assert((Size == 32 || Size == 64) && "Unsupported size");
93 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Tim Northovere0418412017-02-08 23:23:39 +000094 case TargetOpcode::G_FREM:
95 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
96 case TargetOpcode::G_FPOW:
97 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
98 }
99 llvm_unreachable("Unknown libcall function");
100}
101
Diana Picusfc1675e2017-07-05 12:57:24 +0000102LegalizerHelper::LegalizeResult
103llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
104 const CallLowering::ArgInfo &Result,
105 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000106 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
107 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000108 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000109
Diana Picuse97822e2017-04-24 07:22:31 +0000110 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000111 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
112 MachineOperand::CreateES(Name), Result, Args))
113 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000114
Diana Picuse97822e2017-04-24 07:22:31 +0000115 return LegalizerHelper::Legalized;
116}
117
Diana Picus02e11012017-06-15 10:53:31 +0000118static LegalizerHelper::LegalizeResult
119simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
120 Type *OpType) {
121 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000122 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
123 {{MI.getOperand(1).getReg(), OpType},
124 {MI.getOperand(2).getReg(), OpType}});
Diana Picus02e11012017-06-15 10:53:31 +0000125}
126
Tim Northover69fa84a2016-10-14 22:18:18 +0000127LegalizerHelper::LegalizeResult
128LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000129 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
130 unsigned Size = LLTy.getSizeInBits();
Diana Picuse97822e2017-04-24 07:22:31 +0000131 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000132
Diana Picusfc1675e2017-07-05 12:57:24 +0000133 MIRBuilder.setInstr(MI);
134
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000135 switch (MI.getOpcode()) {
136 default:
137 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000138 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000139 case TargetOpcode::G_UDIV:
140 case TargetOpcode::G_SREM:
141 case TargetOpcode::G_UREM: {
142 Type *HLTy = Type::getInt32Ty(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000143 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
144 if (Status != Legalized)
145 return Status;
146 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000147 }
Diana Picus1314a282017-04-11 10:52:34 +0000148 case TargetOpcode::G_FADD:
Tim Northovere0418412017-02-08 23:23:39 +0000149 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000150 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000151 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000152 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
153 if (Status != Legalized)
154 return Status;
155 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000156 }
157 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000158
159 MI.eraseFromParent();
160 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000161}
162
Tim Northover69fa84a2016-10-14 22:18:18 +0000163LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
164 unsigned TypeIdx,
165 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000166 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000167 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000168 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000169
170 MIRBuilder.setInstr(MI);
171
Tim Northover9656f142016-08-04 20:54:13 +0000172 switch (MI.getOpcode()) {
173 default:
174 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000175 case TargetOpcode::G_IMPLICIT_DEF: {
176 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
177 NarrowTy.getSizeInBits();
178
179 SmallVector<unsigned, 2> DstRegs;
180 for (int i = 0; i < NumParts; ++i) {
181 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
182 MIRBuilder.buildUndef(Dst);
183 DstRegs.push_back(Dst);
184 }
185 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
186 MI.eraseFromParent();
187 return Legalized;
188 }
Tim Northover9656f142016-08-04 20:54:13 +0000189 case TargetOpcode::G_ADD: {
190 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Tim Northover0f140c72016-09-09 11:46:34 +0000191 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
192 NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000193
Tim Northoverb18ea162016-09-20 15:20:36 +0000194 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000195 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
196 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
197
Tim Northover0f140c72016-09-09 11:46:34 +0000198 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
199 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000200
201 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000202 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
203 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000204
Tim Northover0f140c72016-09-09 11:46:34 +0000205 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000206 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000207
208 DstRegs.push_back(DstReg);
209 CarryIn = CarryOut;
210 }
Tim Northover0f140c72016-09-09 11:46:34 +0000211 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000212 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000213 MI.eraseFromParent();
214 return Legalized;
215 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000216 case TargetOpcode::G_EXTRACT: {
217 if (TypeIdx != 1)
218 return UnableToLegalize;
219
220 int64_t NarrowSize = NarrowTy.getSizeInBits();
221 int NumParts =
222 MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() / NarrowSize;
223
224 SmallVector<unsigned, 2> SrcRegs, DstRegs;
225 SmallVector<uint64_t, 2> Indexes;
226 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
227
228 unsigned OpReg = MI.getOperand(0).getReg();
229 int64_t OpStart = MI.getOperand(2).getImm();
230 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
231 for (int i = 0; i < NumParts; ++i) {
232 unsigned SrcStart = i * NarrowSize;
233
234 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
235 // No part of the extract uses this subregister, ignore it.
236 continue;
237 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
238 // The entire subregister is extracted, forward the value.
239 DstRegs.push_back(SrcRegs[i]);
240 continue;
241 }
242
243 // OpSegStart is where this destination segment would start in OpReg if it
244 // extended infinitely in both directions.
245 int64_t ExtractOffset, SegSize;
246 if (OpStart < SrcStart) {
247 ExtractOffset = 0;
248 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
249 } else {
250 ExtractOffset = OpStart - SrcStart;
251 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
252 }
253
254 unsigned SegReg = SrcRegs[i];
255 if (ExtractOffset != 0 || SegSize != NarrowSize) {
256 // A genuine extract is needed.
257 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
258 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
259 }
260
261 DstRegs.push_back(SegReg);
262 }
263
264 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
265 MI.eraseFromParent();
266 return Legalized;
267 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000268 case TargetOpcode::G_INSERT: {
269 if (TypeIdx != 0)
270 return UnableToLegalize;
271
Tim Northover75e0b912017-03-06 18:23:04 +0000272 int64_t NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000273 int NumParts =
274 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
275
276 SmallVector<unsigned, 2> SrcRegs, DstRegs;
277 SmallVector<uint64_t, 2> Indexes;
278 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
279
Tim Northover75e0b912017-03-06 18:23:04 +0000280 unsigned OpReg = MI.getOperand(2).getReg();
281 int64_t OpStart = MI.getOperand(3).getImm();
282 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000283 for (int i = 0; i < NumParts; ++i) {
284 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000285
Tim Northover75e0b912017-03-06 18:23:04 +0000286 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000287 // No part of the insert affects this subregister, forward the original.
288 DstRegs.push_back(SrcRegs[i]);
289 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000290 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000291 // The entire subregister is defined by this insert, forward the new
292 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000293 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000294 continue;
295 }
296
Tim Northover2eb18d32017-03-07 21:24:33 +0000297 // OpSegStart is where this destination segment would start in OpReg if it
298 // extended infinitely in both directions.
299 int64_t ExtractOffset, InsertOffset, SegSize;
300 if (OpStart < DstStart) {
301 InsertOffset = 0;
302 ExtractOffset = DstStart - OpStart;
303 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
304 } else {
305 InsertOffset = OpStart - DstStart;
306 ExtractOffset = 0;
307 SegSize =
308 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
309 }
310
311 unsigned SegReg = OpReg;
312 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000313 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000314 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
315 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000316 }
317
Tim Northover75e0b912017-03-06 18:23:04 +0000318 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000319 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000320 DstRegs.push_back(DstReg);
321 }
322
323 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000324 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000325 MI.eraseFromParent();
326 return Legalized;
327 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000328 case TargetOpcode::G_LOAD: {
329 unsigned NarrowSize = NarrowTy.getSizeInBits();
330 int NumParts =
331 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000332 LLT OffsetTy = LLT::scalar(
333 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000334
335 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000336 for (int i = 0; i < NumParts; ++i) {
337 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000338 unsigned SrcReg = 0;
339 unsigned Adjustment = i * NarrowSize / 8;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000340
Daniel Sanders4e523662017-06-13 23:42:32 +0000341 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
342 Adjustment);
343
Justin Bognere094cc42017-01-20 00:30:17 +0000344 // TODO: This is conservatively correct, but we probably want to split the
345 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000346 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
347
348 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000349 }
350 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000351 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000352 MI.eraseFromParent();
353 return Legalized;
354 }
Justin Bognerfde01042017-01-18 17:29:54 +0000355 case TargetOpcode::G_STORE: {
356 unsigned NarrowSize = NarrowTy.getSizeInBits();
357 int NumParts =
358 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000359 LLT OffsetTy = LLT::scalar(
360 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000361
362 SmallVector<unsigned, 2> SrcRegs;
363 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
364
365 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000366 unsigned DstReg = 0;
367 unsigned Adjustment = i * NarrowSize / 8;
368
369 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
370 Adjustment);
371
Justin Bognere094cc42017-01-20 00:30:17 +0000372 // TODO: This is conservatively correct, but we probably want to split the
373 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000374 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
375 }
376 MI.eraseFromParent();
377 return Legalized;
378 }
Igor Breger29537882017-04-07 14:41:59 +0000379 case TargetOpcode::G_CONSTANT: {
380 unsigned NarrowSize = NarrowTy.getSizeInBits();
381 int NumParts =
382 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
383 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
384 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
385
386 SmallVector<unsigned, 2> DstRegs;
387 for (int i = 0; i < NumParts; ++i) {
388 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
389 ConstantInt *CI =
390 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
391 MIRBuilder.buildConstant(DstReg, *CI);
392 DstRegs.push_back(DstReg);
393 }
394 unsigned DstReg = MI.getOperand(0).getReg();
395 MIRBuilder.buildMerge(DstReg, DstRegs);
396 MI.eraseFromParent();
397 return Legalized;
398 }
Tim Northover9656f142016-08-04 20:54:13 +0000399 }
Tim Northover33b07d62016-07-22 20:03:43 +0000400}
401
Tim Northover69fa84a2016-10-14 22:18:18 +0000402LegalizerHelper::LegalizeResult
403LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000404 MIRBuilder.setInstr(MI);
405
Tim Northover32335812016-08-04 18:35:11 +0000406 switch (MI.getOpcode()) {
407 default:
408 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000409 case TargetOpcode::G_ADD:
410 case TargetOpcode::G_AND:
411 case TargetOpcode::G_MUL:
412 case TargetOpcode::G_OR:
413 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000414 case TargetOpcode::G_SUB:
415 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000416 // Perform operation at larger width (any extension is fine here, high bits
417 // don't affect the result) and then truncate the result back to the
418 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000419 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
420 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
421 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
422 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000423
Tim Northover0f140c72016-09-09 11:46:34 +0000424 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
425 MIRBuilder.buildInstr(MI.getOpcode())
426 .addDef(DstExt)
427 .addUse(Src1Ext)
428 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000429
Tim Northover0f140c72016-09-09 11:46:34 +0000430 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000431 MI.eraseFromParent();
432 return Legalized;
433 }
Tim Northover7a753d92016-08-26 17:46:06 +0000434 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000435 case TargetOpcode::G_UDIV:
Diana Picusdf4100b2017-07-18 09:08:47 +0000436 case TargetOpcode::G_SREM:
437 case TargetOpcode::G_UREM:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000438 case TargetOpcode::G_ASHR:
439 case TargetOpcode::G_LSHR: {
440 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
Diana Picusdf4100b2017-07-18 09:08:47 +0000441 MI.getOpcode() == TargetOpcode::G_SREM ||
Justin Bognerddb80ae2017-01-19 07:51:17 +0000442 MI.getOpcode() == TargetOpcode::G_ASHR
443 ? TargetOpcode::G_SEXT
444 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000445
Tim Northover0f140c72016-09-09 11:46:34 +0000446 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
447 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
448 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000449
Tim Northover0f140c72016-09-09 11:46:34 +0000450 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
451 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
452 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000453
Tim Northover0f140c72016-09-09 11:46:34 +0000454 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
455 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000456 .addDef(ResExt)
457 .addUse(LHSExt)
458 .addUse(RHSExt);
459
Tim Northover0f140c72016-09-09 11:46:34 +0000460 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000461 MI.eraseFromParent();
462 return Legalized;
463 }
Tim Northover868332d2017-02-06 23:41:27 +0000464 case TargetOpcode::G_SELECT: {
465 if (TypeIdx != 0)
466 return UnableToLegalize;
467
468 // Perform operation at larger width (any extension is fine here, high bits
469 // don't affect the result) and then truncate the result back to the
470 // original type.
471 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
472 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
473 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
474 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
475
476 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
477 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
478 .addDef(DstExt)
479 .addReg(MI.getOperand(1).getReg())
480 .addUse(Src1Ext)
481 .addUse(Src2Ext);
482
483 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
484 MI.eraseFromParent();
485 return Legalized;
486 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000487 case TargetOpcode::G_FPTOSI:
488 case TargetOpcode::G_FPTOUI: {
489 if (TypeIdx != 0)
490 return UnableToLegalize;
491
492 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
493 MIRBuilder.buildInstr(MI.getOpcode())
494 .addDef(DstExt)
495 .addUse(MI.getOperand(1).getReg());
496
497 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
498 MI.eraseFromParent();
499 return Legalized;
500 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000501 case TargetOpcode::G_SITOFP:
502 case TargetOpcode::G_UITOFP: {
503 if (TypeIdx != 1)
504 return UnableToLegalize;
505
506 unsigned Src = MI.getOperand(1).getReg();
507 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
508
509 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
510 MIRBuilder.buildSExt(SrcExt, Src);
511 } else {
512 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
513 MIRBuilder.buildZExt(SrcExt, Src);
514 }
515
516 MIRBuilder.buildInstr(MI.getOpcode())
517 .addDef(MI.getOperand(0).getReg())
518 .addUse(SrcExt);
519
520 MI.eraseFromParent();
521 return Legalized;
522 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000523 case TargetOpcode::G_INSERT: {
524 if (TypeIdx != 0)
525 return UnableToLegalize;
526
527 unsigned Src = MI.getOperand(1).getReg();
528 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
529 MIRBuilder.buildAnyExt(SrcExt, Src);
530
531 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
532 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
533 MI.getOperand(3).getImm());
534 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
535 MIB.addReg(MI.getOperand(OpNum).getReg());
536 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
537 }
538
539 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
540 MI.eraseFromParent();
541 return Legalized;
542 }
Tim Northover3c73e362016-08-23 18:20:09 +0000543 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000544 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
545 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000546 "illegal to increase number of bytes loaded");
547
Tim Northover0f140c72016-09-09 11:46:34 +0000548 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
549 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
550 **MI.memoperands_begin());
551 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000552 MI.eraseFromParent();
553 return Legalized;
554 }
555 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000556 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
557 WideTy != LLT::scalar(8))
558 return UnableToLegalize;
559
560 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
561 auto Content = TLI.getBooleanContents(false, false);
562
563 unsigned ExtOp = TargetOpcode::G_ANYEXT;
564 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
565 ExtOp = TargetOpcode::G_ZEXT;
566 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
567 ExtOp = TargetOpcode::G_SEXT;
568 else
569 ExtOp = TargetOpcode::G_ANYEXT;
Tim Northover3c73e362016-08-23 18:20:09 +0000570
Tim Northover0f140c72016-09-09 11:46:34 +0000571 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover548feee2017-03-21 22:22:05 +0000572 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
573 MI.getOperand(0).getReg());
Tim Northover0f140c72016-09-09 11:46:34 +0000574 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
575 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000576 MI.eraseFromParent();
577 return Legalized;
578 }
Tim Northoverea904f92016-08-19 22:40:00 +0000579 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000580 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000581 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000582 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000583 MI.eraseFromParent();
584 return Legalized;
585 }
Tim Northovera11be042016-08-19 22:40:08 +0000586 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000587 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
588 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
589 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000590 MI.eraseFromParent();
591 return Legalized;
592 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000593 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000594 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
595 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
596 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000597 MI.eraseFromParent();
598 return Legalized;
599 }
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000600 case TargetOpcode::G_FCMP: {
601 unsigned Op0Ext, Op1Ext, DstReg;
602 unsigned Cmp1 = MI.getOperand(2).getReg();
603 unsigned Cmp2 = MI.getOperand(3).getReg();
604 if (TypeIdx == 0) {
605 Op0Ext = Cmp1;
606 Op1Ext = Cmp2;
607 DstReg = MRI.createGenericVirtualRegister(WideTy);
608 } else {
609 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
610 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
611 DstReg = MI.getOperand(0).getReg();
612 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1);
613 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2);
614 }
615 MIRBuilder.buildFCmp(
616 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
617 DstReg, Op0Ext, Op1Ext);
618 if (TypeIdx == 0)
619 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
620 DstReg);
621 MI.eraseFromParent();
622 return Legalized;
623 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000624 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000625 bool IsSigned = CmpInst::isSigned(
626 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000627 unsigned Cmp1 = MI.getOperand(2).getReg();
628 unsigned Cmp2 = MI.getOperand(3).getReg();
629 unsigned Op0Ext, Op1Ext, DstReg;
630 if (TypeIdx == 0) {
631 Op0Ext = Cmp1;
632 Op1Ext = Cmp2;
633 DstReg = MRI.createGenericVirtualRegister(WideTy);
Tim Northover6cd4b232016-08-23 21:01:26 +0000634 } else {
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000635 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
636 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
637 DstReg = MI.getOperand(0).getReg();
638 if (IsSigned) {
639 MIRBuilder.buildSExt(Op0Ext, Cmp1);
640 MIRBuilder.buildSExt(Op1Ext, Cmp2);
641 } else {
642 MIRBuilder.buildZExt(Op0Ext, Cmp1);
643 MIRBuilder.buildZExt(Op1Ext, Cmp2);
644 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000645 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000646 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000647 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000648 DstReg, Op0Ext, Op1Ext);
649 if (TypeIdx == 0)
650 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
651 DstReg);
Tim Northover051b8ad2016-08-26 17:46:17 +0000652 MI.eraseFromParent();
653 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000654 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000655 case TargetOpcode::G_GEP: {
656 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
657 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
658 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
659 MI.getOperand(2).setReg(OffsetExt);
660 return Legalized;
661 }
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000662 case TargetOpcode::G_PHI: {
663 assert(TypeIdx == 0 && "Expecting only Idx 0");
David Blaikie196f53b22017-08-25 16:46:07 +0000664 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) {
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000665 auto FirstTermIt = MBB.getFirstTerminator();
666 MIRBuilder.setInsertPt(MBB, FirstTermIt);
667 MachineInstr *DefMI = MRI.getVRegDef(Reg);
668 MachineInstrBuilder MIB;
669 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC)
670 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy,
671 DefMI->getOperand(1).getReg());
672 else
673 MIB = MIRBuilder.buildAnyExt(WideTy, Reg);
674 return MIB->getOperand(0).getReg();
675 };
676 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy);
677 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end();
678 OpIt != OpE;) {
679 unsigned Reg = OpIt++->getReg();
680 MachineBasicBlock *OpMBB = OpIt++->getMBB();
681 MIB.addReg(getExtendedReg(Reg, *OpMBB));
682 MIB.addMBB(OpMBB);
683 }
684 auto *MBB = MI.getParent();
685 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
686 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(),
687 MIB->getOperand(0).getReg());
688 MI.eraseFromParent();
689 return Legalized;
690 }
Tim Northover32335812016-08-04 18:35:11 +0000691 }
Tim Northover33b07d62016-07-22 20:03:43 +0000692}
693
Tim Northover69fa84a2016-10-14 22:18:18 +0000694LegalizerHelper::LegalizeResult
695LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000696 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000697 MIRBuilder.setInstr(MI);
698
699 switch(MI.getOpcode()) {
700 default:
701 return UnableToLegalize;
702 case TargetOpcode::G_SREM:
703 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000704 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
705 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000706 .addDef(QuotReg)
707 .addUse(MI.getOperand(1).getReg())
708 .addUse(MI.getOperand(2).getReg());
709
Tim Northover0f140c72016-09-09 11:46:34 +0000710 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
711 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
712 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
713 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000714 MI.eraseFromParent();
715 return Legalized;
716 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000717 case TargetOpcode::G_SMULO:
718 case TargetOpcode::G_UMULO: {
719 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
720 // result.
721 unsigned Res = MI.getOperand(0).getReg();
722 unsigned Overflow = MI.getOperand(1).getReg();
723 unsigned LHS = MI.getOperand(2).getReg();
724 unsigned RHS = MI.getOperand(3).getReg();
725
726 MIRBuilder.buildMul(Res, LHS, RHS);
727
728 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
729 ? TargetOpcode::G_SMULH
730 : TargetOpcode::G_UMULH;
731
732 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
733 MIRBuilder.buildInstr(Opcode)
734 .addDef(HiPart)
735 .addUse(LHS)
736 .addUse(RHS);
737
738 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
739 MIRBuilder.buildConstant(Zero, 0);
740 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
741 MI.eraseFromParent();
742 return Legalized;
743 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000744 case TargetOpcode::G_FNEG: {
745 // TODO: Handle vector types once we are able to
746 // represent them.
747 if (Ty.isVector())
748 return UnableToLegalize;
749 unsigned Res = MI.getOperand(0).getReg();
750 Type *ZeroTy;
751 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
752 switch (Ty.getSizeInBits()) {
753 case 16:
754 ZeroTy = Type::getHalfTy(Ctx);
755 break;
756 case 32:
757 ZeroTy = Type::getFloatTy(Ctx);
758 break;
759 case 64:
760 ZeroTy = Type::getDoubleTy(Ctx);
761 break;
762 default:
763 llvm_unreachable("unexpected floating-point type");
764 }
765 ConstantFP &ZeroForNegation =
766 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
767 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
768 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
769 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
770 .addDef(Res)
771 .addUse(Zero)
772 .addUse(MI.getOperand(1).getReg());
773 MI.eraseFromParent();
774 return Legalized;
775 }
Volkan Keles225921a2017-03-10 21:25:09 +0000776 case TargetOpcode::G_FSUB: {
777 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
778 // First, check if G_FNEG is marked as Lower. If so, we may
779 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
780 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
781 return UnableToLegalize;
782 unsigned Res = MI.getOperand(0).getReg();
783 unsigned LHS = MI.getOperand(1).getReg();
784 unsigned RHS = MI.getOperand(2).getReg();
785 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
786 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
787 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
788 .addDef(Res)
789 .addUse(LHS)
790 .addUse(Neg);
791 MI.eraseFromParent();
792 return Legalized;
793 }
Tim Northovercecee562016-08-26 17:46:13 +0000794 }
795}
796
Tim Northover69fa84a2016-10-14 22:18:18 +0000797LegalizerHelper::LegalizeResult
798LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
799 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000800 // FIXME: Don't know how to handle secondary types yet.
801 if (TypeIdx != 0)
802 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000803 switch (MI.getOpcode()) {
804 default:
805 return UnableToLegalize;
806 case TargetOpcode::G_ADD: {
807 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000808 unsigned DstReg = MI.getOperand(0).getReg();
809 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
Tim Northover33b07d62016-07-22 20:03:43 +0000810
811 MIRBuilder.setInstr(MI);
812
Tim Northoverb18ea162016-09-20 15:20:36 +0000813 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000814 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
815 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
816
817 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000818 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
819 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000820 DstRegs.push_back(DstReg);
821 }
822
Tim Northoverbf017292017-03-03 22:46:09 +0000823 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000824 MI.eraseFromParent();
825 return Legalized;
826 }
827 }
828}