blob: a8cfe0b89a0c76936886bc871101883dbd0c29df [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;
Javed Absar5cde1cc2017-10-30 13:51:56 +000094 case TargetOpcode::G_FSUB:
95 assert((Size == 32 || Size == 64) && "Unsupported size");
96 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Tim Northovere0418412017-02-08 23:23:39 +000097 case TargetOpcode::G_FREM:
98 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
99 case TargetOpcode::G_FPOW:
100 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
101 }
102 llvm_unreachable("Unknown libcall function");
103}
104
Diana Picusfc1675e2017-07-05 12:57:24 +0000105LegalizerHelper::LegalizeResult
106llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
107 const CallLowering::ArgInfo &Result,
108 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000109 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
110 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000111 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000112
Diana Picuse97822e2017-04-24 07:22:31 +0000113 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000114 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
115 MachineOperand::CreateES(Name), Result, Args))
116 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000117
Diana Picuse97822e2017-04-24 07:22:31 +0000118 return LegalizerHelper::Legalized;
119}
120
Diana Picus02e11012017-06-15 10:53:31 +0000121static LegalizerHelper::LegalizeResult
122simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
123 Type *OpType) {
124 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000125 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
126 {{MI.getOperand(1).getReg(), OpType},
127 {MI.getOperand(2).getReg(), OpType}});
Diana Picus02e11012017-06-15 10:53:31 +0000128}
129
Tim Northover69fa84a2016-10-14 22:18:18 +0000130LegalizerHelper::LegalizeResult
131LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000132 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
133 unsigned Size = LLTy.getSizeInBits();
Diana Picuse97822e2017-04-24 07:22:31 +0000134 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000135
Diana Picusfc1675e2017-07-05 12:57:24 +0000136 MIRBuilder.setInstr(MI);
137
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000138 switch (MI.getOpcode()) {
139 default:
140 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000141 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000142 case TargetOpcode::G_UDIV:
143 case TargetOpcode::G_SREM:
144 case TargetOpcode::G_UREM: {
145 Type *HLTy = Type::getInt32Ty(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000146 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
147 if (Status != Legalized)
148 return Status;
149 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000150 }
Diana Picus1314a282017-04-11 10:52:34 +0000151 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000152 case TargetOpcode::G_FSUB:
Tim Northovere0418412017-02-08 23:23:39 +0000153 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000154 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000155 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000156 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
157 if (Status != Legalized)
158 return Status;
159 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000160 }
161 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000162
163 MI.eraseFromParent();
164 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000165}
166
Tim Northover69fa84a2016-10-14 22:18:18 +0000167LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
168 unsigned TypeIdx,
169 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000170 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000171 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000172 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000173
174 MIRBuilder.setInstr(MI);
175
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000176 int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
177 int64_t NarrowSize = NarrowTy.getSizeInBits();
178
Tim Northover9656f142016-08-04 20:54:13 +0000179 switch (MI.getOpcode()) {
180 default:
181 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000182 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000183 // FIXME: add support for when SizeOp0 isn't an exact multiple of
184 // NarrowSize.
185 if (SizeOp0 % NarrowSize != 0)
186 return UnableToLegalize;
187 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000188
189 SmallVector<unsigned, 2> DstRegs;
190 for (int i = 0; i < NumParts; ++i) {
191 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
192 MIRBuilder.buildUndef(Dst);
193 DstRegs.push_back(Dst);
194 }
195 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
196 MI.eraseFromParent();
197 return Legalized;
198 }
Tim Northover9656f142016-08-04 20:54:13 +0000199 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000200 // FIXME: add support for when SizeOp0 isn't an exact multiple of
201 // NarrowSize.
202 if (SizeOp0 % NarrowSize != 0)
203 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000204 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000205 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000206
Tim Northoverb18ea162016-09-20 15:20:36 +0000207 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000208 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
209 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
210
Tim Northover0f140c72016-09-09 11:46:34 +0000211 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
212 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000213
214 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000215 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
216 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000217
Tim Northover0f140c72016-09-09 11:46:34 +0000218 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000219 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000220
221 DstRegs.push_back(DstReg);
222 CarryIn = CarryOut;
223 }
Tim Northover0f140c72016-09-09 11:46:34 +0000224 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000225 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000226 MI.eraseFromParent();
227 return Legalized;
228 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000229 case TargetOpcode::G_EXTRACT: {
230 if (TypeIdx != 1)
231 return UnableToLegalize;
232
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000233 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
234 // FIXME: add support for when SizeOp1 isn't an exact multiple of
235 // NarrowSize.
236 if (SizeOp1 % NarrowSize != 0)
237 return UnableToLegalize;
238 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000239
240 SmallVector<unsigned, 2> SrcRegs, DstRegs;
241 SmallVector<uint64_t, 2> Indexes;
242 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
243
244 unsigned OpReg = MI.getOperand(0).getReg();
245 int64_t OpStart = MI.getOperand(2).getImm();
246 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
247 for (int i = 0; i < NumParts; ++i) {
248 unsigned SrcStart = i * NarrowSize;
249
250 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
251 // No part of the extract uses this subregister, ignore it.
252 continue;
253 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
254 // The entire subregister is extracted, forward the value.
255 DstRegs.push_back(SrcRegs[i]);
256 continue;
257 }
258
259 // OpSegStart is where this destination segment would start in OpReg if it
260 // extended infinitely in both directions.
261 int64_t ExtractOffset, SegSize;
262 if (OpStart < SrcStart) {
263 ExtractOffset = 0;
264 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
265 } else {
266 ExtractOffset = OpStart - SrcStart;
267 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
268 }
269
270 unsigned SegReg = SrcRegs[i];
271 if (ExtractOffset != 0 || SegSize != NarrowSize) {
272 // A genuine extract is needed.
273 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
274 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
275 }
276
277 DstRegs.push_back(SegReg);
278 }
279
280 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
281 MI.eraseFromParent();
282 return Legalized;
283 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000284 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000285 // FIXME: add support for when SizeOp0 isn't an exact multiple of
286 // NarrowSize.
287 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000288 return UnableToLegalize;
289
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000290 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000291
292 SmallVector<unsigned, 2> SrcRegs, DstRegs;
293 SmallVector<uint64_t, 2> Indexes;
294 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
295
Tim Northover75e0b912017-03-06 18:23:04 +0000296 unsigned OpReg = MI.getOperand(2).getReg();
297 int64_t OpStart = MI.getOperand(3).getImm();
298 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000299 for (int i = 0; i < NumParts; ++i) {
300 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000301
Tim Northover75e0b912017-03-06 18:23:04 +0000302 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000303 // No part of the insert affects this subregister, forward the original.
304 DstRegs.push_back(SrcRegs[i]);
305 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000306 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000307 // The entire subregister is defined by this insert, forward the new
308 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000309 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000310 continue;
311 }
312
Tim Northover2eb18d32017-03-07 21:24:33 +0000313 // OpSegStart is where this destination segment would start in OpReg if it
314 // extended infinitely in both directions.
315 int64_t ExtractOffset, InsertOffset, SegSize;
316 if (OpStart < DstStart) {
317 InsertOffset = 0;
318 ExtractOffset = DstStart - OpStart;
319 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
320 } else {
321 InsertOffset = OpStart - DstStart;
322 ExtractOffset = 0;
323 SegSize =
324 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
325 }
326
327 unsigned SegReg = OpReg;
328 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000329 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000330 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
331 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000332 }
333
Tim Northover75e0b912017-03-06 18:23:04 +0000334 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000335 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000336 DstRegs.push_back(DstReg);
337 }
338
339 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000340 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000341 MI.eraseFromParent();
342 return Legalized;
343 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000344 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000345 // FIXME: add support for when SizeOp0 isn't an exact multiple of
346 // NarrowSize.
347 if (SizeOp0 % NarrowSize != 0)
348 return UnableToLegalize;
349 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000350 LLT OffsetTy = LLT::scalar(
351 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000352
353 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000354 for (int i = 0; i < NumParts; ++i) {
355 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000356 unsigned SrcReg = 0;
357 unsigned Adjustment = i * NarrowSize / 8;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000358
Daniel Sanders4e523662017-06-13 23:42:32 +0000359 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
360 Adjustment);
361
Justin Bognere094cc42017-01-20 00:30:17 +0000362 // TODO: This is conservatively correct, but we probably want to split the
363 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000364 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
365
366 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000367 }
368 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000369 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000370 MI.eraseFromParent();
371 return Legalized;
372 }
Justin Bognerfde01042017-01-18 17:29:54 +0000373 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000374 // FIXME: add support for when SizeOp0 isn't an exact multiple of
375 // NarrowSize.
376 if (SizeOp0 % NarrowSize != 0)
377 return UnableToLegalize;
378 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000379 LLT OffsetTy = LLT::scalar(
380 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000381
382 SmallVector<unsigned, 2> SrcRegs;
383 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
384
385 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000386 unsigned DstReg = 0;
387 unsigned Adjustment = i * NarrowSize / 8;
388
389 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
390 Adjustment);
391
Justin Bognere094cc42017-01-20 00:30:17 +0000392 // TODO: This is conservatively correct, but we probably want to split the
393 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000394 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
395 }
396 MI.eraseFromParent();
397 return Legalized;
398 }
Igor Breger29537882017-04-07 14:41:59 +0000399 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000400 // FIXME: add support for when SizeOp0 isn't an exact multiple of
401 // NarrowSize.
402 if (SizeOp0 % NarrowSize != 0)
403 return UnableToLegalize;
404 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000405 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
406 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
407
408 SmallVector<unsigned, 2> DstRegs;
409 for (int i = 0; i < NumParts; ++i) {
410 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
411 ConstantInt *CI =
412 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
413 MIRBuilder.buildConstant(DstReg, *CI);
414 DstRegs.push_back(DstReg);
415 }
416 unsigned DstReg = MI.getOperand(0).getReg();
417 MIRBuilder.buildMerge(DstReg, DstRegs);
418 MI.eraseFromParent();
419 return Legalized;
420 }
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000421 case TargetOpcode::G_OR: {
422 // Legalize bitwise operation:
423 // A = BinOp<Ty> B, C
424 // into:
425 // B1, ..., BN = G_UNMERGE_VALUES B
426 // C1, ..., CN = G_UNMERGE_VALUES C
427 // A1 = BinOp<Ty/N> B1, C2
428 // ...
429 // AN = BinOp<Ty/N> BN, CN
430 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000431
432 // FIXME: add support for when SizeOp0 isn't an exact multiple of
433 // NarrowSize.
434 if (SizeOp0 % NarrowSize != 0)
435 return UnableToLegalize;
436 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000437
438 // List the registers where the destination will be scattered.
439 SmallVector<unsigned, 2> DstRegs;
440 // List the registers where the first argument will be split.
441 SmallVector<unsigned, 2> SrcsReg1;
442 // List the registers where the second argument will be split.
443 SmallVector<unsigned, 2> SrcsReg2;
444 // Create all the temporary registers.
445 for (int i = 0; i < NumParts; ++i) {
446 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
447 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
448 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
449
450 DstRegs.push_back(DstReg);
451 SrcsReg1.push_back(SrcReg1);
452 SrcsReg2.push_back(SrcReg2);
453 }
454 // Explode the big arguments into smaller chunks.
455 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
456 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
457
458 // Do the operation on each small part.
459 for (int i = 0; i < NumParts; ++i)
460 MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
461
462 // Gather the destination registers into the final destination.
463 unsigned DstReg = MI.getOperand(0).getReg();
464 MIRBuilder.buildMerge(DstReg, DstRegs);
465 MI.eraseFromParent();
466 return Legalized;
467 }
Tim Northover9656f142016-08-04 20:54:13 +0000468 }
Tim Northover33b07d62016-07-22 20:03:43 +0000469}
470
Tim Northover69fa84a2016-10-14 22:18:18 +0000471LegalizerHelper::LegalizeResult
472LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000473 MIRBuilder.setInstr(MI);
474
Tim Northover32335812016-08-04 18:35:11 +0000475 switch (MI.getOpcode()) {
476 default:
477 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000478 case TargetOpcode::G_ADD:
479 case TargetOpcode::G_AND:
480 case TargetOpcode::G_MUL:
481 case TargetOpcode::G_OR:
482 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000483 case TargetOpcode::G_SUB:
484 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000485 // Perform operation at larger width (any extension is fine here, high bits
486 // don't affect the result) and then truncate the result back to the
487 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000488 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
489 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
490 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
491 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000492
Tim Northover0f140c72016-09-09 11:46:34 +0000493 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
494 MIRBuilder.buildInstr(MI.getOpcode())
495 .addDef(DstExt)
496 .addUse(Src1Ext)
497 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000498
Tim Northover0f140c72016-09-09 11:46:34 +0000499 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000500 MI.eraseFromParent();
501 return Legalized;
502 }
Tim Northover7a753d92016-08-26 17:46:06 +0000503 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000504 case TargetOpcode::G_UDIV:
Diana Picusdf4100b2017-07-18 09:08:47 +0000505 case TargetOpcode::G_SREM:
506 case TargetOpcode::G_UREM:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000507 case TargetOpcode::G_ASHR:
508 case TargetOpcode::G_LSHR: {
509 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
Diana Picusdf4100b2017-07-18 09:08:47 +0000510 MI.getOpcode() == TargetOpcode::G_SREM ||
Justin Bognerddb80ae2017-01-19 07:51:17 +0000511 MI.getOpcode() == TargetOpcode::G_ASHR
512 ? TargetOpcode::G_SEXT
513 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000514
Tim Northover0f140c72016-09-09 11:46:34 +0000515 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
516 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
517 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000518
Tim Northover0f140c72016-09-09 11:46:34 +0000519 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
520 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
521 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000522
Tim Northover0f140c72016-09-09 11:46:34 +0000523 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
524 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000525 .addDef(ResExt)
526 .addUse(LHSExt)
527 .addUse(RHSExt);
528
Tim Northover0f140c72016-09-09 11:46:34 +0000529 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000530 MI.eraseFromParent();
531 return Legalized;
532 }
Tim Northover868332d2017-02-06 23:41:27 +0000533 case TargetOpcode::G_SELECT: {
534 if (TypeIdx != 0)
535 return UnableToLegalize;
536
537 // Perform operation at larger width (any extension is fine here, high bits
538 // don't affect the result) and then truncate the result back to the
539 // original type.
540 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
541 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
542 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
543 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
544
545 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
546 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
547 .addDef(DstExt)
548 .addReg(MI.getOperand(1).getReg())
549 .addUse(Src1Ext)
550 .addUse(Src2Ext);
551
552 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
553 MI.eraseFromParent();
554 return Legalized;
555 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000556 case TargetOpcode::G_FPTOSI:
557 case TargetOpcode::G_FPTOUI: {
558 if (TypeIdx != 0)
559 return UnableToLegalize;
560
561 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
562 MIRBuilder.buildInstr(MI.getOpcode())
563 .addDef(DstExt)
564 .addUse(MI.getOperand(1).getReg());
565
566 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
567 MI.eraseFromParent();
568 return Legalized;
569 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000570 case TargetOpcode::G_SITOFP:
571 case TargetOpcode::G_UITOFP: {
572 if (TypeIdx != 1)
573 return UnableToLegalize;
574
575 unsigned Src = MI.getOperand(1).getReg();
576 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
577
578 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
579 MIRBuilder.buildSExt(SrcExt, Src);
580 } else {
581 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
582 MIRBuilder.buildZExt(SrcExt, Src);
583 }
584
585 MIRBuilder.buildInstr(MI.getOpcode())
586 .addDef(MI.getOperand(0).getReg())
587 .addUse(SrcExt);
588
589 MI.eraseFromParent();
590 return Legalized;
591 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000592 case TargetOpcode::G_INSERT: {
593 if (TypeIdx != 0)
594 return UnableToLegalize;
595
596 unsigned Src = MI.getOperand(1).getReg();
597 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
598 MIRBuilder.buildAnyExt(SrcExt, Src);
599
600 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
601 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
602 MI.getOperand(3).getImm());
603 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
604 MIB.addReg(MI.getOperand(OpNum).getReg());
605 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
606 }
607
608 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
609 MI.eraseFromParent();
610 return Legalized;
611 }
Tim Northover3c73e362016-08-23 18:20:09 +0000612 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000613 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
614 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000615 "illegal to increase number of bytes loaded");
616
Tim Northover0f140c72016-09-09 11:46:34 +0000617 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
618 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
619 **MI.memoperands_begin());
620 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000621 MI.eraseFromParent();
622 return Legalized;
623 }
624 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000625 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
626 WideTy != LLT::scalar(8))
627 return UnableToLegalize;
628
629 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
630 auto Content = TLI.getBooleanContents(false, false);
631
632 unsigned ExtOp = TargetOpcode::G_ANYEXT;
633 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
634 ExtOp = TargetOpcode::G_ZEXT;
635 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
636 ExtOp = TargetOpcode::G_SEXT;
637 else
638 ExtOp = TargetOpcode::G_ANYEXT;
Tim Northover3c73e362016-08-23 18:20:09 +0000639
Tim Northover0f140c72016-09-09 11:46:34 +0000640 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover548feee2017-03-21 22:22:05 +0000641 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
642 MI.getOperand(0).getReg());
Tim Northover0f140c72016-09-09 11:46:34 +0000643 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
644 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000645 MI.eraseFromParent();
646 return Legalized;
647 }
Tim Northoverea904f92016-08-19 22:40:00 +0000648 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000649 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000650 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000651 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000652 MI.eraseFromParent();
653 return Legalized;
654 }
Tim Northovera11be042016-08-19 22:40:08 +0000655 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000656 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
657 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
658 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000659 MI.eraseFromParent();
660 return Legalized;
661 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000662 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000663 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
664 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
665 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000666 MI.eraseFromParent();
667 return Legalized;
668 }
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000669 case TargetOpcode::G_FCMP: {
670 unsigned Op0Ext, Op1Ext, DstReg;
671 unsigned Cmp1 = MI.getOperand(2).getReg();
672 unsigned Cmp2 = MI.getOperand(3).getReg();
673 if (TypeIdx == 0) {
674 Op0Ext = Cmp1;
675 Op1Ext = Cmp2;
676 DstReg = MRI.createGenericVirtualRegister(WideTy);
677 } else {
678 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
679 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
680 DstReg = MI.getOperand(0).getReg();
681 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1);
682 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2);
683 }
684 MIRBuilder.buildFCmp(
685 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
686 DstReg, Op0Ext, Op1Ext);
687 if (TypeIdx == 0)
688 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
689 DstReg);
690 MI.eraseFromParent();
691 return Legalized;
692 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000693 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000694 bool IsSigned = CmpInst::isSigned(
695 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000696 unsigned Cmp1 = MI.getOperand(2).getReg();
697 unsigned Cmp2 = MI.getOperand(3).getReg();
698 unsigned Op0Ext, Op1Ext, DstReg;
699 if (TypeIdx == 0) {
700 Op0Ext = Cmp1;
701 Op1Ext = Cmp2;
702 DstReg = MRI.createGenericVirtualRegister(WideTy);
Tim Northover6cd4b232016-08-23 21:01:26 +0000703 } else {
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000704 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
705 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
706 DstReg = MI.getOperand(0).getReg();
707 if (IsSigned) {
708 MIRBuilder.buildSExt(Op0Ext, Cmp1);
709 MIRBuilder.buildSExt(Op1Ext, Cmp2);
710 } else {
711 MIRBuilder.buildZExt(Op0Ext, Cmp1);
712 MIRBuilder.buildZExt(Op1Ext, Cmp2);
713 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000714 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000715 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000716 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000717 DstReg, Op0Ext, Op1Ext);
718 if (TypeIdx == 0)
719 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
720 DstReg);
Tim Northover051b8ad2016-08-26 17:46:17 +0000721 MI.eraseFromParent();
722 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000723 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000724 case TargetOpcode::G_GEP: {
725 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
726 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
727 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
728 MI.getOperand(2).setReg(OffsetExt);
729 return Legalized;
730 }
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000731 case TargetOpcode::G_PHI: {
732 assert(TypeIdx == 0 && "Expecting only Idx 0");
David Blaikie196f53b22017-08-25 16:46:07 +0000733 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) {
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000734 auto FirstTermIt = MBB.getFirstTerminator();
735 MIRBuilder.setInsertPt(MBB, FirstTermIt);
736 MachineInstr *DefMI = MRI.getVRegDef(Reg);
737 MachineInstrBuilder MIB;
738 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC)
739 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy,
740 DefMI->getOperand(1).getReg());
741 else
742 MIB = MIRBuilder.buildAnyExt(WideTy, Reg);
743 return MIB->getOperand(0).getReg();
744 };
745 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy);
746 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end();
747 OpIt != OpE;) {
748 unsigned Reg = OpIt++->getReg();
749 MachineBasicBlock *OpMBB = OpIt++->getMBB();
750 MIB.addReg(getExtendedReg(Reg, *OpMBB));
751 MIB.addMBB(OpMBB);
752 }
753 auto *MBB = MI.getParent();
754 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
755 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(),
756 MIB->getOperand(0).getReg());
757 MI.eraseFromParent();
758 return Legalized;
759 }
Tim Northover32335812016-08-04 18:35:11 +0000760 }
Tim Northover33b07d62016-07-22 20:03:43 +0000761}
762
Tim Northover69fa84a2016-10-14 22:18:18 +0000763LegalizerHelper::LegalizeResult
764LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000765 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000766 MIRBuilder.setInstr(MI);
767
768 switch(MI.getOpcode()) {
769 default:
770 return UnableToLegalize;
771 case TargetOpcode::G_SREM:
772 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000773 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
774 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000775 .addDef(QuotReg)
776 .addUse(MI.getOperand(1).getReg())
777 .addUse(MI.getOperand(2).getReg());
778
Tim Northover0f140c72016-09-09 11:46:34 +0000779 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
780 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
781 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
782 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000783 MI.eraseFromParent();
784 return Legalized;
785 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000786 case TargetOpcode::G_SMULO:
787 case TargetOpcode::G_UMULO: {
788 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
789 // result.
790 unsigned Res = MI.getOperand(0).getReg();
791 unsigned Overflow = MI.getOperand(1).getReg();
792 unsigned LHS = MI.getOperand(2).getReg();
793 unsigned RHS = MI.getOperand(3).getReg();
794
795 MIRBuilder.buildMul(Res, LHS, RHS);
796
797 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
798 ? TargetOpcode::G_SMULH
799 : TargetOpcode::G_UMULH;
800
801 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
802 MIRBuilder.buildInstr(Opcode)
803 .addDef(HiPart)
804 .addUse(LHS)
805 .addUse(RHS);
806
807 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
808 MIRBuilder.buildConstant(Zero, 0);
809 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
810 MI.eraseFromParent();
811 return Legalized;
812 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000813 case TargetOpcode::G_FNEG: {
814 // TODO: Handle vector types once we are able to
815 // represent them.
816 if (Ty.isVector())
817 return UnableToLegalize;
818 unsigned Res = MI.getOperand(0).getReg();
819 Type *ZeroTy;
820 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
821 switch (Ty.getSizeInBits()) {
822 case 16:
823 ZeroTy = Type::getHalfTy(Ctx);
824 break;
825 case 32:
826 ZeroTy = Type::getFloatTy(Ctx);
827 break;
828 case 64:
829 ZeroTy = Type::getDoubleTy(Ctx);
830 break;
831 default:
832 llvm_unreachable("unexpected floating-point type");
833 }
834 ConstantFP &ZeroForNegation =
835 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
836 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
837 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
838 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
839 .addDef(Res)
840 .addUse(Zero)
841 .addUse(MI.getOperand(1).getReg());
842 MI.eraseFromParent();
843 return Legalized;
844 }
Volkan Keles225921a2017-03-10 21:25:09 +0000845 case TargetOpcode::G_FSUB: {
846 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
847 // First, check if G_FNEG is marked as Lower. If so, we may
848 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
849 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
850 return UnableToLegalize;
851 unsigned Res = MI.getOperand(0).getReg();
852 unsigned LHS = MI.getOperand(1).getReg();
853 unsigned RHS = MI.getOperand(2).getReg();
854 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
855 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
856 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
857 .addDef(Res)
858 .addUse(LHS)
859 .addUse(Neg);
860 MI.eraseFromParent();
861 return Legalized;
862 }
Tim Northovercecee562016-08-26 17:46:13 +0000863 }
864}
865
Tim Northover69fa84a2016-10-14 22:18:18 +0000866LegalizerHelper::LegalizeResult
867LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
868 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000869 // FIXME: Don't know how to handle secondary types yet.
870 if (TypeIdx != 0)
871 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000872 switch (MI.getOpcode()) {
873 default:
874 return UnableToLegalize;
875 case TargetOpcode::G_ADD: {
876 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000877 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000878 unsigned Size = MRI.getType(DstReg).getSizeInBits();
879 int NumParts = Size / NarrowSize;
880 // FIXME: Don't know how to handle the situation where the small vectors
881 // aren't all the same size yet.
882 if (Size % NarrowSize != 0)
883 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000884
885 MIRBuilder.setInstr(MI);
886
Tim Northoverb18ea162016-09-20 15:20:36 +0000887 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000888 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
889 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
890
891 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000892 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
893 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000894 DstRegs.push_back(DstReg);
895 }
896
Tim Northoverbf017292017-03-03 22:46:09 +0000897 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000898 MI.eraseFromParent();
899 return Legalized;
900 }
901 }
902}