blob: 9dcdb0d41cd51023e3cfa6e2d9de1fd87a5520e6 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tim Northover33b07d62016-07-22 20:03:43 +00006//
7//===----------------------------------------------------------------------===//
8//
Tim Northover69fa84a2016-10-14 22:18:18 +00009/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000010/// individual instructions and the LegalizeMachineIR wrapper pass for the
11/// primary legalization.
12//
13//===----------------------------------------------------------------------===//
14
Tim Northover69fa84a2016-10-14 22:18:18 +000015#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000016#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000017#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.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"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000020#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000021#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000023#include "llvm/Support/Debug.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000024#include "llvm/Support/MathExtras.h"
Tim Northover33b07d62016-07-22 20:03:43 +000025#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000026
Daniel Sanders5377fb32017-04-20 15:46:12 +000027#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000028
29using namespace llvm;
Daniel Sanders9ade5592018-01-29 17:37:29 +000030using namespace LegalizeActions;
Tim Northover33b07d62016-07-22 20:03:43 +000031
Matt Arsenaultc83b8232019-02-07 17:38:00 +000032/// Try to break down \p OrigTy into \p NarrowTy sized pieces.
33///
34/// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy,
35/// with any leftover piece as type \p LeftoverTy
36///
37/// Returns -1 if the breakdown is not satisfiable.
38static int getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) {
39 assert(!LeftoverTy.isValid() && "this is an out argument");
40
41 unsigned Size = OrigTy.getSizeInBits();
42 unsigned NarrowSize = NarrowTy.getSizeInBits();
43 unsigned NumParts = Size / NarrowSize;
44 unsigned LeftoverSize = Size - NumParts * NarrowSize;
45 assert(Size > NarrowSize);
46
47 if (LeftoverSize == 0)
48 return NumParts;
49
50 if (NarrowTy.isVector()) {
51 unsigned EltSize = OrigTy.getScalarSizeInBits();
52 if (LeftoverSize % EltSize != 0)
53 return -1;
54 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
55 } else {
56 LeftoverTy = LLT::scalar(LeftoverSize);
57 }
58
59 return NumParts;
60}
61
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000062LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000063 GISelChangeObserver &Observer,
64 MachineIRBuilder &Builder)
65 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
66 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000067 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000068 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000069}
70
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000071LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000072 GISelChangeObserver &Observer,
73 MachineIRBuilder &B)
74 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000075 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000076 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000077}
Tim Northover69fa84a2016-10-14 22:18:18 +000078LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000079LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000080 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000081
Daniel Sanders262ed0e2018-01-24 17:17:46 +000082 auto Step = LI.getAction(MI, MRI);
83 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000084 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000085 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000086 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000087 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000088 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000089 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000090 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000091 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000092 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000093 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000094 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000095 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000096 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000097 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000098 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000099 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000100 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000101 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000102 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000103 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000104 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
105 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000106 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000107 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +0000108 return UnableToLegalize;
109 }
110}
111
Tim Northover69fa84a2016-10-14 22:18:18 +0000112void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
113 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +0000114 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +0000115 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +0000116 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +0000117}
118
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000119bool LegalizerHelper::extractParts(unsigned Reg, LLT RegTy,
120 LLT MainTy, LLT &LeftoverTy,
121 SmallVectorImpl<unsigned> &VRegs,
122 SmallVectorImpl<unsigned> &LeftoverRegs) {
123 assert(!LeftoverTy.isValid() && "this is an out argument");
124
125 unsigned RegSize = RegTy.getSizeInBits();
126 unsigned MainSize = MainTy.getSizeInBits();
127 unsigned NumParts = RegSize / MainSize;
128 unsigned LeftoverSize = RegSize - NumParts * MainSize;
129
130 // Use an unmerge when possible.
131 if (LeftoverSize == 0) {
132 for (unsigned I = 0; I < NumParts; ++I)
133 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy));
134 MIRBuilder.buildUnmerge(VRegs, Reg);
135 return true;
136 }
137
138 if (MainTy.isVector()) {
139 unsigned EltSize = MainTy.getScalarSizeInBits();
140 if (LeftoverSize % EltSize != 0)
141 return false;
142 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
143 } else {
144 LeftoverTy = LLT::scalar(LeftoverSize);
145 }
146
147 // For irregular sizes, extract the individual parts.
148 for (unsigned I = 0; I != NumParts; ++I) {
149 unsigned NewReg = MRI.createGenericVirtualRegister(MainTy);
150 VRegs.push_back(NewReg);
151 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I);
152 }
153
154 for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
155 Offset += LeftoverSize) {
156 unsigned NewReg = MRI.createGenericVirtualRegister(LeftoverTy);
157 LeftoverRegs.push_back(NewReg);
158 MIRBuilder.buildExtract(NewReg, Reg, Offset);
159 }
160
161 return true;
162}
163
164void LegalizerHelper::insertParts(unsigned DstReg,
165 LLT ResultTy, LLT PartTy,
166 ArrayRef<unsigned> PartRegs,
167 LLT LeftoverTy,
168 ArrayRef<unsigned> LeftoverRegs) {
169 if (!LeftoverTy.isValid()) {
170 assert(LeftoverRegs.empty());
171
Matt Arsenault81511e52019-02-05 00:13:44 +0000172 if (!ResultTy.isVector()) {
173 MIRBuilder.buildMerge(DstReg, PartRegs);
174 return;
175 }
176
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000177 if (PartTy.isVector())
178 MIRBuilder.buildConcatVectors(DstReg, PartRegs);
179 else
180 MIRBuilder.buildBuildVector(DstReg, PartRegs);
181 return;
182 }
183
184 unsigned PartSize = PartTy.getSizeInBits();
185 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits();
186
187 unsigned CurResultReg = MRI.createGenericVirtualRegister(ResultTy);
188 MIRBuilder.buildUndef(CurResultReg);
189
190 unsigned Offset = 0;
191 for (unsigned PartReg : PartRegs) {
192 unsigned NewResultReg = MRI.createGenericVirtualRegister(ResultTy);
193 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset);
194 CurResultReg = NewResultReg;
195 Offset += PartSize;
196 }
197
198 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) {
199 // Use the original output register for the final insert to avoid a copy.
200 unsigned NewResultReg = (I + 1 == E) ?
201 DstReg : MRI.createGenericVirtualRegister(ResultTy);
202
203 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset);
204 CurResultReg = NewResultReg;
205 Offset += LeftoverPartSize;
206 }
207}
208
Tim Northovere0418412017-02-08 23:23:39 +0000209static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
210 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +0000211 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000212 assert((Size == 32 || Size == 64) && "Unsupported size");
213 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +0000214 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000215 assert((Size == 32 || Size == 64) && "Unsupported size");
216 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000217 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000218 assert((Size == 32 || Size == 64) && "Unsupported size");
219 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000220 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000221 assert((Size == 32 || Size == 64) && "Unsupported size");
222 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000223 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
224 assert(Size == 32 && "Unsupported size");
225 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000226 case TargetOpcode::G_FADD:
227 assert((Size == 32 || Size == 64) && "Unsupported size");
228 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000229 case TargetOpcode::G_FSUB:
230 assert((Size == 32 || Size == 64) && "Unsupported size");
231 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000232 case TargetOpcode::G_FMUL:
233 assert((Size == 32 || Size == 64) && "Unsupported size");
234 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000235 case TargetOpcode::G_FDIV:
236 assert((Size == 32 || Size == 64) && "Unsupported size");
237 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Jessica Paquette84bedac2019-01-30 23:46:15 +0000238 case TargetOpcode::G_FEXP:
239 assert((Size == 32 || Size == 64) && "Unsupported size");
240 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000241 case TargetOpcode::G_FREM:
242 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
243 case TargetOpcode::G_FPOW:
244 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000245 case TargetOpcode::G_FMA:
246 assert((Size == 32 || Size == 64) && "Unsupported size");
247 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Jessica Paquette7db82d72019-01-28 18:34:18 +0000248 case TargetOpcode::G_FSIN:
249 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
250 return Size == 128 ? RTLIB::SIN_F128
251 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32;
252 case TargetOpcode::G_FCOS:
253 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
254 return Size == 128 ? RTLIB::COS_F128
255 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32;
Jessica Paquettec49428a2019-01-28 19:53:14 +0000256 case TargetOpcode::G_FLOG10:
257 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
258 return Size == 128 ? RTLIB::LOG10_F128
259 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32;
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000260 case TargetOpcode::G_FLOG:
261 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
262 return Size == 128 ? RTLIB::LOG_F128
263 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32;
Jessica Paquette0154bd12019-01-30 21:16:04 +0000264 case TargetOpcode::G_FLOG2:
265 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
266 return Size == 128 ? RTLIB::LOG2_F128
267 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000268 }
269 llvm_unreachable("Unknown libcall function");
270}
271
Diana Picusfc1675e2017-07-05 12:57:24 +0000272LegalizerHelper::LegalizeResult
273llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
274 const CallLowering::ArgInfo &Result,
275 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000276 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
277 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000278 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000279
Diana Picuse97822e2017-04-24 07:22:31 +0000280 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000281 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
282 MachineOperand::CreateES(Name), Result, Args))
283 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000284
Diana Picuse97822e2017-04-24 07:22:31 +0000285 return LegalizerHelper::Legalized;
286}
287
Diana Picus65ed3642018-01-17 13:34:10 +0000288// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000289static LegalizerHelper::LegalizeResult
290simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
291 Type *OpType) {
292 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000293
294 SmallVector<CallLowering::ArgInfo, 3> Args;
295 for (unsigned i = 1; i < MI.getNumOperands(); i++)
296 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000297 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000298 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000299}
300
Diana Picus65ed3642018-01-17 13:34:10 +0000301static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
302 Type *FromType) {
303 auto ToMVT = MVT::getVT(ToType);
304 auto FromMVT = MVT::getVT(FromType);
305
306 switch (Opcode) {
307 case TargetOpcode::G_FPEXT:
308 return RTLIB::getFPEXT(FromMVT, ToMVT);
309 case TargetOpcode::G_FPTRUNC:
310 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000311 case TargetOpcode::G_FPTOSI:
312 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
313 case TargetOpcode::G_FPTOUI:
314 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000315 case TargetOpcode::G_SITOFP:
316 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
317 case TargetOpcode::G_UITOFP:
318 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000319 }
320 llvm_unreachable("Unsupported libcall function");
321}
322
323static LegalizerHelper::LegalizeResult
324conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
325 Type *FromType) {
326 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
327 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
328 {{MI.getOperand(1).getReg(), FromType}});
329}
330
Tim Northover69fa84a2016-10-14 22:18:18 +0000331LegalizerHelper::LegalizeResult
332LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000333 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
334 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000335 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000336
Diana Picusfc1675e2017-07-05 12:57:24 +0000337 MIRBuilder.setInstr(MI);
338
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000339 switch (MI.getOpcode()) {
340 default:
341 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000342 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000343 case TargetOpcode::G_UDIV:
344 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000345 case TargetOpcode::G_UREM:
346 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000347 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000348 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
349 if (Status != Legalized)
350 return Status;
351 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000352 }
Diana Picus1314a282017-04-11 10:52:34 +0000353 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000354 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000355 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000356 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000357 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000358 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000359 case TargetOpcode::G_FREM:
360 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000361 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000362 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000363 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000364 case TargetOpcode::G_FLOG2:
365 case TargetOpcode::G_FEXP: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000366 if (Size > 64) {
367 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
368 return UnableToLegalize;
369 }
Diana Picus02e11012017-06-15 10:53:31 +0000370 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000371 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
372 if (Status != Legalized)
373 return Status;
374 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000375 }
Diana Picus65ed3642018-01-17 13:34:10 +0000376 case TargetOpcode::G_FPEXT: {
377 // FIXME: Support other floating point types (half, fp128 etc)
378 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
379 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
380 if (ToSize != 64 || FromSize != 32)
381 return UnableToLegalize;
382 LegalizeResult Status = conversionLibcall(
383 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
384 if (Status != Legalized)
385 return Status;
386 break;
387 }
388 case TargetOpcode::G_FPTRUNC: {
389 // FIXME: Support other floating point types (half, fp128 etc)
390 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
391 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
392 if (ToSize != 32 || FromSize != 64)
393 return UnableToLegalize;
394 LegalizeResult Status = conversionLibcall(
395 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
396 if (Status != Legalized)
397 return Status;
398 break;
399 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000400 case TargetOpcode::G_FPTOSI:
401 case TargetOpcode::G_FPTOUI: {
402 // FIXME: Support other types
403 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
404 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
405 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
406 return UnableToLegalize;
407 LegalizeResult Status = conversionLibcall(
408 MI, MIRBuilder, Type::getInt32Ty(Ctx),
409 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
410 if (Status != Legalized)
411 return Status;
412 break;
413 }
Diana Picus517531e2018-01-30 09:15:17 +0000414 case TargetOpcode::G_SITOFP:
415 case TargetOpcode::G_UITOFP: {
416 // FIXME: Support other types
417 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
418 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
419 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
420 return UnableToLegalize;
421 LegalizeResult Status = conversionLibcall(
422 MI, MIRBuilder,
423 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
424 Type::getInt32Ty(Ctx));
425 if (Status != Legalized)
426 return Status;
427 break;
428 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000429 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000430
431 MI.eraseFromParent();
432 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000433}
434
Tim Northover69fa84a2016-10-14 22:18:18 +0000435LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
436 unsigned TypeIdx,
437 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000438 MIRBuilder.setInstr(MI);
439
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000440 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
441 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000442
Tim Northover9656f142016-08-04 20:54:13 +0000443 switch (MI.getOpcode()) {
444 default:
445 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000446 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000447 // FIXME: add support for when SizeOp0 isn't an exact multiple of
448 // NarrowSize.
449 if (SizeOp0 % NarrowSize != 0)
450 return UnableToLegalize;
451 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000452
453 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000454 for (int i = 0; i < NumParts; ++i)
455 DstRegs.push_back(
456 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000457
458 unsigned DstReg = MI.getOperand(0).getReg();
459 if(MRI.getType(DstReg).isVector())
460 MIRBuilder.buildBuildVector(DstReg, DstRegs);
461 else
462 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000463 MI.eraseFromParent();
464 return Legalized;
465 }
Tim Northover9656f142016-08-04 20:54:13 +0000466 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000467 // FIXME: add support for when SizeOp0 isn't an exact multiple of
468 // NarrowSize.
469 if (SizeOp0 % NarrowSize != 0)
470 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000471 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000472 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000473
Tim Northoverb18ea162016-09-20 15:20:36 +0000474 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000475 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
476 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
477
Tim Northover0f140c72016-09-09 11:46:34 +0000478 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
479 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000480
481 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000482 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
483 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000484
Tim Northover0f140c72016-09-09 11:46:34 +0000485 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000486 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000487
488 DstRegs.push_back(DstReg);
489 CarryIn = CarryOut;
490 }
Tim Northover0f140c72016-09-09 11:46:34 +0000491 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000492 if(MRI.getType(DstReg).isVector())
493 MIRBuilder.buildBuildVector(DstReg, DstRegs);
494 else
495 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000496 MI.eraseFromParent();
497 return Legalized;
498 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000499 case TargetOpcode::G_SUB: {
500 // FIXME: add support for when SizeOp0 isn't an exact multiple of
501 // NarrowSize.
502 if (SizeOp0 % NarrowSize != 0)
503 return UnableToLegalize;
504
505 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
506
507 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
508 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
509 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
510
511 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
512 unsigned BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
513 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
514 {Src1Regs[0], Src2Regs[0]});
515 DstRegs.push_back(DstReg);
516 unsigned BorrowIn = BorrowOut;
517 for (int i = 1; i < NumParts; ++i) {
518 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
519 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
520
521 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
522 {Src1Regs[i], Src2Regs[i], BorrowIn});
523
524 DstRegs.push_back(DstReg);
525 BorrowIn = BorrowOut;
526 }
527 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
528 MI.eraseFromParent();
529 return Legalized;
530 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000531 case TargetOpcode::G_MUL:
532 return narrowScalarMul(MI, TypeIdx, NarrowTy);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000533 case TargetOpcode::G_EXTRACT: {
534 if (TypeIdx != 1)
535 return UnableToLegalize;
536
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000537 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
538 // FIXME: add support for when SizeOp1 isn't an exact multiple of
539 // NarrowSize.
540 if (SizeOp1 % NarrowSize != 0)
541 return UnableToLegalize;
542 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000543
544 SmallVector<unsigned, 2> SrcRegs, DstRegs;
545 SmallVector<uint64_t, 2> Indexes;
546 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
547
548 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000549 uint64_t OpStart = MI.getOperand(2).getImm();
550 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000551 for (int i = 0; i < NumParts; ++i) {
552 unsigned SrcStart = i * NarrowSize;
553
554 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
555 // No part of the extract uses this subregister, ignore it.
556 continue;
557 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
558 // The entire subregister is extracted, forward the value.
559 DstRegs.push_back(SrcRegs[i]);
560 continue;
561 }
562
563 // OpSegStart is where this destination segment would start in OpReg if it
564 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000565 int64_t ExtractOffset;
566 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000567 if (OpStart < SrcStart) {
568 ExtractOffset = 0;
569 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
570 } else {
571 ExtractOffset = OpStart - SrcStart;
572 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
573 }
574
575 unsigned SegReg = SrcRegs[i];
576 if (ExtractOffset != 0 || SegSize != NarrowSize) {
577 // A genuine extract is needed.
578 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
579 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
580 }
581
582 DstRegs.push_back(SegReg);
583 }
584
Amara Emerson5ec14602018-12-10 18:44:58 +0000585 unsigned DstReg = MI.getOperand(0).getReg();
586 if(MRI.getType(DstReg).isVector())
587 MIRBuilder.buildBuildVector(DstReg, DstRegs);
588 else
589 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000590 MI.eraseFromParent();
591 return Legalized;
592 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000593 case TargetOpcode::G_INSERT: {
Matt Arsenault30989e42019-01-22 21:42:11 +0000594 // FIXME: Don't know how to handle secondary types yet.
595 if (TypeIdx != 0)
596 return UnableToLegalize;
597
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000598 // FIXME: add support for when SizeOp0 isn't an exact multiple of
599 // NarrowSize.
600 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000601 return UnableToLegalize;
602
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000603 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000604
605 SmallVector<unsigned, 2> SrcRegs, DstRegs;
606 SmallVector<uint64_t, 2> Indexes;
607 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
608
Tim Northover75e0b912017-03-06 18:23:04 +0000609 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000610 uint64_t OpStart = MI.getOperand(3).getImm();
611 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000612 for (int i = 0; i < NumParts; ++i) {
613 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000614
Tim Northover75e0b912017-03-06 18:23:04 +0000615 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000616 // No part of the insert affects this subregister, forward the original.
617 DstRegs.push_back(SrcRegs[i]);
618 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000619 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000620 // The entire subregister is defined by this insert, forward the new
621 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000622 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000623 continue;
624 }
625
Tim Northover2eb18d32017-03-07 21:24:33 +0000626 // OpSegStart is where this destination segment would start in OpReg if it
627 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000628 int64_t ExtractOffset, InsertOffset;
629 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000630 if (OpStart < DstStart) {
631 InsertOffset = 0;
632 ExtractOffset = DstStart - OpStart;
633 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
634 } else {
635 InsertOffset = OpStart - DstStart;
636 ExtractOffset = 0;
637 SegSize =
638 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
639 }
640
641 unsigned SegReg = OpReg;
642 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000643 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000644 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
645 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000646 }
647
Tim Northover75e0b912017-03-06 18:23:04 +0000648 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000649 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000650 DstRegs.push_back(DstReg);
651 }
652
653 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000654 unsigned DstReg = MI.getOperand(0).getReg();
655 if(MRI.getType(DstReg).isVector())
656 MIRBuilder.buildBuildVector(DstReg, DstRegs);
657 else
658 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000659 MI.eraseFromParent();
660 return Legalized;
661 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000662 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000663 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000664 unsigned DstReg = MI.getOperand(0).getReg();
665 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000666 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000667 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000668
669 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
670 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
671 auto &MMO = **MI.memoperands_begin();
672 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
673 MIRBuilder.buildAnyExt(DstReg, TmpReg);
674 MI.eraseFromParent();
675 return Legalized;
676 }
677
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000678 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000679 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000680 case TargetOpcode::G_ZEXTLOAD:
681 case TargetOpcode::G_SEXTLOAD: {
682 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
683 unsigned DstReg = MI.getOperand(0).getReg();
684 unsigned PtrReg = MI.getOperand(1).getReg();
685
686 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
687 auto &MMO = **MI.memoperands_begin();
688 if (MMO.getSize() * 8 == NarrowSize) {
689 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
690 } else {
691 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
692 : TargetOpcode::G_SEXTLOAD;
693 MIRBuilder.buildInstr(ExtLoad)
694 .addDef(TmpReg)
695 .addUse(PtrReg)
696 .addMemOperand(&MMO);
697 }
698
699 if (ZExt)
700 MIRBuilder.buildZExt(DstReg, TmpReg);
701 else
702 MIRBuilder.buildSExt(DstReg, TmpReg);
703
704 MI.eraseFromParent();
705 return Legalized;
706 }
Justin Bognerfde01042017-01-18 17:29:54 +0000707 case TargetOpcode::G_STORE: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000708 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000709
710 unsigned SrcReg = MI.getOperand(0).getReg();
711 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000712 if (SrcTy.isVector())
713 return UnableToLegalize;
714
715 int NumParts = SizeOp0 / NarrowSize;
716 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
717 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
718 if (SrcTy.isVector() && LeftoverBits != 0)
719 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000720
721 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
722 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
723 auto &MMO = **MI.memoperands_begin();
724 MIRBuilder.buildTrunc(TmpReg, SrcReg);
725 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
726 MI.eraseFromParent();
727 return Legalized;
728 }
729
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000730 return reduceLoadStoreWidth(MI, 0, NarrowTy);
Justin Bognerfde01042017-01-18 17:29:54 +0000731 }
Igor Breger29537882017-04-07 14:41:59 +0000732 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000733 // FIXME: add support for when SizeOp0 isn't an exact multiple of
734 // NarrowSize.
735 if (SizeOp0 % NarrowSize != 0)
736 return UnableToLegalize;
737 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000738 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000739 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000740
741 SmallVector<unsigned, 2> DstRegs;
742 for (int i = 0; i < NumParts; ++i) {
743 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
744 ConstantInt *CI =
745 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
746 MIRBuilder.buildConstant(DstReg, *CI);
747 DstRegs.push_back(DstReg);
748 }
749 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000750 if(MRI.getType(DstReg).isVector())
751 MIRBuilder.buildBuildVector(DstReg, DstRegs);
752 else
753 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000754 MI.eraseFromParent();
755 return Legalized;
756 }
Matt Arsenault81511e52019-02-05 00:13:44 +0000757 case TargetOpcode::G_SELECT:
758 return narrowScalarSelect(MI, TypeIdx, NarrowTy);
Petar Avramovic150fd432018-12-18 11:36:14 +0000759 case TargetOpcode::G_AND:
760 case TargetOpcode::G_OR:
761 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000762 // Legalize bitwise operation:
763 // A = BinOp<Ty> B, C
764 // into:
765 // B1, ..., BN = G_UNMERGE_VALUES B
766 // C1, ..., CN = G_UNMERGE_VALUES C
767 // A1 = BinOp<Ty/N> B1, C2
768 // ...
769 // AN = BinOp<Ty/N> BN, CN
770 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000771
772 // FIXME: add support for when SizeOp0 isn't an exact multiple of
773 // NarrowSize.
774 if (SizeOp0 % NarrowSize != 0)
775 return UnableToLegalize;
776 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000777
778 // List the registers where the destination will be scattered.
779 SmallVector<unsigned, 2> DstRegs;
780 // List the registers where the first argument will be split.
781 SmallVector<unsigned, 2> SrcsReg1;
782 // List the registers where the second argument will be split.
783 SmallVector<unsigned, 2> SrcsReg2;
784 // Create all the temporary registers.
785 for (int i = 0; i < NumParts; ++i) {
786 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
787 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
788 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
789
790 DstRegs.push_back(DstReg);
791 SrcsReg1.push_back(SrcReg1);
792 SrcsReg2.push_back(SrcReg2);
793 }
794 // Explode the big arguments into smaller chunks.
795 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
796 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
797
798 // Do the operation on each small part.
799 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000800 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
801 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000802
803 // Gather the destination registers into the final destination.
804 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000805 if(MRI.getType(DstReg).isVector())
806 MIRBuilder.buildBuildVector(DstReg, DstRegs);
807 else
808 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000809 MI.eraseFromParent();
810 return Legalized;
811 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000812 case TargetOpcode::G_SHL:
813 case TargetOpcode::G_LSHR:
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +0000814 case TargetOpcode::G_ASHR:
815 return narrowScalarShift(MI, TypeIdx, NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000816 case TargetOpcode::G_CTLZ:
817 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
818 case TargetOpcode::G_CTTZ:
819 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
820 case TargetOpcode::G_CTPOP:
821 if (TypeIdx != 0)
822 return UnableToLegalize; // TODO
823
824 Observer.changingInstr(MI);
825 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
826 Observer.changedInstr(MI);
827 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000828 case TargetOpcode::G_INTTOPTR:
829 if (TypeIdx != 1)
830 return UnableToLegalize;
831
832 Observer.changingInstr(MI);
833 narrowScalarSrc(MI, NarrowTy, 1);
834 Observer.changedInstr(MI);
835 return Legalized;
836 case TargetOpcode::G_PTRTOINT:
837 if (TypeIdx != 0)
838 return UnableToLegalize;
839
840 Observer.changingInstr(MI);
841 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
842 Observer.changedInstr(MI);
843 return Legalized;
Tim Northover9656f142016-08-04 20:54:13 +0000844 }
Tim Northover33b07d62016-07-22 20:03:43 +0000845}
846
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000847void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
848 unsigned OpIdx, unsigned ExtOpcode) {
849 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000850 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000851 MO.setReg(ExtB->getOperand(0).getReg());
852}
853
Matt Arsenault30989e42019-01-22 21:42:11 +0000854void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
855 unsigned OpIdx) {
856 MachineOperand &MO = MI.getOperand(OpIdx);
857 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
858 {MO.getReg()});
859 MO.setReg(ExtB->getOperand(0).getReg());
860}
861
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000862void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
863 unsigned OpIdx, unsigned TruncOpcode) {
864 MachineOperand &MO = MI.getOperand(OpIdx);
865 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
866 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000867 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000868 MO.setReg(DstExt);
869}
870
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000871void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
872 unsigned OpIdx, unsigned ExtOpcode) {
873 MachineOperand &MO = MI.getOperand(OpIdx);
874 unsigned DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
875 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
876 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
877 MO.setReg(DstTrunc);
878}
879
Tim Northover69fa84a2016-10-14 22:18:18 +0000880LegalizerHelper::LegalizeResult
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000881LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
882 LLT WideTy) {
883 if (TypeIdx != 1)
884 return UnableToLegalize;
885
886 unsigned DstReg = MI.getOperand(0).getReg();
887 LLT DstTy = MRI.getType(DstReg);
888 if (!DstTy.isScalar())
889 return UnableToLegalize;
890
891 unsigned NumOps = MI.getNumOperands();
892 unsigned NumSrc = MI.getNumOperands() - 1;
893 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
894
895 unsigned Src1 = MI.getOperand(1).getReg();
896 unsigned ResultReg = MIRBuilder.buildZExt(DstTy, Src1)->getOperand(0).getReg();
897
898 for (unsigned I = 2; I != NumOps; ++I) {
899 const unsigned Offset = (I - 1) * PartSize;
900
901 unsigned SrcReg = MI.getOperand(I).getReg();
902 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
903
904 auto ZextInput = MIRBuilder.buildZExt(DstTy, SrcReg);
905
906 unsigned NextResult = I + 1 == NumOps ? DstReg :
907 MRI.createGenericVirtualRegister(DstTy);
908
909 auto ShiftAmt = MIRBuilder.buildConstant(DstTy, Offset);
910 auto Shl = MIRBuilder.buildShl(DstTy, ZextInput, ShiftAmt);
911 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
912 ResultReg = NextResult;
913 }
914
915 MI.eraseFromParent();
916 return Legalized;
917}
918
919LegalizerHelper::LegalizeResult
920LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
921 LLT WideTy) {
922 if (TypeIdx != 0)
923 return UnableToLegalize;
924
925 unsigned NumDst = MI.getNumOperands() - 1;
926 unsigned SrcReg = MI.getOperand(NumDst).getReg();
927 LLT SrcTy = MRI.getType(SrcReg);
928 if (!SrcTy.isScalar())
929 return UnableToLegalize;
930
931 unsigned Dst0Reg = MI.getOperand(0).getReg();
932 LLT DstTy = MRI.getType(Dst0Reg);
933 if (!DstTy.isScalar())
934 return UnableToLegalize;
935
936 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
937 LLT NewSrcTy = LLT::scalar(NewSrcSize);
938 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
939
940 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
941
942 for (unsigned I = 1; I != NumDst; ++I) {
943 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
944 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
945 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
946 }
947
948 Observer.changingInstr(MI);
949
950 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
951 for (unsigned I = 0; I != NumDst; ++I)
952 widenScalarDst(MI, WideTy, I);
953
954 Observer.changedInstr(MI);
955
956 return Legalized;
957}
958
959LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +0000960LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000961 MIRBuilder.setInstr(MI);
962
Tim Northover32335812016-08-04 18:35:11 +0000963 switch (MI.getOpcode()) {
964 default:
965 return UnableToLegalize;
Matt Arsenault0e5d8562019-02-02 23:56:00 +0000966 case TargetOpcode::G_EXTRACT: {
967 if (TypeIdx != 1)
968 return UnableToLegalize;
969
970 unsigned SrcReg = MI.getOperand(1).getReg();
971 LLT SrcTy = MRI.getType(SrcReg);
972 if (!SrcTy.isVector())
973 return UnableToLegalize;
974
975 unsigned DstReg = MI.getOperand(0).getReg();
976 LLT DstTy = MRI.getType(DstReg);
977 if (DstTy != SrcTy.getElementType())
978 return UnableToLegalize;
979
980 unsigned Offset = MI.getOperand(2).getImm();
981 if (Offset % SrcTy.getScalarSizeInBits() != 0)
982 return UnableToLegalize;
983
984 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
985
986 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
987 Offset);
988 widenScalarDst(MI, WideTy.getScalarType(), 0);
989
990 return Legalized;
991 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000992 case TargetOpcode::G_MERGE_VALUES:
993 return widenScalarMergeValues(MI, TypeIdx, WideTy);
994 case TargetOpcode::G_UNMERGE_VALUES:
995 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000996 case TargetOpcode::G_UADDO:
997 case TargetOpcode::G_USUBO: {
998 if (TypeIdx == 1)
999 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001000 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1001 {MI.getOperand(2).getReg()});
1002 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1003 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001004 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
1005 ? TargetOpcode::G_ADD
1006 : TargetOpcode::G_SUB;
1007 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001008 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001009 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
1010 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
1011 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001012 TargetOpcode::G_AND, {WideTy},
1013 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001014 // There is no overflow if the AndOp is the same as NewOp.
1015 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1016 AndOp);
1017 // Now trunc the NewOp to the original result.
1018 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1019 MI.eraseFromParent();
1020 return Legalized;
1021 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001022 case TargetOpcode::G_CTTZ:
1023 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1024 case TargetOpcode::G_CTLZ:
1025 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1026 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001027 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001028 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001029 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001030 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001031 return Legalized;
1032 }
1033
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001034 unsigned SrcReg = MI.getOperand(1).getReg();
1035
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001036 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001037 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1038 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001039 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1040 // The count is the same in the larger type except if the original
1041 // value was zero. This can be handled by setting the bit just off
1042 // the top of the original type.
1043 auto TopBit =
1044 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001045 MIBSrc = MIRBuilder.buildOr(
1046 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001047 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001048
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001049 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001050 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001051 // This is already the correct result for CTPOP and CTTZs
1052 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1053 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1054 // The correct result is NewOp - (Difference in widety and current ty).
1055 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001056 MIBNewOp = MIRBuilder.buildInstr(
1057 TargetOpcode::G_SUB, {WideTy},
1058 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001059 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001060
1061 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1062 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001063 return Legalized;
1064 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001065 case TargetOpcode::G_BSWAP: {
1066 Observer.changingInstr(MI);
1067 unsigned DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001068
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001069 unsigned ShrReg = MRI.createGenericVirtualRegister(WideTy);
1070 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
1071 unsigned ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
1072 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1073
1074 MI.getOperand(0).setReg(DstExt);
1075
1076 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1077
1078 LLT Ty = MRI.getType(DstReg);
1079 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1080 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1081 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1082 .addDef(ShrReg)
1083 .addUse(DstExt)
1084 .addUse(ShiftAmtReg);
1085
1086 MIRBuilder.buildTrunc(DstReg, ShrReg);
1087 Observer.changedInstr(MI);
1088 return Legalized;
1089 }
Tim Northover61c16142016-08-04 21:39:49 +00001090 case TargetOpcode::G_ADD:
1091 case TargetOpcode::G_AND:
1092 case TargetOpcode::G_MUL:
1093 case TargetOpcode::G_OR:
1094 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001095 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +00001096 // Perform operation at larger width (any extension is fine here, high bits
1097 // don't affect the result) and then truncate the result back to the
1098 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001099 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001100 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1101 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1102 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001103 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001104 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001105
Roman Tereshin6d266382018-05-09 21:43:30 +00001106 case TargetOpcode::G_SHL:
Matt Arsenault30989e42019-01-22 21:42:11 +00001107 Observer.changingInstr(MI);
1108
1109 if (TypeIdx == 0) {
1110 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1111 widenScalarDst(MI, WideTy);
1112 } else {
1113 assert(TypeIdx == 1);
1114 // The "number of bits to shift" operand must preserve its value as an
1115 // unsigned integer:
1116 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1117 }
1118
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001119 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001120 return Legalized;
1121
Tim Northover7a753d92016-08-26 17:46:06 +00001122 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001123 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001124 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001125 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1126 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1127 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001128 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001129 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001130
Roman Tereshin6d266382018-05-09 21:43:30 +00001131 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001132 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001133 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001134
1135 if (TypeIdx == 0) {
1136 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1137 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1138
1139 widenScalarSrc(MI, WideTy, 1, CvtOp);
1140 widenScalarDst(MI, WideTy);
1141 } else {
1142 assert(TypeIdx == 1);
1143 // The "number of bits to shift" operand must preserve its value as an
1144 // unsigned integer:
1145 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1146 }
1147
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001148 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001149 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001150 case TargetOpcode::G_UDIV:
1151 case TargetOpcode::G_UREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001152 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001153 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1154 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1155 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001156 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001157 return Legalized;
1158
1159 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001160 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001161 if (TypeIdx == 0) {
1162 // Perform operation at larger width (any extension is fine here, high
1163 // bits don't affect the result) and then truncate the result back to the
1164 // original type.
1165 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1166 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1167 widenScalarDst(MI, WideTy);
1168 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001169 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001170 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001171 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001172 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001173 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001174 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001175
Ahmed Bougachab6137062017-01-23 21:10:14 +00001176 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001177 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001178 if (TypeIdx != 0)
1179 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001180 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001181 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001182 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001183 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001184
Ahmed Bougachad2948232017-01-20 01:37:24 +00001185 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001186 if (TypeIdx != 1)
1187 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001188 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001189 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001190 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001191 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001192
1193 case TargetOpcode::G_UITOFP:
1194 if (TypeIdx != 1)
1195 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001196 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001197 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001198 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001199 return Legalized;
1200
1201 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +00001202 if (TypeIdx != 0)
1203 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001204 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001205 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1206 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001207 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001208 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001209
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001210 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001211 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001212 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001213 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001214 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001215 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001216 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001217
Tim Northover3c73e362016-08-23 18:20:09 +00001218 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001219 if (TypeIdx != 0)
1220 return UnableToLegalize;
1221
1222 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1223 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001224 return UnableToLegalize;
1225
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001226 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001227
1228 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1229 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1230 widenScalarSrc(MI, WideTy, 0, ExtType);
1231
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001232 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001233 return Legalized;
1234 }
Tim Northoverea904f92016-08-19 22:40:00 +00001235 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001236 MachineOperand &SrcMO = MI.getOperand(1);
1237 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1238 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001239 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001240 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1241
1242 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001243 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001244 return Legalized;
1245 }
Tim Northovera11be042016-08-19 22:40:08 +00001246 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001247 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001248 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001249 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001250 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001251 switch (WideTy.getSizeInBits()) {
1252 case 32:
1253 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
1254 break;
1255 case 64:
1256 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
1257 break;
1258 default:
1259 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +00001260 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001261 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001262 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1263
1264 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001265 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001266 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001267 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001268 case TargetOpcode::G_IMPLICIT_DEF: {
1269 Observer.changingInstr(MI);
1270 widenScalarDst(MI, WideTy);
1271 Observer.changedInstr(MI);
1272 return Legalized;
1273 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001274 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001275 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001276 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001277 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001278 return Legalized;
1279
1280 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001281 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001282 if (TypeIdx == 0)
1283 widenScalarDst(MI, WideTy);
1284 else {
1285 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1286 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001287 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001288 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001289 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001290
1291 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001292 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001293 if (TypeIdx == 0)
1294 widenScalarDst(MI, WideTy);
1295 else {
1296 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1297 MI.getOperand(1).getPredicate()))
1298 ? TargetOpcode::G_SEXT
1299 : TargetOpcode::G_ZEXT;
1300 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1301 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1302 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001303 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001304 return Legalized;
1305
1306 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001307 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001308 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001309 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001310 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001311 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001312
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001313 case TargetOpcode::G_PHI: {
1314 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001315
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001316 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001317 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1318 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1319 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1320 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001321 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001322
1323 MachineBasicBlock &MBB = *MI.getParent();
1324 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1325 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001326 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001327 return Legalized;
1328 }
Matt Arsenault63786292019-01-22 20:38:15 +00001329 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1330 if (TypeIdx == 0) {
1331 unsigned VecReg = MI.getOperand(1).getReg();
1332 LLT VecTy = MRI.getType(VecReg);
1333 Observer.changingInstr(MI);
1334
1335 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1336 WideTy.getSizeInBits()),
1337 1, TargetOpcode::G_SEXT);
1338
1339 widenScalarDst(MI, WideTy, 0);
1340 Observer.changedInstr(MI);
1341 return Legalized;
1342 }
1343
Amara Emersoncbd86d82018-10-25 14:04:54 +00001344 if (TypeIdx != 2)
1345 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001346 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001347 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001348 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001349 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001350 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001351 case TargetOpcode::G_FADD:
1352 case TargetOpcode::G_FMUL:
1353 case TargetOpcode::G_FSUB:
1354 case TargetOpcode::G_FMA:
1355 case TargetOpcode::G_FNEG:
1356 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001357 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001358 case TargetOpcode::G_FDIV:
1359 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001360 case TargetOpcode::G_FCEIL:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001361 case TargetOpcode::G_FCOS:
1362 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001363 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001364 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001365 case TargetOpcode::G_FLOG2:
Jessica Paquette22457f82019-01-30 21:03:52 +00001366 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001367 case TargetOpcode::G_FEXP:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001368 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001369 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001370
1371 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1372 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1373
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001374 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1375 Observer.changedInstr(MI);
1376 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001377 case TargetOpcode::G_INTTOPTR:
1378 if (TypeIdx != 1)
1379 return UnableToLegalize;
1380
1381 Observer.changingInstr(MI);
1382 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1383 Observer.changedInstr(MI);
1384 return Legalized;
1385 case TargetOpcode::G_PTRTOINT:
1386 if (TypeIdx != 0)
1387 return UnableToLegalize;
1388
1389 Observer.changingInstr(MI);
1390 widenScalarDst(MI, WideTy, 0);
1391 Observer.changedInstr(MI);
1392 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001393 }
Tim Northover33b07d62016-07-22 20:03:43 +00001394}
1395
Tim Northover69fa84a2016-10-14 22:18:18 +00001396LegalizerHelper::LegalizeResult
1397LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001398 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001399 MIRBuilder.setInstr(MI);
1400
1401 switch(MI.getOpcode()) {
1402 default:
1403 return UnableToLegalize;
1404 case TargetOpcode::G_SREM:
1405 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001406 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1407 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001408 .addDef(QuotReg)
1409 .addUse(MI.getOperand(1).getReg())
1410 .addUse(MI.getOperand(2).getReg());
1411
Tim Northover0f140c72016-09-09 11:46:34 +00001412 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1413 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1414 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1415 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001416 MI.eraseFromParent();
1417 return Legalized;
1418 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001419 case TargetOpcode::G_SMULO:
1420 case TargetOpcode::G_UMULO: {
1421 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1422 // result.
1423 unsigned Res = MI.getOperand(0).getReg();
1424 unsigned Overflow = MI.getOperand(1).getReg();
1425 unsigned LHS = MI.getOperand(2).getReg();
1426 unsigned RHS = MI.getOperand(3).getReg();
1427
1428 MIRBuilder.buildMul(Res, LHS, RHS);
1429
1430 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1431 ? TargetOpcode::G_SMULH
1432 : TargetOpcode::G_UMULH;
1433
1434 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1435 MIRBuilder.buildInstr(Opcode)
1436 .addDef(HiPart)
1437 .addUse(LHS)
1438 .addUse(RHS);
1439
1440 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1441 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001442
1443 // For *signed* multiply, overflow is detected by checking:
1444 // (hi != (lo >> bitwidth-1))
1445 if (Opcode == TargetOpcode::G_SMULH) {
1446 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1447 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1448 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1449 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1450 .addDef(Shifted)
1451 .addUse(Res)
1452 .addUse(ShiftAmt);
1453 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1454 } else {
1455 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1456 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001457 MI.eraseFromParent();
1458 return Legalized;
1459 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001460 case TargetOpcode::G_FNEG: {
1461 // TODO: Handle vector types once we are able to
1462 // represent them.
1463 if (Ty.isVector())
1464 return UnableToLegalize;
1465 unsigned Res = MI.getOperand(0).getReg();
1466 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001467 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001468 switch (Ty.getSizeInBits()) {
1469 case 16:
1470 ZeroTy = Type::getHalfTy(Ctx);
1471 break;
1472 case 32:
1473 ZeroTy = Type::getFloatTy(Ctx);
1474 break;
1475 case 64:
1476 ZeroTy = Type::getDoubleTy(Ctx);
1477 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001478 case 128:
1479 ZeroTy = Type::getFP128Ty(Ctx);
1480 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001481 default:
1482 llvm_unreachable("unexpected floating-point type");
1483 }
1484 ConstantFP &ZeroForNegation =
1485 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001486 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001487 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1488 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001489 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001490 .addUse(MI.getOperand(1).getReg());
1491 MI.eraseFromParent();
1492 return Legalized;
1493 }
Volkan Keles225921a2017-03-10 21:25:09 +00001494 case TargetOpcode::G_FSUB: {
1495 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1496 // First, check if G_FNEG is marked as Lower. If so, we may
1497 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001498 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001499 return UnableToLegalize;
1500 unsigned Res = MI.getOperand(0).getReg();
1501 unsigned LHS = MI.getOperand(1).getReg();
1502 unsigned RHS = MI.getOperand(2).getReg();
1503 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1504 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1505 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1506 .addDef(Res)
1507 .addUse(LHS)
1508 .addUse(Neg);
1509 MI.eraseFromParent();
1510 return Legalized;
1511 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001512 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1513 unsigned OldValRes = MI.getOperand(0).getReg();
1514 unsigned SuccessRes = MI.getOperand(1).getReg();
1515 unsigned Addr = MI.getOperand(2).getReg();
1516 unsigned CmpVal = MI.getOperand(3).getReg();
1517 unsigned NewVal = MI.getOperand(4).getReg();
1518 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1519 **MI.memoperands_begin());
1520 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1521 MI.eraseFromParent();
1522 return Legalized;
1523 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001524 case TargetOpcode::G_LOAD:
1525 case TargetOpcode::G_SEXTLOAD:
1526 case TargetOpcode::G_ZEXTLOAD: {
1527 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1528 unsigned DstReg = MI.getOperand(0).getReg();
1529 unsigned PtrReg = MI.getOperand(1).getReg();
1530 LLT DstTy = MRI.getType(DstReg);
1531 auto &MMO = **MI.memoperands_begin();
1532
1533 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001534 // In the case of G_LOAD, this was a non-extending load already and we're
1535 // about to lower to the same instruction.
1536 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1537 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001538 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1539 MI.eraseFromParent();
1540 return Legalized;
1541 }
1542
1543 if (DstTy.isScalar()) {
1544 unsigned TmpReg = MRI.createGenericVirtualRegister(
1545 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1546 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1547 switch (MI.getOpcode()) {
1548 default:
1549 llvm_unreachable("Unexpected opcode");
1550 case TargetOpcode::G_LOAD:
1551 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1552 break;
1553 case TargetOpcode::G_SEXTLOAD:
1554 MIRBuilder.buildSExt(DstReg, TmpReg);
1555 break;
1556 case TargetOpcode::G_ZEXTLOAD:
1557 MIRBuilder.buildZExt(DstReg, TmpReg);
1558 break;
1559 }
1560 MI.eraseFromParent();
1561 return Legalized;
1562 }
1563
1564 return UnableToLegalize;
1565 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001566 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1567 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1568 case TargetOpcode::G_CTLZ:
1569 case TargetOpcode::G_CTTZ:
1570 case TargetOpcode::G_CTPOP:
1571 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001572 case G_UADDE: {
1573 unsigned Res = MI.getOperand(0).getReg();
1574 unsigned CarryOut = MI.getOperand(1).getReg();
1575 unsigned LHS = MI.getOperand(2).getReg();
1576 unsigned RHS = MI.getOperand(3).getReg();
1577 unsigned CarryIn = MI.getOperand(4).getReg();
1578
1579 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1580 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1581
1582 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1583 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1584 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1585 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1586
1587 MI.eraseFromParent();
1588 return Legalized;
1589 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001590 case G_USUBO: {
1591 unsigned Res = MI.getOperand(0).getReg();
1592 unsigned BorrowOut = MI.getOperand(1).getReg();
1593 unsigned LHS = MI.getOperand(2).getReg();
1594 unsigned RHS = MI.getOperand(3).getReg();
1595
1596 MIRBuilder.buildSub(Res, LHS, RHS);
1597 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1598
1599 MI.eraseFromParent();
1600 return Legalized;
1601 }
1602 case G_USUBE: {
1603 unsigned Res = MI.getOperand(0).getReg();
1604 unsigned BorrowOut = MI.getOperand(1).getReg();
1605 unsigned LHS = MI.getOperand(2).getReg();
1606 unsigned RHS = MI.getOperand(3).getReg();
1607 unsigned BorrowIn = MI.getOperand(4).getReg();
1608
1609 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1610 unsigned ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1611 unsigned LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1612 unsigned LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1613
1614 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1615 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1616 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1617 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1618 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1619 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1620
1621 MI.eraseFromParent();
1622 return Legalized;
1623 }
Tim Northovercecee562016-08-26 17:46:13 +00001624 }
1625}
1626
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001627LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1628 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
1629 SmallVector<unsigned, 2> DstRegs;
1630
1631 unsigned NarrowSize = NarrowTy.getSizeInBits();
1632 unsigned DstReg = MI.getOperand(0).getReg();
1633 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1634 int NumParts = Size / NarrowSize;
1635 // FIXME: Don't know how to handle the situation where the small vectors
1636 // aren't all the same size yet.
1637 if (Size % NarrowSize != 0)
1638 return UnableToLegalize;
1639
1640 for (int i = 0; i < NumParts; ++i) {
1641 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1642 MIRBuilder.buildUndef(TmpReg);
1643 DstRegs.push_back(TmpReg);
1644 }
1645
1646 if (NarrowTy.isVector())
1647 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1648 else
1649 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1650
1651 MI.eraseFromParent();
1652 return Legalized;
1653}
1654
1655LegalizerHelper::LegalizeResult
1656LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
1657 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001658 const unsigned Opc = MI.getOpcode();
1659 const unsigned NumOps = MI.getNumOperands() - 1;
1660 const unsigned NarrowSize = NarrowTy.getSizeInBits();
1661 const unsigned DstReg = MI.getOperand(0).getReg();
1662 const unsigned Flags = MI.getFlags();
1663 const LLT DstTy = MRI.getType(DstReg);
1664 const unsigned Size = DstTy.getSizeInBits();
1665 const int NumParts = Size / NarrowSize;
1666 const LLT EltTy = DstTy.getElementType();
1667 const unsigned EltSize = EltTy.getSizeInBits();
1668 const unsigned BitsForNumParts = NarrowSize * NumParts;
1669
1670 // Check if we have any leftovers. If we do, then only handle the case where
1671 // the leftover is one element.
1672 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001673 return UnableToLegalize;
1674
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001675 if (BitsForNumParts != Size) {
1676 unsigned AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
1677 MIRBuilder.buildUndef(AccumDstReg);
1678
1679 // Handle the pieces which evenly divide into the requested type with
1680 // extract/op/insert sequence.
1681 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
1682 SmallVector<SrcOp, 4> SrcOps;
1683 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1684 unsigned PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
1685 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
1686 SrcOps.push_back(PartOpReg);
1687 }
1688
1689 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
1690 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1691
1692 unsigned PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
1693 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
1694 AccumDstReg = PartInsertReg;
1695 Offset += NarrowSize;
1696 }
1697
1698 // Handle the remaining element sized leftover piece.
1699 SmallVector<SrcOp, 4> SrcOps;
1700 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1701 unsigned PartOpReg = MRI.createGenericVirtualRegister(EltTy);
1702 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
1703 BitsForNumParts);
1704 SrcOps.push_back(PartOpReg);
1705 }
1706
1707 unsigned PartDstReg = MRI.createGenericVirtualRegister(EltTy);
1708 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1709 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
1710 MI.eraseFromParent();
1711
1712 return Legalized;
1713 }
1714
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001715 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1716
1717 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1718
1719 if (NumOps >= 2)
1720 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1721
1722 if (NumOps >= 3)
1723 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
1724
1725 for (int i = 0; i < NumParts; ++i) {
1726 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1727
1728 if (NumOps == 1)
1729 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1730 else if (NumOps == 2) {
1731 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1732 } else if (NumOps == 3) {
1733 MIRBuilder.buildInstr(Opc, {DstReg},
1734 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1735 }
1736
1737 DstRegs.push_back(DstReg);
1738 }
1739
1740 if (NarrowTy.isVector())
1741 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1742 else
1743 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1744
1745 MI.eraseFromParent();
1746 return Legalized;
1747}
1748
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001749// Handle splitting vector operations which need to have the same number of
1750// elements in each type index, but each type index may have a different element
1751// type.
1752//
1753// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
1754// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1755// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1756//
1757// Also handles some irregular breakdown cases, e.g.
1758// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
1759// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1760// s64 = G_SHL s64, s32
1761LegalizerHelper::LegalizeResult
1762LegalizerHelper::fewerElementsVectorMultiEltType(
1763 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
1764 if (TypeIdx != 0)
1765 return UnableToLegalize;
1766
1767 const LLT NarrowTy0 = NarrowTyArg;
1768 const unsigned NewNumElts =
1769 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
1770
1771 const unsigned DstReg = MI.getOperand(0).getReg();
1772 LLT DstTy = MRI.getType(DstReg);
1773 LLT LeftoverTy0;
1774
1775 // All of the operands need to have the same number of elements, so if we can
1776 // determine a type breakdown for the result type, we can for all of the
1777 // source types.
1778 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0);
1779 if (NumParts < 0)
1780 return UnableToLegalize;
1781
1782 SmallVector<MachineInstrBuilder, 4> NewInsts;
1783
1784 SmallVector<unsigned, 4> DstRegs, LeftoverDstRegs;
1785 SmallVector<unsigned, 4> PartRegs, LeftoverRegs;
1786
1787 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1788 LLT LeftoverTy;
1789 unsigned SrcReg = MI.getOperand(I).getReg();
1790 LLT SrcTyI = MRI.getType(SrcReg);
1791 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
1792 LLT LeftoverTyI;
1793
1794 // Split this operand into the requested typed registers, and any leftover
1795 // required to reproduce the original type.
1796 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
1797 LeftoverRegs))
1798 return UnableToLegalize;
1799
1800 if (I == 1) {
1801 // For the first operand, create an instruction for each part and setup
1802 // the result.
1803 for (unsigned PartReg : PartRegs) {
1804 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1805 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
1806 .addDef(PartDstReg)
1807 .addUse(PartReg));
1808 DstRegs.push_back(PartDstReg);
1809 }
1810
1811 for (unsigned LeftoverReg : LeftoverRegs) {
1812 unsigned PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
1813 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
1814 .addDef(PartDstReg)
1815 .addUse(LeftoverReg));
1816 LeftoverDstRegs.push_back(PartDstReg);
1817 }
1818 } else {
1819 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
1820
1821 // Add the newly created operand splits to the existing instructions. The
1822 // odd-sized pieces are ordered after the requested NarrowTyArg sized
1823 // pieces.
1824 unsigned InstCount = 0;
1825 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
1826 NewInsts[InstCount++].addUse(PartRegs[J]);
1827 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
1828 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
1829 }
1830
1831 PartRegs.clear();
1832 LeftoverRegs.clear();
1833 }
1834
1835 // Insert the newly built operations and rebuild the result register.
1836 for (auto &MIB : NewInsts)
1837 MIRBuilder.insertInstr(MIB);
1838
1839 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
1840
1841 MI.eraseFromParent();
1842 return Legalized;
1843}
1844
Tim Northover69fa84a2016-10-14 22:18:18 +00001845LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001846LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1847 LLT NarrowTy) {
1848 if (TypeIdx != 0)
1849 return UnableToLegalize;
1850
1851 unsigned DstReg = MI.getOperand(0).getReg();
1852 unsigned SrcReg = MI.getOperand(1).getReg();
1853 LLT DstTy = MRI.getType(DstReg);
1854 LLT SrcTy = MRI.getType(SrcReg);
1855
1856 LLT NarrowTy0 = NarrowTy;
1857 LLT NarrowTy1;
1858 unsigned NumParts;
1859
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001860 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00001861 // Uneven breakdown not handled.
1862 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1863 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1864 return UnableToLegalize;
1865
1866 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001867 } else {
1868 NumParts = DstTy.getNumElements();
1869 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00001870 }
1871
1872 SmallVector<unsigned, 4> SrcRegs, DstRegs;
1873 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1874
1875 for (unsigned I = 0; I < NumParts; ++I) {
1876 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1877 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1878 .addDef(DstReg)
1879 .addUse(SrcRegs[I]);
1880
1881 NewInst->setFlags(MI.getFlags());
1882 DstRegs.push_back(DstReg);
1883 }
1884
1885 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001886 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001887 else
1888 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1889
1890 MI.eraseFromParent();
1891 return Legalized;
1892}
1893
1894LegalizerHelper::LegalizeResult
1895LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1896 LLT NarrowTy) {
1897 unsigned DstReg = MI.getOperand(0).getReg();
1898 unsigned Src0Reg = MI.getOperand(2).getReg();
1899 LLT DstTy = MRI.getType(DstReg);
1900 LLT SrcTy = MRI.getType(Src0Reg);
1901
1902 unsigned NumParts;
1903 LLT NarrowTy0, NarrowTy1;
1904
1905 if (TypeIdx == 0) {
1906 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1907 unsigned OldElts = DstTy.getNumElements();
1908
1909 NarrowTy0 = NarrowTy;
1910 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
1911 NarrowTy1 = NarrowTy.isVector() ?
1912 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
1913 SrcTy.getElementType();
1914
1915 } else {
1916 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1917 unsigned OldElts = SrcTy.getNumElements();
1918
1919 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
1920 NarrowTy.getNumElements();
1921 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
1922 DstTy.getScalarSizeInBits());
1923 NarrowTy1 = NarrowTy;
1924 }
1925
1926 // FIXME: Don't know how to handle the situation where the small vectors
1927 // aren't all the same size yet.
1928 if (NarrowTy1.isVector() &&
1929 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
1930 return UnableToLegalize;
1931
1932 CmpInst::Predicate Pred
1933 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
1934
1935 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1936 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
1937 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
1938
1939 for (unsigned I = 0; I < NumParts; ++I) {
1940 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1941 DstRegs.push_back(DstReg);
1942
1943 if (MI.getOpcode() == TargetOpcode::G_ICMP)
1944 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1945 else {
1946 MachineInstr *NewCmp
1947 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1948 NewCmp->setFlags(MI.getFlags());
1949 }
1950 }
1951
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001952 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00001953 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1954 else
1955 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1956
1957 MI.eraseFromParent();
1958 return Legalized;
1959}
1960
1961LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00001962LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
1963 LLT NarrowTy) {
1964 unsigned DstReg = MI.getOperand(0).getReg();
1965 unsigned CondReg = MI.getOperand(1).getReg();
1966
1967 unsigned NumParts = 0;
1968 LLT NarrowTy0, NarrowTy1;
1969
1970 LLT DstTy = MRI.getType(DstReg);
1971 LLT CondTy = MRI.getType(CondReg);
1972 unsigned Size = DstTy.getSizeInBits();
1973
1974 assert(TypeIdx == 0 || CondTy.isVector());
1975
1976 if (TypeIdx == 0) {
1977 NarrowTy0 = NarrowTy;
1978 NarrowTy1 = CondTy;
1979
1980 unsigned NarrowSize = NarrowTy0.getSizeInBits();
1981 // FIXME: Don't know how to handle the situation where the small vectors
1982 // aren't all the same size yet.
1983 if (Size % NarrowSize != 0)
1984 return UnableToLegalize;
1985
1986 NumParts = Size / NarrowSize;
1987
1988 // Need to break down the condition type
1989 if (CondTy.isVector()) {
1990 if (CondTy.getNumElements() == NumParts)
1991 NarrowTy1 = CondTy.getElementType();
1992 else
1993 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
1994 CondTy.getScalarSizeInBits());
1995 }
1996 } else {
1997 NumParts = CondTy.getNumElements();
1998 if (NarrowTy.isVector()) {
1999 // TODO: Handle uneven breakdown.
2000 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
2001 return UnableToLegalize;
2002
2003 return UnableToLegalize;
2004 } else {
2005 NarrowTy0 = DstTy.getElementType();
2006 NarrowTy1 = NarrowTy;
2007 }
2008 }
2009
2010 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
2011 if (CondTy.isVector())
2012 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2013
2014 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2015 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2016
2017 for (unsigned i = 0; i < NumParts; ++i) {
2018 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
2019 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2020 Src1Regs[i], Src2Regs[i]);
2021 DstRegs.push_back(DstReg);
2022 }
2023
2024 if (NarrowTy0.isVector())
2025 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2026 else
2027 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2028
2029 MI.eraseFromParent();
2030 return Legalized;
2031}
2032
2033LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002034LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2035 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002036 // FIXME: Don't know how to handle secondary types yet.
2037 if (TypeIdx != 0)
2038 return UnableToLegalize;
2039
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002040 MachineMemOperand *MMO = *MI.memoperands_begin();
2041
2042 // This implementation doesn't work for atomics. Give up instead of doing
2043 // something invalid.
2044 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2045 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2046 return UnableToLegalize;
2047
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002048 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
2049 unsigned ValReg = MI.getOperand(0).getReg();
2050 unsigned AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002051 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002052
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002053 int NumParts = -1;
2054 LLT LeftoverTy;
2055 SmallVector<unsigned, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002056 if (IsLoad) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002057 NumParts = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
2058 } else {
2059 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
2060 NarrowLeftoverRegs))
2061 NumParts = NarrowRegs.size();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002062 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002063
2064 if (NumParts == -1)
2065 return UnableToLegalize;
2066
2067 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2068
2069 unsigned TotalSize = ValTy.getSizeInBits();
2070
2071 // Split the load/store into PartTy sized pieces starting at Offset. If this
2072 // is a load, return the new registers in ValRegs. For a store, each elements
2073 // of ValRegs should be PartTy. Returns the next offset that needs to be
2074 // handled.
2075 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<unsigned> &ValRegs,
2076 unsigned Offset) -> unsigned {
2077 MachineFunction &MF = MIRBuilder.getMF();
2078 unsigned PartSize = PartTy.getSizeInBits();
2079 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2080 Offset += PartSize, ++Idx) {
2081 unsigned ByteSize = PartSize / 8;
2082 unsigned ByteOffset = Offset / 8;
2083 unsigned NewAddrReg = 0;
2084
2085 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2086
2087 MachineMemOperand *NewMMO =
2088 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2089
2090 if (IsLoad) {
2091 unsigned Dst = MRI.createGenericVirtualRegister(PartTy);
2092 ValRegs.push_back(Dst);
2093 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2094 } else {
2095 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2096 }
2097 }
2098
2099 return Offset;
2100 };
2101
2102 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2103
2104 // Handle the rest of the register if this isn't an even type breakdown.
2105 if (LeftoverTy.isValid())
2106 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2107
2108 if (IsLoad) {
2109 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2110 LeftoverTy, NarrowLeftoverRegs);
2111 }
2112
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002113 MI.eraseFromParent();
2114 return Legalized;
2115}
2116
2117LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002118LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2119 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002120 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002121
2122 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002123 switch (MI.getOpcode()) {
2124 case G_IMPLICIT_DEF:
2125 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2126 case G_AND:
2127 case G_OR:
2128 case G_XOR:
2129 case G_ADD:
2130 case G_SUB:
2131 case G_MUL:
2132 case G_SMULH:
2133 case G_UMULH:
2134 case G_FADD:
2135 case G_FMUL:
2136 case G_FSUB:
2137 case G_FNEG:
2138 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002139 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002140 case G_FDIV:
2141 case G_FREM:
2142 case G_FMA:
2143 case G_FPOW:
2144 case G_FEXP:
2145 case G_FEXP2:
2146 case G_FLOG:
2147 case G_FLOG2:
2148 case G_FLOG10:
2149 case G_FCEIL:
2150 case G_INTRINSIC_ROUND:
2151 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002152 case G_FCOS:
2153 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002154 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002155 case G_BSWAP:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002156 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002157 case G_SHL:
2158 case G_LSHR:
2159 case G_ASHR:
2160 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002161 case G_ZEXT:
2162 case G_SEXT:
2163 case G_ANYEXT:
2164 case G_FPEXT:
2165 case G_FPTRUNC:
2166 case G_SITOFP:
2167 case G_UITOFP:
2168 case G_FPTOSI:
2169 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002170 case G_INTTOPTR:
2171 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002172 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002173 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2174 case G_ICMP:
2175 case G_FCMP:
2176 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002177 case G_SELECT:
2178 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002179 case G_LOAD:
2180 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002181 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002182 default:
2183 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002184 }
2185}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002186
2187LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002188LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2189 const LLT HalfTy, const LLT AmtTy) {
2190
2191 unsigned InL = MRI.createGenericVirtualRegister(HalfTy);
2192 unsigned InH = MRI.createGenericVirtualRegister(HalfTy);
2193 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2194
2195 if (Amt.isNullValue()) {
2196 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2197 MI.eraseFromParent();
2198 return Legalized;
2199 }
2200
2201 LLT NVT = HalfTy;
2202 unsigned NVTBits = HalfTy.getSizeInBits();
2203 unsigned VTBits = 2 * NVTBits;
2204
2205 SrcOp Lo(0), Hi(0);
2206 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2207 if (Amt.ugt(VTBits)) {
2208 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2209 } else if (Amt.ugt(NVTBits)) {
2210 Lo = MIRBuilder.buildConstant(NVT, 0);
2211 Hi = MIRBuilder.buildShl(NVT, InL,
2212 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2213 } else if (Amt == NVTBits) {
2214 Lo = MIRBuilder.buildConstant(NVT, 0);
2215 Hi = InL;
2216 } else {
2217 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002218 auto OrLHS =
2219 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2220 auto OrRHS = MIRBuilder.buildLShr(
2221 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2222 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002223 }
2224 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2225 if (Amt.ugt(VTBits)) {
2226 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2227 } else if (Amt.ugt(NVTBits)) {
2228 Lo = MIRBuilder.buildLShr(NVT, InH,
2229 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2230 Hi = MIRBuilder.buildConstant(NVT, 0);
2231 } else if (Amt == NVTBits) {
2232 Lo = InH;
2233 Hi = MIRBuilder.buildConstant(NVT, 0);
2234 } else {
2235 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2236
2237 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2238 auto OrRHS = MIRBuilder.buildShl(
2239 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2240
2241 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2242 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2243 }
2244 } else {
2245 if (Amt.ugt(VTBits)) {
2246 Hi = Lo = MIRBuilder.buildAShr(
2247 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2248 } else if (Amt.ugt(NVTBits)) {
2249 Lo = MIRBuilder.buildAShr(NVT, InH,
2250 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2251 Hi = MIRBuilder.buildAShr(NVT, InH,
2252 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2253 } else if (Amt == NVTBits) {
2254 Lo = InH;
2255 Hi = MIRBuilder.buildAShr(NVT, InH,
2256 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2257 } else {
2258 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2259
2260 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2261 auto OrRHS = MIRBuilder.buildShl(
2262 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2263
2264 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2265 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2266 }
2267 }
2268
2269 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2270 MI.eraseFromParent();
2271
2272 return Legalized;
2273}
2274
2275// TODO: Optimize if constant shift amount.
2276LegalizerHelper::LegalizeResult
2277LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2278 LLT RequestedTy) {
2279 if (TypeIdx == 1) {
2280 Observer.changingInstr(MI);
2281 narrowScalarSrc(MI, RequestedTy, 2);
2282 Observer.changedInstr(MI);
2283 return Legalized;
2284 }
2285
2286 unsigned DstReg = MI.getOperand(0).getReg();
2287 LLT DstTy = MRI.getType(DstReg);
2288 if (DstTy.isVector())
2289 return UnableToLegalize;
2290
2291 unsigned Amt = MI.getOperand(2).getReg();
2292 LLT ShiftAmtTy = MRI.getType(Amt);
2293 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2294 if (DstEltSize % 2 != 0)
2295 return UnableToLegalize;
2296
2297 // Ignore the input type. We can only go to exactly half the size of the
2298 // input. If that isn't small enough, the resulting pieces will be further
2299 // legalized.
2300 const unsigned NewBitSize = DstEltSize / 2;
2301 const LLT HalfTy = LLT::scalar(NewBitSize);
2302 const LLT CondTy = LLT::scalar(1);
2303
2304 if (const MachineInstr *KShiftAmt =
2305 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2306 return narrowScalarShiftByConstant(
2307 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2308 }
2309
2310 // TODO: Expand with known bits.
2311
2312 // Handle the fully general expansion by an unknown amount.
2313 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2314
2315 unsigned InL = MRI.createGenericVirtualRegister(HalfTy);
2316 unsigned InH = MRI.createGenericVirtualRegister(HalfTy);
2317 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2318
2319 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2320 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2321
2322 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2323 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2324 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2325
2326 unsigned ResultRegs[2];
2327 switch (MI.getOpcode()) {
2328 case TargetOpcode::G_SHL: {
2329 // Short: ShAmt < NewBitSize
2330 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2331
2332 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2333 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2334 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2335
2336 // Long: ShAmt >= NewBitSize
2337 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2338 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2339
2340 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2341 auto Hi = MIRBuilder.buildSelect(
2342 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2343
2344 ResultRegs[0] = Lo.getReg(0);
2345 ResultRegs[1] = Hi.getReg(0);
2346 break;
2347 }
2348 case TargetOpcode::G_LSHR: {
2349 // Short: ShAmt < NewBitSize
2350 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2351
2352 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2353 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2354 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2355
2356 // Long: ShAmt >= NewBitSize
2357 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2358 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2359
2360 auto Lo = MIRBuilder.buildSelect(
2361 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2362 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2363
2364 ResultRegs[0] = Lo.getReg(0);
2365 ResultRegs[1] = Hi.getReg(0);
2366 break;
2367 }
2368 case TargetOpcode::G_ASHR: {
2369 // Short: ShAmt < NewBitSize
2370 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2371
2372 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2373 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2374 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2375
2376 // Long: ShAmt >= NewBitSize
2377
2378 // Sign of Hi part.
2379 auto HiL = MIRBuilder.buildAShr(
2380 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2381
2382 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2383
2384 auto Lo = MIRBuilder.buildSelect(
2385 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2386
2387 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2388
2389 ResultRegs[0] = Lo.getReg(0);
2390 ResultRegs[1] = Hi.getReg(0);
2391 break;
2392 }
2393 default:
2394 llvm_unreachable("not a shift");
2395 }
2396
2397 MIRBuilder.buildMerge(DstReg, ResultRegs);
2398 MI.eraseFromParent();
2399 return Legalized;
2400}
2401
2402LegalizerHelper::LegalizeResult
Matt Arsenault211e89d2019-01-27 00:52:51 +00002403LegalizerHelper::narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT NewTy) {
2404 unsigned DstReg = MI.getOperand(0).getReg();
2405 unsigned Src0 = MI.getOperand(1).getReg();
2406 unsigned Src1 = MI.getOperand(2).getReg();
2407 LLT Ty = MRI.getType(DstReg);
2408 if (Ty.isVector())
2409 return UnableToLegalize;
2410
2411 unsigned Size = Ty.getSizeInBits();
2412 unsigned NewSize = Size / 2;
2413 if (Size != 2 * NewSize)
2414 return UnableToLegalize;
2415
2416 LLT HalfTy = LLT::scalar(NewSize);
2417 // TODO: if HalfTy != NewTy, handle the breakdown all at once?
2418
2419 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
2420 unsigned Lo = MRI.createGenericVirtualRegister(HalfTy);
2421 unsigned Hi = MRI.createGenericVirtualRegister(HalfTy);
2422 unsigned ExtLo = MRI.createGenericVirtualRegister(Ty);
2423 unsigned ExtHi = MRI.createGenericVirtualRegister(Ty);
2424 unsigned ShiftedHi = MRI.createGenericVirtualRegister(Ty);
2425
2426 SmallVector<unsigned, 2> Src0Parts;
2427 SmallVector<unsigned, 2> Src1Parts;
2428
2429 extractParts(Src0, HalfTy, 2, Src0Parts);
2430 extractParts(Src1, HalfTy, 2, Src1Parts);
2431
2432 MIRBuilder.buildMul(Lo, Src0Parts[0], Src1Parts[0]);
2433
2434 // TODO: Use smulh or umulh depending on what the target has.
2435 MIRBuilder.buildUMulH(Hi, Src0Parts[1], Src1Parts[1]);
2436
2437 MIRBuilder.buildConstant(ShiftAmt, NewSize);
2438 MIRBuilder.buildAnyExt(ExtHi, Hi);
2439 MIRBuilder.buildShl(ShiftedHi, ExtHi, ShiftAmt);
2440
2441 MIRBuilder.buildZExt(ExtLo, Lo);
2442 MIRBuilder.buildOr(DstReg, ExtLo, ShiftedHi);
2443 MI.eraseFromParent();
2444 return Legalized;
2445}
2446
2447LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00002448LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
2449 LLT NarrowTy) {
2450 if (TypeIdx != 0)
2451 return UnableToLegalize;
2452
2453 unsigned CondReg = MI.getOperand(1).getReg();
2454 LLT CondTy = MRI.getType(CondReg);
2455 if (CondTy.isVector()) // TODO: Handle vselect
2456 return UnableToLegalize;
2457
2458 unsigned DstReg = MI.getOperand(0).getReg();
2459 LLT DstTy = MRI.getType(DstReg);
2460
2461 SmallVector<unsigned, 4> DstRegs, DstLeftoverRegs;
2462 SmallVector<unsigned, 4> Src1Regs, Src1LeftoverRegs;
2463 SmallVector<unsigned, 4> Src2Regs, Src2LeftoverRegs;
2464 LLT LeftoverTy;
2465 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
2466 Src1Regs, Src1LeftoverRegs))
2467 return UnableToLegalize;
2468
2469 LLT Unused;
2470 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
2471 Src2Regs, Src2LeftoverRegs))
2472 llvm_unreachable("inconsistent extractParts result");
2473
2474 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
2475 auto Select = MIRBuilder.buildSelect(NarrowTy,
2476 CondReg, Src1Regs[I], Src2Regs[I]);
2477 DstRegs.push_back(Select->getOperand(0).getReg());
2478 }
2479
2480 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
2481 auto Select = MIRBuilder.buildSelect(
2482 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
2483 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
2484 }
2485
2486 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
2487 LeftoverTy, DstLeftoverRegs);
2488
2489 MI.eraseFromParent();
2490 return Legalized;
2491}
2492
2493LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002494LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
2495 unsigned Opc = MI.getOpcode();
2496 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00002497 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002498 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00002499 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002500 };
2501 switch (Opc) {
2502 default:
2503 return UnableToLegalize;
2504 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
2505 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00002506 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002507 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00002508 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002509 return Legalized;
2510 }
2511 case TargetOpcode::G_CTLZ: {
2512 unsigned SrcReg = MI.getOperand(1).getReg();
2513 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002514 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00002515 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002516 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
2517 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002518 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
2519 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
2520 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
2521 SrcReg, MIBZero);
2522 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
2523 MIBCtlzZU);
2524 MI.eraseFromParent();
2525 return Legalized;
2526 }
2527 // for now, we do this:
2528 // NewLen = NextPowerOf2(Len);
2529 // x = x | (x >> 1);
2530 // x = x | (x >> 2);
2531 // ...
2532 // x = x | (x >>16);
2533 // x = x | (x >>32); // for 64-bit input
2534 // Upto NewLen/2
2535 // return Len - popcount(x);
2536 //
2537 // Ref: "Hacker's Delight" by Henry Warren
2538 unsigned Op = SrcReg;
2539 unsigned NewLen = PowerOf2Ceil(Len);
2540 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
2541 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
2542 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002543 TargetOpcode::G_OR, {Ty},
2544 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
2545 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002546 Op = MIBOp->getOperand(0).getReg();
2547 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002548 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
2549 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2550 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002551 MI.eraseFromParent();
2552 return Legalized;
2553 }
2554 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
2555 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00002556 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002557 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00002558 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002559 return Legalized;
2560 }
2561 case TargetOpcode::G_CTTZ: {
2562 unsigned SrcReg = MI.getOperand(1).getReg();
2563 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002564 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002565 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
2566 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002567 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
2568 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002569 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
2570 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
2571 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
2572 SrcReg, MIBZero);
2573 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
2574 MIBCttzZU);
2575 MI.eraseFromParent();
2576 return Legalized;
2577 }
2578 // for now, we use: { return popcount(~x & (x - 1)); }
2579 // unless the target has ctlz but not ctpop, in which case we use:
2580 // { return 32 - nlz(~x & (x-1)); }
2581 // Ref: "Hacker's Delight" by Henry Warren
2582 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
2583 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002584 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002585 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002586 TargetOpcode::G_AND, {Ty},
2587 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
2588 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002589 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
2590 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002591 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
2592 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002593 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2594 {MIBCstLen,
2595 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002596 MI.eraseFromParent();
2597 return Legalized;
2598 }
2599 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
2600 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
2601 return Legalized;
2602 }
2603 }
2604}