blob: 8491763d9910bcbbf891aca791267ecdf41a297c [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);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000102 case MoreElements:
103 LLVM_DEBUG(dbgs() << ".. Increase number of elements\n");
104 return moreElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000105 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000106 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000107 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
108 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000109 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000110 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +0000111 return UnableToLegalize;
112 }
113}
114
Tim Northover69fa84a2016-10-14 22:18:18 +0000115void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
116 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +0000117 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +0000118 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +0000119 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +0000120}
121
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000122bool LegalizerHelper::extractParts(unsigned Reg, LLT RegTy,
123 LLT MainTy, LLT &LeftoverTy,
124 SmallVectorImpl<unsigned> &VRegs,
125 SmallVectorImpl<unsigned> &LeftoverRegs) {
126 assert(!LeftoverTy.isValid() && "this is an out argument");
127
128 unsigned RegSize = RegTy.getSizeInBits();
129 unsigned MainSize = MainTy.getSizeInBits();
130 unsigned NumParts = RegSize / MainSize;
131 unsigned LeftoverSize = RegSize - NumParts * MainSize;
132
133 // Use an unmerge when possible.
134 if (LeftoverSize == 0) {
135 for (unsigned I = 0; I < NumParts; ++I)
136 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy));
137 MIRBuilder.buildUnmerge(VRegs, Reg);
138 return true;
139 }
140
141 if (MainTy.isVector()) {
142 unsigned EltSize = MainTy.getScalarSizeInBits();
143 if (LeftoverSize % EltSize != 0)
144 return false;
145 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
146 } else {
147 LeftoverTy = LLT::scalar(LeftoverSize);
148 }
149
150 // For irregular sizes, extract the individual parts.
151 for (unsigned I = 0; I != NumParts; ++I) {
152 unsigned NewReg = MRI.createGenericVirtualRegister(MainTy);
153 VRegs.push_back(NewReg);
154 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I);
155 }
156
157 for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
158 Offset += LeftoverSize) {
159 unsigned NewReg = MRI.createGenericVirtualRegister(LeftoverTy);
160 LeftoverRegs.push_back(NewReg);
161 MIRBuilder.buildExtract(NewReg, Reg, Offset);
162 }
163
164 return true;
165}
166
167void LegalizerHelper::insertParts(unsigned DstReg,
168 LLT ResultTy, LLT PartTy,
169 ArrayRef<unsigned> PartRegs,
170 LLT LeftoverTy,
171 ArrayRef<unsigned> LeftoverRegs) {
172 if (!LeftoverTy.isValid()) {
173 assert(LeftoverRegs.empty());
174
Matt Arsenault81511e52019-02-05 00:13:44 +0000175 if (!ResultTy.isVector()) {
176 MIRBuilder.buildMerge(DstReg, PartRegs);
177 return;
178 }
179
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000180 if (PartTy.isVector())
181 MIRBuilder.buildConcatVectors(DstReg, PartRegs);
182 else
183 MIRBuilder.buildBuildVector(DstReg, PartRegs);
184 return;
185 }
186
187 unsigned PartSize = PartTy.getSizeInBits();
188 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits();
189
190 unsigned CurResultReg = MRI.createGenericVirtualRegister(ResultTy);
191 MIRBuilder.buildUndef(CurResultReg);
192
193 unsigned Offset = 0;
194 for (unsigned PartReg : PartRegs) {
195 unsigned NewResultReg = MRI.createGenericVirtualRegister(ResultTy);
196 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset);
197 CurResultReg = NewResultReg;
198 Offset += PartSize;
199 }
200
201 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) {
202 // Use the original output register for the final insert to avoid a copy.
203 unsigned NewResultReg = (I + 1 == E) ?
204 DstReg : MRI.createGenericVirtualRegister(ResultTy);
205
206 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset);
207 CurResultReg = NewResultReg;
208 Offset += LeftoverPartSize;
209 }
210}
211
Tim Northovere0418412017-02-08 23:23:39 +0000212static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
213 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +0000214 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000215 assert((Size == 32 || Size == 64) && "Unsupported size");
216 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +0000217 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000218 assert((Size == 32 || Size == 64) && "Unsupported size");
219 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000220 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000221 assert((Size == 32 || Size == 64) && "Unsupported size");
222 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000223 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000224 assert((Size == 32 || Size == 64) && "Unsupported size");
225 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000226 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
227 assert(Size == 32 && "Unsupported size");
228 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000229 case TargetOpcode::G_FADD:
230 assert((Size == 32 || Size == 64) && "Unsupported size");
231 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000232 case TargetOpcode::G_FSUB:
233 assert((Size == 32 || Size == 64) && "Unsupported size");
234 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000235 case TargetOpcode::G_FMUL:
236 assert((Size == 32 || Size == 64) && "Unsupported size");
237 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000238 case TargetOpcode::G_FDIV:
239 assert((Size == 32 || Size == 64) && "Unsupported size");
240 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Jessica Paquette84bedac2019-01-30 23:46:15 +0000241 case TargetOpcode::G_FEXP:
242 assert((Size == 32 || Size == 64) && "Unsupported size");
243 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000244 case TargetOpcode::G_FREM:
245 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
246 case TargetOpcode::G_FPOW:
247 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000248 case TargetOpcode::G_FMA:
249 assert((Size == 32 || Size == 64) && "Unsupported size");
250 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Jessica Paquette7db82d72019-01-28 18:34:18 +0000251 case TargetOpcode::G_FSIN:
252 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
253 return Size == 128 ? RTLIB::SIN_F128
254 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32;
255 case TargetOpcode::G_FCOS:
256 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
257 return Size == 128 ? RTLIB::COS_F128
258 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32;
Jessica Paquettec49428a2019-01-28 19:53:14 +0000259 case TargetOpcode::G_FLOG10:
260 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
261 return Size == 128 ? RTLIB::LOG10_F128
262 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32;
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000263 case TargetOpcode::G_FLOG:
264 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
265 return Size == 128 ? RTLIB::LOG_F128
266 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32;
Jessica Paquette0154bd12019-01-30 21:16:04 +0000267 case TargetOpcode::G_FLOG2:
268 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
269 return Size == 128 ? RTLIB::LOG2_F128
270 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000271 }
272 llvm_unreachable("Unknown libcall function");
273}
274
Diana Picusfc1675e2017-07-05 12:57:24 +0000275LegalizerHelper::LegalizeResult
276llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
277 const CallLowering::ArgInfo &Result,
278 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000279 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
280 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000281 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000282
Diana Picuse97822e2017-04-24 07:22:31 +0000283 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000284 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
285 MachineOperand::CreateES(Name), Result, Args))
286 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000287
Diana Picuse97822e2017-04-24 07:22:31 +0000288 return LegalizerHelper::Legalized;
289}
290
Diana Picus65ed3642018-01-17 13:34:10 +0000291// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000292static LegalizerHelper::LegalizeResult
293simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
294 Type *OpType) {
295 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000296
297 SmallVector<CallLowering::ArgInfo, 3> Args;
298 for (unsigned i = 1; i < MI.getNumOperands(); i++)
299 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000300 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000301 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000302}
303
Diana Picus65ed3642018-01-17 13:34:10 +0000304static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
305 Type *FromType) {
306 auto ToMVT = MVT::getVT(ToType);
307 auto FromMVT = MVT::getVT(FromType);
308
309 switch (Opcode) {
310 case TargetOpcode::G_FPEXT:
311 return RTLIB::getFPEXT(FromMVT, ToMVT);
312 case TargetOpcode::G_FPTRUNC:
313 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000314 case TargetOpcode::G_FPTOSI:
315 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
316 case TargetOpcode::G_FPTOUI:
317 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000318 case TargetOpcode::G_SITOFP:
319 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
320 case TargetOpcode::G_UITOFP:
321 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000322 }
323 llvm_unreachable("Unsupported libcall function");
324}
325
326static LegalizerHelper::LegalizeResult
327conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
328 Type *FromType) {
329 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
330 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
331 {{MI.getOperand(1).getReg(), FromType}});
332}
333
Tim Northover69fa84a2016-10-14 22:18:18 +0000334LegalizerHelper::LegalizeResult
335LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000336 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
337 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000338 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000339
Diana Picusfc1675e2017-07-05 12:57:24 +0000340 MIRBuilder.setInstr(MI);
341
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000342 switch (MI.getOpcode()) {
343 default:
344 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000345 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000346 case TargetOpcode::G_UDIV:
347 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000348 case TargetOpcode::G_UREM:
349 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000350 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000351 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
352 if (Status != Legalized)
353 return Status;
354 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000355 }
Diana Picus1314a282017-04-11 10:52:34 +0000356 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000357 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000358 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000359 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000360 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000361 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000362 case TargetOpcode::G_FREM:
363 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000364 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000365 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000366 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000367 case TargetOpcode::G_FLOG2:
368 case TargetOpcode::G_FEXP: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000369 if (Size > 64) {
370 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
371 return UnableToLegalize;
372 }
Diana Picus02e11012017-06-15 10:53:31 +0000373 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000374 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
375 if (Status != Legalized)
376 return Status;
377 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000378 }
Diana Picus65ed3642018-01-17 13:34:10 +0000379 case TargetOpcode::G_FPEXT: {
380 // FIXME: Support other floating point types (half, fp128 etc)
381 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
382 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
383 if (ToSize != 64 || FromSize != 32)
384 return UnableToLegalize;
385 LegalizeResult Status = conversionLibcall(
386 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
387 if (Status != Legalized)
388 return Status;
389 break;
390 }
391 case TargetOpcode::G_FPTRUNC: {
392 // FIXME: Support other floating point types (half, fp128 etc)
393 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
394 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
395 if (ToSize != 32 || FromSize != 64)
396 return UnableToLegalize;
397 LegalizeResult Status = conversionLibcall(
398 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
399 if (Status != Legalized)
400 return Status;
401 break;
402 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000403 case TargetOpcode::G_FPTOSI:
404 case TargetOpcode::G_FPTOUI: {
405 // FIXME: Support other types
406 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
407 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
408 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
409 return UnableToLegalize;
410 LegalizeResult Status = conversionLibcall(
411 MI, MIRBuilder, Type::getInt32Ty(Ctx),
412 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
413 if (Status != Legalized)
414 return Status;
415 break;
416 }
Diana Picus517531e2018-01-30 09:15:17 +0000417 case TargetOpcode::G_SITOFP:
418 case TargetOpcode::G_UITOFP: {
419 // FIXME: Support other types
420 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
421 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
422 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
423 return UnableToLegalize;
424 LegalizeResult Status = conversionLibcall(
425 MI, MIRBuilder,
426 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
427 Type::getInt32Ty(Ctx));
428 if (Status != Legalized)
429 return Status;
430 break;
431 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000432 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000433
434 MI.eraseFromParent();
435 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000436}
437
Tim Northover69fa84a2016-10-14 22:18:18 +0000438LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
439 unsigned TypeIdx,
440 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000441 MIRBuilder.setInstr(MI);
442
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000443 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
444 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000445
Tim Northover9656f142016-08-04 20:54:13 +0000446 switch (MI.getOpcode()) {
447 default:
448 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000449 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000450 // FIXME: add support for when SizeOp0 isn't an exact multiple of
451 // NarrowSize.
452 if (SizeOp0 % NarrowSize != 0)
453 return UnableToLegalize;
454 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000455
456 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000457 for (int i = 0; i < NumParts; ++i)
458 DstRegs.push_back(
459 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000460
461 unsigned DstReg = MI.getOperand(0).getReg();
462 if(MRI.getType(DstReg).isVector())
463 MIRBuilder.buildBuildVector(DstReg, DstRegs);
464 else
465 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000466 MI.eraseFromParent();
467 return Legalized;
468 }
Tim Northover9656f142016-08-04 20:54:13 +0000469 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000470 // FIXME: add support for when SizeOp0 isn't an exact multiple of
471 // NarrowSize.
472 if (SizeOp0 % NarrowSize != 0)
473 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000474 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000475 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000476
Tim Northoverb18ea162016-09-20 15:20:36 +0000477 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000478 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
479 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
480
Tim Northover0f140c72016-09-09 11:46:34 +0000481 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
482 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000483
484 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000485 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
486 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000487
Tim Northover0f140c72016-09-09 11:46:34 +0000488 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000489 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000490
491 DstRegs.push_back(DstReg);
492 CarryIn = CarryOut;
493 }
Tim Northover0f140c72016-09-09 11:46:34 +0000494 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000495 if(MRI.getType(DstReg).isVector())
496 MIRBuilder.buildBuildVector(DstReg, DstRegs);
497 else
498 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000499 MI.eraseFromParent();
500 return Legalized;
501 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000502 case TargetOpcode::G_SUB: {
503 // FIXME: add support for when SizeOp0 isn't an exact multiple of
504 // NarrowSize.
505 if (SizeOp0 % NarrowSize != 0)
506 return UnableToLegalize;
507
508 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
509
510 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
511 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
512 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
513
514 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
515 unsigned BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
516 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
517 {Src1Regs[0], Src2Regs[0]});
518 DstRegs.push_back(DstReg);
519 unsigned BorrowIn = BorrowOut;
520 for (int i = 1; i < NumParts; ++i) {
521 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
522 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
523
524 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
525 {Src1Regs[i], Src2Regs[i], BorrowIn});
526
527 DstRegs.push_back(DstReg);
528 BorrowIn = BorrowOut;
529 }
530 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
531 MI.eraseFromParent();
532 return Legalized;
533 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000534 case TargetOpcode::G_MUL:
535 return narrowScalarMul(MI, TypeIdx, NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +0000536 case TargetOpcode::G_EXTRACT:
537 return narrowScalarExtract(MI, TypeIdx, NarrowTy);
538 case TargetOpcode::G_INSERT:
539 return narrowScalarInsert(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000540 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000541 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000542 unsigned DstReg = MI.getOperand(0).getReg();
543 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000544 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000545 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000546
547 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
548 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
549 auto &MMO = **MI.memoperands_begin();
550 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
551 MIRBuilder.buildAnyExt(DstReg, TmpReg);
552 MI.eraseFromParent();
553 return Legalized;
554 }
555
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000556 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000557 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000558 case TargetOpcode::G_ZEXTLOAD:
559 case TargetOpcode::G_SEXTLOAD: {
560 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
561 unsigned DstReg = MI.getOperand(0).getReg();
562 unsigned PtrReg = MI.getOperand(1).getReg();
563
564 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
565 auto &MMO = **MI.memoperands_begin();
566 if (MMO.getSize() * 8 == NarrowSize) {
567 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
568 } else {
569 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
570 : TargetOpcode::G_SEXTLOAD;
571 MIRBuilder.buildInstr(ExtLoad)
572 .addDef(TmpReg)
573 .addUse(PtrReg)
574 .addMemOperand(&MMO);
575 }
576
577 if (ZExt)
578 MIRBuilder.buildZExt(DstReg, TmpReg);
579 else
580 MIRBuilder.buildSExt(DstReg, TmpReg);
581
582 MI.eraseFromParent();
583 return Legalized;
584 }
Justin Bognerfde01042017-01-18 17:29:54 +0000585 case TargetOpcode::G_STORE: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000586 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000587
588 unsigned SrcReg = MI.getOperand(0).getReg();
589 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000590 if (SrcTy.isVector())
591 return UnableToLegalize;
592
593 int NumParts = SizeOp0 / NarrowSize;
594 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
595 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
596 if (SrcTy.isVector() && LeftoverBits != 0)
597 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000598
599 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
600 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
601 auto &MMO = **MI.memoperands_begin();
602 MIRBuilder.buildTrunc(TmpReg, SrcReg);
603 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
604 MI.eraseFromParent();
605 return Legalized;
606 }
607
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000608 return reduceLoadStoreWidth(MI, 0, NarrowTy);
Justin Bognerfde01042017-01-18 17:29:54 +0000609 }
Igor Breger29537882017-04-07 14:41:59 +0000610 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000611 // FIXME: add support for when SizeOp0 isn't an exact multiple of
612 // NarrowSize.
613 if (SizeOp0 % NarrowSize != 0)
614 return UnableToLegalize;
615 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000616 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000617 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000618
619 SmallVector<unsigned, 2> DstRegs;
620 for (int i = 0; i < NumParts; ++i) {
621 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
622 ConstantInt *CI =
623 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
624 MIRBuilder.buildConstant(DstReg, *CI);
625 DstRegs.push_back(DstReg);
626 }
627 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000628 if(MRI.getType(DstReg).isVector())
629 MIRBuilder.buildBuildVector(DstReg, DstRegs);
630 else
631 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000632 MI.eraseFromParent();
633 return Legalized;
634 }
Matt Arsenault81511e52019-02-05 00:13:44 +0000635 case TargetOpcode::G_SELECT:
636 return narrowScalarSelect(MI, TypeIdx, NarrowTy);
Petar Avramovic150fd432018-12-18 11:36:14 +0000637 case TargetOpcode::G_AND:
638 case TargetOpcode::G_OR:
639 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000640 // Legalize bitwise operation:
641 // A = BinOp<Ty> B, C
642 // into:
643 // B1, ..., BN = G_UNMERGE_VALUES B
644 // C1, ..., CN = G_UNMERGE_VALUES C
645 // A1 = BinOp<Ty/N> B1, C2
646 // ...
647 // AN = BinOp<Ty/N> BN, CN
648 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000649
650 // FIXME: add support for when SizeOp0 isn't an exact multiple of
651 // NarrowSize.
652 if (SizeOp0 % NarrowSize != 0)
653 return UnableToLegalize;
654 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000655
656 // List the registers where the destination will be scattered.
657 SmallVector<unsigned, 2> DstRegs;
658 // List the registers where the first argument will be split.
659 SmallVector<unsigned, 2> SrcsReg1;
660 // List the registers where the second argument will be split.
661 SmallVector<unsigned, 2> SrcsReg2;
662 // Create all the temporary registers.
663 for (int i = 0; i < NumParts; ++i) {
664 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
665 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
666 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
667
668 DstRegs.push_back(DstReg);
669 SrcsReg1.push_back(SrcReg1);
670 SrcsReg2.push_back(SrcReg2);
671 }
672 // Explode the big arguments into smaller chunks.
673 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
674 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
675
676 // Do the operation on each small part.
677 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000678 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
679 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000680
681 // Gather the destination registers into the final destination.
682 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000683 if(MRI.getType(DstReg).isVector())
684 MIRBuilder.buildBuildVector(DstReg, DstRegs);
685 else
686 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000687 MI.eraseFromParent();
688 return Legalized;
689 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000690 case TargetOpcode::G_SHL:
691 case TargetOpcode::G_LSHR:
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +0000692 case TargetOpcode::G_ASHR:
693 return narrowScalarShift(MI, TypeIdx, NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000694 case TargetOpcode::G_CTLZ:
695 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
696 case TargetOpcode::G_CTTZ:
697 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
698 case TargetOpcode::G_CTPOP:
699 if (TypeIdx != 0)
700 return UnableToLegalize; // TODO
701
702 Observer.changingInstr(MI);
703 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
704 Observer.changedInstr(MI);
705 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000706 case TargetOpcode::G_INTTOPTR:
707 if (TypeIdx != 1)
708 return UnableToLegalize;
709
710 Observer.changingInstr(MI);
711 narrowScalarSrc(MI, NarrowTy, 1);
712 Observer.changedInstr(MI);
713 return Legalized;
714 case TargetOpcode::G_PTRTOINT:
715 if (TypeIdx != 0)
716 return UnableToLegalize;
717
718 Observer.changingInstr(MI);
719 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
720 Observer.changedInstr(MI);
721 return Legalized;
Tim Northover9656f142016-08-04 20:54:13 +0000722 }
Tim Northover33b07d62016-07-22 20:03:43 +0000723}
724
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000725void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
726 unsigned OpIdx, unsigned ExtOpcode) {
727 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000728 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000729 MO.setReg(ExtB->getOperand(0).getReg());
730}
731
Matt Arsenault30989e42019-01-22 21:42:11 +0000732void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
733 unsigned OpIdx) {
734 MachineOperand &MO = MI.getOperand(OpIdx);
735 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
736 {MO.getReg()});
737 MO.setReg(ExtB->getOperand(0).getReg());
738}
739
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000740void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
741 unsigned OpIdx, unsigned TruncOpcode) {
742 MachineOperand &MO = MI.getOperand(OpIdx);
743 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
744 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000745 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000746 MO.setReg(DstExt);
747}
748
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000749void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
750 unsigned OpIdx, unsigned ExtOpcode) {
751 MachineOperand &MO = MI.getOperand(OpIdx);
752 unsigned DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
753 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
754 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
755 MO.setReg(DstTrunc);
756}
757
Matt Arsenault18ec3822019-02-11 22:00:39 +0000758void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy,
759 unsigned OpIdx) {
760 MachineOperand &MO = MI.getOperand(OpIdx);
761 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
762 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
763 MIRBuilder.buildExtract(MO.getReg(), DstExt, 0);
764 MO.setReg(DstExt);
765}
766
Matt Arsenault26b7e852019-02-19 16:30:19 +0000767void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy,
768 unsigned OpIdx) {
769 MachineOperand &MO = MI.getOperand(OpIdx);
770
771 LLT OldTy = MRI.getType(MO.getReg());
772 unsigned OldElts = OldTy.getNumElements();
773 unsigned NewElts = MoreTy.getNumElements();
774
775 unsigned NumParts = NewElts / OldElts;
776
777 // Use concat_vectors if the result is a multiple of the number of elements.
778 if (NumParts * OldElts == NewElts) {
779 SmallVector<unsigned, 8> Parts;
780 Parts.push_back(MO.getReg());
781
782 unsigned ImpDef = MIRBuilder.buildUndef(OldTy).getReg(0);
783 for (unsigned I = 1; I != NumParts; ++I)
784 Parts.push_back(ImpDef);
785
786 auto Concat = MIRBuilder.buildConcatVectors(MoreTy, Parts);
787 MO.setReg(Concat.getReg(0));
788 return;
789 }
790
791 unsigned MoreReg = MRI.createGenericVirtualRegister(MoreTy);
792 unsigned ImpDef = MIRBuilder.buildUndef(MoreTy).getReg(0);
793 MIRBuilder.buildInsert(MoreReg, ImpDef, MO.getReg(), 0);
794 MO.setReg(MoreReg);
795}
796
Tim Northover69fa84a2016-10-14 22:18:18 +0000797LegalizerHelper::LegalizeResult
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000798LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
799 LLT WideTy) {
800 if (TypeIdx != 1)
801 return UnableToLegalize;
802
803 unsigned DstReg = MI.getOperand(0).getReg();
804 LLT DstTy = MRI.getType(DstReg);
805 if (!DstTy.isScalar())
806 return UnableToLegalize;
807
808 unsigned NumOps = MI.getNumOperands();
809 unsigned NumSrc = MI.getNumOperands() - 1;
810 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
811
812 unsigned Src1 = MI.getOperand(1).getReg();
813 unsigned ResultReg = MIRBuilder.buildZExt(DstTy, Src1)->getOperand(0).getReg();
814
815 for (unsigned I = 2; I != NumOps; ++I) {
816 const unsigned Offset = (I - 1) * PartSize;
817
818 unsigned SrcReg = MI.getOperand(I).getReg();
819 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
820
821 auto ZextInput = MIRBuilder.buildZExt(DstTy, SrcReg);
822
823 unsigned NextResult = I + 1 == NumOps ? DstReg :
824 MRI.createGenericVirtualRegister(DstTy);
825
826 auto ShiftAmt = MIRBuilder.buildConstant(DstTy, Offset);
827 auto Shl = MIRBuilder.buildShl(DstTy, ZextInput, ShiftAmt);
828 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
829 ResultReg = NextResult;
830 }
831
832 MI.eraseFromParent();
833 return Legalized;
834}
835
836LegalizerHelper::LegalizeResult
837LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
838 LLT WideTy) {
839 if (TypeIdx != 0)
840 return UnableToLegalize;
841
842 unsigned NumDst = MI.getNumOperands() - 1;
843 unsigned SrcReg = MI.getOperand(NumDst).getReg();
844 LLT SrcTy = MRI.getType(SrcReg);
845 if (!SrcTy.isScalar())
846 return UnableToLegalize;
847
848 unsigned Dst0Reg = MI.getOperand(0).getReg();
849 LLT DstTy = MRI.getType(Dst0Reg);
850 if (!DstTy.isScalar())
851 return UnableToLegalize;
852
853 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
854 LLT NewSrcTy = LLT::scalar(NewSrcSize);
855 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
856
857 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
858
859 for (unsigned I = 1; I != NumDst; ++I) {
860 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
861 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
862 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
863 }
864
865 Observer.changingInstr(MI);
866
867 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
868 for (unsigned I = 0; I != NumDst; ++I)
869 widenScalarDst(MI, WideTy, I);
870
871 Observer.changedInstr(MI);
872
873 return Legalized;
874}
875
876LegalizerHelper::LegalizeResult
Matt Arsenault1cf71362019-02-12 14:54:52 +0000877LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
878 LLT WideTy) {
Matt Arsenaultfbe92a52019-02-18 22:39:27 +0000879 unsigned DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +0000880 unsigned SrcReg = MI.getOperand(1).getReg();
881 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenaultfbe92a52019-02-18 22:39:27 +0000882
883 LLT DstTy = MRI.getType(DstReg);
884 unsigned Offset = MI.getOperand(2).getImm();
885
886 if (TypeIdx == 0) {
887 if (SrcTy.isVector() || DstTy.isVector())
888 return UnableToLegalize;
889
890 SrcOp Src(SrcReg);
891 if (SrcTy.isPointer()) {
892 // Extracts from pointers can be handled only if they are really just
893 // simple integers.
894 const DataLayout &DL = MIRBuilder.getDataLayout();
895 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
896 return UnableToLegalize;
897
898 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
899 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
900 SrcTy = SrcAsIntTy;
901 }
902
903 if (DstTy.isPointer())
904 return UnableToLegalize;
905
906 if (Offset == 0) {
907 // Avoid a shift in the degenerate case.
908 MIRBuilder.buildTrunc(DstReg,
909 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
910 MI.eraseFromParent();
911 return Legalized;
912 }
913
914 // Do a shift in the source type.
915 LLT ShiftTy = SrcTy;
916 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
917 Src = MIRBuilder.buildAnyExt(WideTy, Src);
918 ShiftTy = WideTy;
919 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits())
920 return UnableToLegalize;
921
922 auto LShr = MIRBuilder.buildLShr(
923 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
924 MIRBuilder.buildTrunc(DstReg, LShr);
925 MI.eraseFromParent();
926 return Legalized;
927 }
928
Matt Arsenault1cf71362019-02-12 14:54:52 +0000929 if (!SrcTy.isVector())
930 return UnableToLegalize;
931
Matt Arsenault1cf71362019-02-12 14:54:52 +0000932 if (DstTy != SrcTy.getElementType())
933 return UnableToLegalize;
934
Matt Arsenault1cf71362019-02-12 14:54:52 +0000935 if (Offset % SrcTy.getScalarSizeInBits() != 0)
936 return UnableToLegalize;
937
938 Observer.changingInstr(MI);
939 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
940
941 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
942 Offset);
943 widenScalarDst(MI, WideTy.getScalarType(), 0);
944 Observer.changedInstr(MI);
945 return Legalized;
946}
947
948LegalizerHelper::LegalizeResult
949LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
950 LLT WideTy) {
951 if (TypeIdx != 0)
952 return UnableToLegalize;
953 Observer.changingInstr(MI);
954 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
955 widenScalarDst(MI, WideTy);
956 Observer.changedInstr(MI);
957 return Legalized;
958}
959
960LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +0000961LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000962 MIRBuilder.setInstr(MI);
963
Tim Northover32335812016-08-04 18:35:11 +0000964 switch (MI.getOpcode()) {
965 default:
966 return UnableToLegalize;
Matt Arsenault1cf71362019-02-12 14:54:52 +0000967 case TargetOpcode::G_EXTRACT:
968 return widenScalarExtract(MI, TypeIdx, WideTy);
969 case TargetOpcode::G_INSERT:
970 return widenScalarInsert(MI, TypeIdx, WideTy);
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000971 case TargetOpcode::G_MERGE_VALUES:
972 return widenScalarMergeValues(MI, TypeIdx, WideTy);
973 case TargetOpcode::G_UNMERGE_VALUES:
974 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000975 case TargetOpcode::G_UADDO:
976 case TargetOpcode::G_USUBO: {
977 if (TypeIdx == 1)
978 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000979 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
980 {MI.getOperand(2).getReg()});
981 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
982 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000983 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
984 ? TargetOpcode::G_ADD
985 : TargetOpcode::G_SUB;
986 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000987 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000988 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
989 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
990 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000991 TargetOpcode::G_AND, {WideTy},
992 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000993 // There is no overflow if the AndOp is the same as NewOp.
994 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
995 AndOp);
996 // Now trunc the NewOp to the original result.
997 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
998 MI.eraseFromParent();
999 return Legalized;
1000 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001001 case TargetOpcode::G_CTTZ:
1002 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1003 case TargetOpcode::G_CTLZ:
1004 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1005 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001006 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001007 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001008 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001009 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001010 return Legalized;
1011 }
1012
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001013 unsigned SrcReg = MI.getOperand(1).getReg();
1014
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001015 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001016 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1017 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001018 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1019 // The count is the same in the larger type except if the original
1020 // value was zero. This can be handled by setting the bit just off
1021 // the top of the original type.
1022 auto TopBit =
1023 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001024 MIBSrc = MIRBuilder.buildOr(
1025 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001026 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001027
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001028 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001029 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001030 // This is already the correct result for CTPOP and CTTZs
1031 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1032 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1033 // The correct result is NewOp - (Difference in widety and current ty).
1034 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001035 MIBNewOp = MIRBuilder.buildInstr(
1036 TargetOpcode::G_SUB, {WideTy},
1037 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001038 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001039
1040 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1041 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001042 return Legalized;
1043 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001044 case TargetOpcode::G_BSWAP: {
1045 Observer.changingInstr(MI);
1046 unsigned DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001047
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001048 unsigned ShrReg = MRI.createGenericVirtualRegister(WideTy);
1049 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
1050 unsigned ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
1051 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1052
1053 MI.getOperand(0).setReg(DstExt);
1054
1055 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1056
1057 LLT Ty = MRI.getType(DstReg);
1058 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1059 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1060 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1061 .addDef(ShrReg)
1062 .addUse(DstExt)
1063 .addUse(ShiftAmtReg);
1064
1065 MIRBuilder.buildTrunc(DstReg, ShrReg);
1066 Observer.changedInstr(MI);
1067 return Legalized;
1068 }
Tim Northover61c16142016-08-04 21:39:49 +00001069 case TargetOpcode::G_ADD:
1070 case TargetOpcode::G_AND:
1071 case TargetOpcode::G_MUL:
1072 case TargetOpcode::G_OR:
1073 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001074 case TargetOpcode::G_SUB:
Matt Arsenault1cf71362019-02-12 14:54:52 +00001075 // Perform operation at larger width (any extension is fines here, high bits
Tim Northover32335812016-08-04 18:35:11 +00001076 // don't affect the result) and then truncate the result back to the
1077 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001078 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001079 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1080 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1081 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001082 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001083 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001084
Roman Tereshin6d266382018-05-09 21:43:30 +00001085 case TargetOpcode::G_SHL:
Matt Arsenault30989e42019-01-22 21:42:11 +00001086 Observer.changingInstr(MI);
1087
1088 if (TypeIdx == 0) {
1089 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1090 widenScalarDst(MI, WideTy);
1091 } else {
1092 assert(TypeIdx == 1);
1093 // The "number of bits to shift" operand must preserve its value as an
1094 // unsigned integer:
1095 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1096 }
1097
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001098 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001099 return Legalized;
1100
Tim Northover7a753d92016-08-26 17:46:06 +00001101 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001102 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001103 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001104 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1105 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1106 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001107 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001108 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001109
Roman Tereshin6d266382018-05-09 21:43:30 +00001110 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001111 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001112 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001113
1114 if (TypeIdx == 0) {
1115 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1116 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1117
1118 widenScalarSrc(MI, WideTy, 1, CvtOp);
1119 widenScalarDst(MI, WideTy);
1120 } else {
1121 assert(TypeIdx == 1);
1122 // The "number of bits to shift" operand must preserve its value as an
1123 // unsigned integer:
1124 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1125 }
1126
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001127 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001128 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001129 case TargetOpcode::G_UDIV:
1130 case TargetOpcode::G_UREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001131 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001132 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1133 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1134 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001135 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001136 return Legalized;
1137
1138 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001139 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001140 if (TypeIdx == 0) {
1141 // Perform operation at larger width (any extension is fine here, high
1142 // bits don't affect the result) and then truncate the result back to the
1143 // original type.
1144 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1145 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1146 widenScalarDst(MI, WideTy);
1147 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001148 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001149 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001150 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001151 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001152 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001153 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001154
Ahmed Bougachab6137062017-01-23 21:10:14 +00001155 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001156 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001157 if (TypeIdx != 0)
1158 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001159 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001160 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001161 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001162 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001163
Ahmed Bougachad2948232017-01-20 01:37:24 +00001164 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001165 if (TypeIdx != 1)
1166 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001167 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001168 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001169 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001170 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001171
1172 case TargetOpcode::G_UITOFP:
1173 if (TypeIdx != 1)
1174 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001175 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001176 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001177 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001178 return Legalized;
1179
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001180 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001181 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001182 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001183 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001184 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001185 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001186 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001187
Tim Northover3c73e362016-08-23 18:20:09 +00001188 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001189 if (TypeIdx != 0)
1190 return UnableToLegalize;
1191
1192 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1193 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001194 return UnableToLegalize;
1195
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001196 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001197
1198 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1199 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1200 widenScalarSrc(MI, WideTy, 0, ExtType);
1201
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001202 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001203 return Legalized;
1204 }
Tim Northoverea904f92016-08-19 22:40:00 +00001205 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001206 MachineOperand &SrcMO = MI.getOperand(1);
1207 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1208 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001209 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001210 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1211
1212 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001213 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001214 return Legalized;
1215 }
Tim Northovera11be042016-08-19 22:40:08 +00001216 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001217 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001218 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001219 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001220 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001221 switch (WideTy.getSizeInBits()) {
1222 case 32:
Matt Arsenault996c6662019-02-12 14:54:54 +00001223 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
1224 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001225 break;
1226 case 64:
Matt Arsenault996c6662019-02-12 14:54:54 +00001227 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
1228 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001229 break;
1230 default:
Matt Arsenault996c6662019-02-12 14:54:54 +00001231 return UnableToLegalize;
Tim Northover6cd4b232016-08-23 21:01:26 +00001232 }
Matt Arsenault996c6662019-02-12 14:54:54 +00001233
1234 assert(!LosesInfo && "extend should always be lossless");
1235
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001236 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001237 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1238
1239 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001240 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001241 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001242 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001243 case TargetOpcode::G_IMPLICIT_DEF: {
1244 Observer.changingInstr(MI);
1245 widenScalarDst(MI, WideTy);
1246 Observer.changedInstr(MI);
1247 return Legalized;
1248 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001249 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001250 Observer.changingInstr(MI);
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +00001251 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001252 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001253 return Legalized;
1254
1255 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001256 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001257 if (TypeIdx == 0)
1258 widenScalarDst(MI, WideTy);
1259 else {
1260 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1261 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001262 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001263 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001264 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001265
1266 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001267 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001268 if (TypeIdx == 0)
1269 widenScalarDst(MI, WideTy);
1270 else {
1271 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1272 MI.getOperand(1).getPredicate()))
1273 ? TargetOpcode::G_SEXT
1274 : TargetOpcode::G_ZEXT;
1275 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1276 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1277 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001278 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001279 return Legalized;
1280
1281 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001282 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001283 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001284 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001285 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001286 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001287
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001288 case TargetOpcode::G_PHI: {
1289 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001290
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001291 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001292 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1293 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1294 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1295 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001296 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001297
1298 MachineBasicBlock &MBB = *MI.getParent();
1299 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1300 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001301 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001302 return Legalized;
1303 }
Matt Arsenault63786292019-01-22 20:38:15 +00001304 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1305 if (TypeIdx == 0) {
1306 unsigned VecReg = MI.getOperand(1).getReg();
1307 LLT VecTy = MRI.getType(VecReg);
1308 Observer.changingInstr(MI);
1309
1310 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1311 WideTy.getSizeInBits()),
1312 1, TargetOpcode::G_SEXT);
1313
1314 widenScalarDst(MI, WideTy, 0);
1315 Observer.changedInstr(MI);
1316 return Legalized;
1317 }
1318
Amara Emersoncbd86d82018-10-25 14:04:54 +00001319 if (TypeIdx != 2)
1320 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001321 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001322 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001323 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001324 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001325 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001326 case TargetOpcode::G_FADD:
1327 case TargetOpcode::G_FMUL:
1328 case TargetOpcode::G_FSUB:
1329 case TargetOpcode::G_FMA:
1330 case TargetOpcode::G_FNEG:
1331 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001332 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001333 case TargetOpcode::G_FDIV:
1334 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001335 case TargetOpcode::G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00001336 case TargetOpcode::G_FFLOOR:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001337 case TargetOpcode::G_FCOS:
1338 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001339 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001340 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001341 case TargetOpcode::G_FLOG2:
Jessica Paquette22457f82019-01-30 21:03:52 +00001342 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001343 case TargetOpcode::G_FEXP:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001344 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001345 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001346
1347 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1348 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1349
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001350 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1351 Observer.changedInstr(MI);
1352 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001353 case TargetOpcode::G_INTTOPTR:
1354 if (TypeIdx != 1)
1355 return UnableToLegalize;
1356
1357 Observer.changingInstr(MI);
1358 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1359 Observer.changedInstr(MI);
1360 return Legalized;
1361 case TargetOpcode::G_PTRTOINT:
1362 if (TypeIdx != 0)
1363 return UnableToLegalize;
1364
1365 Observer.changingInstr(MI);
1366 widenScalarDst(MI, WideTy, 0);
1367 Observer.changedInstr(MI);
1368 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001369 }
Tim Northover33b07d62016-07-22 20:03:43 +00001370}
1371
Tim Northover69fa84a2016-10-14 22:18:18 +00001372LegalizerHelper::LegalizeResult
1373LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001374 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001375 MIRBuilder.setInstr(MI);
1376
1377 switch(MI.getOpcode()) {
1378 default:
1379 return UnableToLegalize;
1380 case TargetOpcode::G_SREM:
1381 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001382 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1383 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001384 .addDef(QuotReg)
1385 .addUse(MI.getOperand(1).getReg())
1386 .addUse(MI.getOperand(2).getReg());
1387
Tim Northover0f140c72016-09-09 11:46:34 +00001388 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1389 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1390 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1391 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001392 MI.eraseFromParent();
1393 return Legalized;
1394 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001395 case TargetOpcode::G_SMULO:
1396 case TargetOpcode::G_UMULO: {
1397 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1398 // result.
1399 unsigned Res = MI.getOperand(0).getReg();
1400 unsigned Overflow = MI.getOperand(1).getReg();
1401 unsigned LHS = MI.getOperand(2).getReg();
1402 unsigned RHS = MI.getOperand(3).getReg();
1403
1404 MIRBuilder.buildMul(Res, LHS, RHS);
1405
1406 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1407 ? TargetOpcode::G_SMULH
1408 : TargetOpcode::G_UMULH;
1409
1410 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1411 MIRBuilder.buildInstr(Opcode)
1412 .addDef(HiPart)
1413 .addUse(LHS)
1414 .addUse(RHS);
1415
1416 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1417 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001418
1419 // For *signed* multiply, overflow is detected by checking:
1420 // (hi != (lo >> bitwidth-1))
1421 if (Opcode == TargetOpcode::G_SMULH) {
1422 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1423 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1424 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1425 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1426 .addDef(Shifted)
1427 .addUse(Res)
1428 .addUse(ShiftAmt);
1429 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1430 } else {
1431 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1432 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001433 MI.eraseFromParent();
1434 return Legalized;
1435 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001436 case TargetOpcode::G_FNEG: {
1437 // TODO: Handle vector types once we are able to
1438 // represent them.
1439 if (Ty.isVector())
1440 return UnableToLegalize;
1441 unsigned Res = MI.getOperand(0).getReg();
1442 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001443 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001444 switch (Ty.getSizeInBits()) {
1445 case 16:
1446 ZeroTy = Type::getHalfTy(Ctx);
1447 break;
1448 case 32:
1449 ZeroTy = Type::getFloatTy(Ctx);
1450 break;
1451 case 64:
1452 ZeroTy = Type::getDoubleTy(Ctx);
1453 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001454 case 128:
1455 ZeroTy = Type::getFP128Ty(Ctx);
1456 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001457 default:
1458 llvm_unreachable("unexpected floating-point type");
1459 }
1460 ConstantFP &ZeroForNegation =
1461 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001462 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001463 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1464 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001465 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001466 .addUse(MI.getOperand(1).getReg());
1467 MI.eraseFromParent();
1468 return Legalized;
1469 }
Volkan Keles225921a2017-03-10 21:25:09 +00001470 case TargetOpcode::G_FSUB: {
1471 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1472 // First, check if G_FNEG is marked as Lower. If so, we may
1473 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001474 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001475 return UnableToLegalize;
1476 unsigned Res = MI.getOperand(0).getReg();
1477 unsigned LHS = MI.getOperand(1).getReg();
1478 unsigned RHS = MI.getOperand(2).getReg();
1479 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1480 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1481 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1482 .addDef(Res)
1483 .addUse(LHS)
1484 .addUse(Neg);
1485 MI.eraseFromParent();
1486 return Legalized;
1487 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001488 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1489 unsigned OldValRes = MI.getOperand(0).getReg();
1490 unsigned SuccessRes = MI.getOperand(1).getReg();
1491 unsigned Addr = MI.getOperand(2).getReg();
1492 unsigned CmpVal = MI.getOperand(3).getReg();
1493 unsigned NewVal = MI.getOperand(4).getReg();
1494 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1495 **MI.memoperands_begin());
1496 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1497 MI.eraseFromParent();
1498 return Legalized;
1499 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001500 case TargetOpcode::G_LOAD:
1501 case TargetOpcode::G_SEXTLOAD:
1502 case TargetOpcode::G_ZEXTLOAD: {
1503 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1504 unsigned DstReg = MI.getOperand(0).getReg();
1505 unsigned PtrReg = MI.getOperand(1).getReg();
1506 LLT DstTy = MRI.getType(DstReg);
1507 auto &MMO = **MI.memoperands_begin();
1508
1509 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001510 // In the case of G_LOAD, this was a non-extending load already and we're
1511 // about to lower to the same instruction.
1512 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1513 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001514 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1515 MI.eraseFromParent();
1516 return Legalized;
1517 }
1518
1519 if (DstTy.isScalar()) {
1520 unsigned TmpReg = MRI.createGenericVirtualRegister(
1521 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1522 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1523 switch (MI.getOpcode()) {
1524 default:
1525 llvm_unreachable("Unexpected opcode");
1526 case TargetOpcode::G_LOAD:
1527 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1528 break;
1529 case TargetOpcode::G_SEXTLOAD:
1530 MIRBuilder.buildSExt(DstReg, TmpReg);
1531 break;
1532 case TargetOpcode::G_ZEXTLOAD:
1533 MIRBuilder.buildZExt(DstReg, TmpReg);
1534 break;
1535 }
1536 MI.eraseFromParent();
1537 return Legalized;
1538 }
1539
1540 return UnableToLegalize;
1541 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001542 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1543 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1544 case TargetOpcode::G_CTLZ:
1545 case TargetOpcode::G_CTTZ:
1546 case TargetOpcode::G_CTPOP:
1547 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicbd395692019-02-26 17:22:42 +00001548 case G_UADDO: {
1549 unsigned Res = MI.getOperand(0).getReg();
1550 unsigned CarryOut = MI.getOperand(1).getReg();
1551 unsigned LHS = MI.getOperand(2).getReg();
1552 unsigned RHS = MI.getOperand(3).getReg();
1553
1554 MIRBuilder.buildAdd(Res, LHS, RHS);
1555 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS);
1556
1557 MI.eraseFromParent();
1558 return Legalized;
1559 }
Petar Avramovicb8276f22018-12-17 12:31:07 +00001560 case G_UADDE: {
1561 unsigned Res = MI.getOperand(0).getReg();
1562 unsigned CarryOut = MI.getOperand(1).getReg();
1563 unsigned LHS = MI.getOperand(2).getReg();
1564 unsigned RHS = MI.getOperand(3).getReg();
1565 unsigned CarryIn = MI.getOperand(4).getReg();
1566
1567 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1568 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1569
1570 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1571 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1572 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1573 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1574
1575 MI.eraseFromParent();
1576 return Legalized;
1577 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001578 case G_USUBO: {
1579 unsigned Res = MI.getOperand(0).getReg();
1580 unsigned BorrowOut = MI.getOperand(1).getReg();
1581 unsigned LHS = MI.getOperand(2).getReg();
1582 unsigned RHS = MI.getOperand(3).getReg();
1583
1584 MIRBuilder.buildSub(Res, LHS, RHS);
1585 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1586
1587 MI.eraseFromParent();
1588 return Legalized;
1589 }
1590 case G_USUBE: {
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 unsigned BorrowIn = MI.getOperand(4).getReg();
1596
1597 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1598 unsigned ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1599 unsigned LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1600 unsigned LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1601
1602 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1603 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1604 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1605 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1606 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1607 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1608
1609 MI.eraseFromParent();
1610 return Legalized;
1611 }
Tim Northovercecee562016-08-26 17:46:13 +00001612 }
1613}
1614
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001615LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1616 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
1617 SmallVector<unsigned, 2> DstRegs;
1618
1619 unsigned NarrowSize = NarrowTy.getSizeInBits();
1620 unsigned DstReg = MI.getOperand(0).getReg();
1621 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1622 int NumParts = Size / NarrowSize;
1623 // FIXME: Don't know how to handle the situation where the small vectors
1624 // aren't all the same size yet.
1625 if (Size % NarrowSize != 0)
1626 return UnableToLegalize;
1627
1628 for (int i = 0; i < NumParts; ++i) {
1629 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1630 MIRBuilder.buildUndef(TmpReg);
1631 DstRegs.push_back(TmpReg);
1632 }
1633
1634 if (NarrowTy.isVector())
1635 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1636 else
1637 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1638
1639 MI.eraseFromParent();
1640 return Legalized;
1641}
1642
1643LegalizerHelper::LegalizeResult
1644LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
1645 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001646 const unsigned Opc = MI.getOpcode();
1647 const unsigned NumOps = MI.getNumOperands() - 1;
1648 const unsigned NarrowSize = NarrowTy.getSizeInBits();
1649 const unsigned DstReg = MI.getOperand(0).getReg();
1650 const unsigned Flags = MI.getFlags();
1651 const LLT DstTy = MRI.getType(DstReg);
1652 const unsigned Size = DstTy.getSizeInBits();
1653 const int NumParts = Size / NarrowSize;
1654 const LLT EltTy = DstTy.getElementType();
1655 const unsigned EltSize = EltTy.getSizeInBits();
1656 const unsigned BitsForNumParts = NarrowSize * NumParts;
1657
1658 // Check if we have any leftovers. If we do, then only handle the case where
1659 // the leftover is one element.
1660 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001661 return UnableToLegalize;
1662
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001663 if (BitsForNumParts != Size) {
1664 unsigned AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
1665 MIRBuilder.buildUndef(AccumDstReg);
1666
1667 // Handle the pieces which evenly divide into the requested type with
1668 // extract/op/insert sequence.
1669 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
1670 SmallVector<SrcOp, 4> SrcOps;
1671 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1672 unsigned PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
1673 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
1674 SrcOps.push_back(PartOpReg);
1675 }
1676
1677 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
1678 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1679
1680 unsigned PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
1681 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
1682 AccumDstReg = PartInsertReg;
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001683 }
1684
1685 // Handle the remaining element sized leftover piece.
1686 SmallVector<SrcOp, 4> SrcOps;
1687 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1688 unsigned PartOpReg = MRI.createGenericVirtualRegister(EltTy);
1689 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
1690 BitsForNumParts);
1691 SrcOps.push_back(PartOpReg);
1692 }
1693
1694 unsigned PartDstReg = MRI.createGenericVirtualRegister(EltTy);
1695 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1696 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
1697 MI.eraseFromParent();
1698
1699 return Legalized;
1700 }
1701
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001702 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1703
1704 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1705
1706 if (NumOps >= 2)
1707 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1708
1709 if (NumOps >= 3)
1710 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
1711
1712 for (int i = 0; i < NumParts; ++i) {
1713 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1714
1715 if (NumOps == 1)
1716 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1717 else if (NumOps == 2) {
1718 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1719 } else if (NumOps == 3) {
1720 MIRBuilder.buildInstr(Opc, {DstReg},
1721 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1722 }
1723
1724 DstRegs.push_back(DstReg);
1725 }
1726
1727 if (NarrowTy.isVector())
1728 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1729 else
1730 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1731
1732 MI.eraseFromParent();
1733 return Legalized;
1734}
1735
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001736// Handle splitting vector operations which need to have the same number of
1737// elements in each type index, but each type index may have a different element
1738// type.
1739//
1740// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
1741// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1742// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1743//
1744// Also handles some irregular breakdown cases, e.g.
1745// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
1746// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1747// s64 = G_SHL s64, s32
1748LegalizerHelper::LegalizeResult
1749LegalizerHelper::fewerElementsVectorMultiEltType(
1750 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
1751 if (TypeIdx != 0)
1752 return UnableToLegalize;
1753
1754 const LLT NarrowTy0 = NarrowTyArg;
1755 const unsigned NewNumElts =
1756 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
1757
1758 const unsigned DstReg = MI.getOperand(0).getReg();
1759 LLT DstTy = MRI.getType(DstReg);
1760 LLT LeftoverTy0;
1761
1762 // All of the operands need to have the same number of elements, so if we can
1763 // determine a type breakdown for the result type, we can for all of the
1764 // source types.
1765 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0);
1766 if (NumParts < 0)
1767 return UnableToLegalize;
1768
1769 SmallVector<MachineInstrBuilder, 4> NewInsts;
1770
1771 SmallVector<unsigned, 4> DstRegs, LeftoverDstRegs;
1772 SmallVector<unsigned, 4> PartRegs, LeftoverRegs;
1773
1774 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1775 LLT LeftoverTy;
1776 unsigned SrcReg = MI.getOperand(I).getReg();
1777 LLT SrcTyI = MRI.getType(SrcReg);
1778 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
1779 LLT LeftoverTyI;
1780
1781 // Split this operand into the requested typed registers, and any leftover
1782 // required to reproduce the original type.
1783 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
1784 LeftoverRegs))
1785 return UnableToLegalize;
1786
1787 if (I == 1) {
1788 // For the first operand, create an instruction for each part and setup
1789 // the result.
1790 for (unsigned PartReg : PartRegs) {
1791 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1792 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
1793 .addDef(PartDstReg)
1794 .addUse(PartReg));
1795 DstRegs.push_back(PartDstReg);
1796 }
1797
1798 for (unsigned LeftoverReg : LeftoverRegs) {
1799 unsigned PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
1800 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
1801 .addDef(PartDstReg)
1802 .addUse(LeftoverReg));
1803 LeftoverDstRegs.push_back(PartDstReg);
1804 }
1805 } else {
1806 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
1807
1808 // Add the newly created operand splits to the existing instructions. The
1809 // odd-sized pieces are ordered after the requested NarrowTyArg sized
1810 // pieces.
1811 unsigned InstCount = 0;
1812 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
1813 NewInsts[InstCount++].addUse(PartRegs[J]);
1814 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
1815 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
1816 }
1817
1818 PartRegs.clear();
1819 LeftoverRegs.clear();
1820 }
1821
1822 // Insert the newly built operations and rebuild the result register.
1823 for (auto &MIB : NewInsts)
1824 MIRBuilder.insertInstr(MIB);
1825
1826 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
1827
1828 MI.eraseFromParent();
1829 return Legalized;
1830}
1831
Tim Northover69fa84a2016-10-14 22:18:18 +00001832LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001833LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1834 LLT NarrowTy) {
1835 if (TypeIdx != 0)
1836 return UnableToLegalize;
1837
1838 unsigned DstReg = MI.getOperand(0).getReg();
1839 unsigned SrcReg = MI.getOperand(1).getReg();
1840 LLT DstTy = MRI.getType(DstReg);
1841 LLT SrcTy = MRI.getType(SrcReg);
1842
1843 LLT NarrowTy0 = NarrowTy;
1844 LLT NarrowTy1;
1845 unsigned NumParts;
1846
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001847 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00001848 // Uneven breakdown not handled.
1849 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1850 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1851 return UnableToLegalize;
1852
1853 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001854 } else {
1855 NumParts = DstTy.getNumElements();
1856 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00001857 }
1858
1859 SmallVector<unsigned, 4> SrcRegs, DstRegs;
1860 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1861
1862 for (unsigned I = 0; I < NumParts; ++I) {
1863 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1864 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1865 .addDef(DstReg)
1866 .addUse(SrcRegs[I]);
1867
1868 NewInst->setFlags(MI.getFlags());
1869 DstRegs.push_back(DstReg);
1870 }
1871
1872 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001873 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001874 else
1875 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1876
1877 MI.eraseFromParent();
1878 return Legalized;
1879}
1880
1881LegalizerHelper::LegalizeResult
1882LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1883 LLT NarrowTy) {
1884 unsigned DstReg = MI.getOperand(0).getReg();
1885 unsigned Src0Reg = MI.getOperand(2).getReg();
1886 LLT DstTy = MRI.getType(DstReg);
1887 LLT SrcTy = MRI.getType(Src0Reg);
1888
1889 unsigned NumParts;
1890 LLT NarrowTy0, NarrowTy1;
1891
1892 if (TypeIdx == 0) {
1893 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1894 unsigned OldElts = DstTy.getNumElements();
1895
1896 NarrowTy0 = NarrowTy;
1897 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
1898 NarrowTy1 = NarrowTy.isVector() ?
1899 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
1900 SrcTy.getElementType();
1901
1902 } else {
1903 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1904 unsigned OldElts = SrcTy.getNumElements();
1905
1906 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
1907 NarrowTy.getNumElements();
1908 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
1909 DstTy.getScalarSizeInBits());
1910 NarrowTy1 = NarrowTy;
1911 }
1912
1913 // FIXME: Don't know how to handle the situation where the small vectors
1914 // aren't all the same size yet.
1915 if (NarrowTy1.isVector() &&
1916 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
1917 return UnableToLegalize;
1918
1919 CmpInst::Predicate Pred
1920 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
1921
1922 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1923 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
1924 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
1925
1926 for (unsigned I = 0; I < NumParts; ++I) {
1927 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1928 DstRegs.push_back(DstReg);
1929
1930 if (MI.getOpcode() == TargetOpcode::G_ICMP)
1931 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1932 else {
1933 MachineInstr *NewCmp
1934 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1935 NewCmp->setFlags(MI.getFlags());
1936 }
1937 }
1938
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001939 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00001940 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1941 else
1942 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1943
1944 MI.eraseFromParent();
1945 return Legalized;
1946}
1947
1948LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00001949LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
1950 LLT NarrowTy) {
1951 unsigned DstReg = MI.getOperand(0).getReg();
1952 unsigned CondReg = MI.getOperand(1).getReg();
1953
1954 unsigned NumParts = 0;
1955 LLT NarrowTy0, NarrowTy1;
1956
1957 LLT DstTy = MRI.getType(DstReg);
1958 LLT CondTy = MRI.getType(CondReg);
1959 unsigned Size = DstTy.getSizeInBits();
1960
1961 assert(TypeIdx == 0 || CondTy.isVector());
1962
1963 if (TypeIdx == 0) {
1964 NarrowTy0 = NarrowTy;
1965 NarrowTy1 = CondTy;
1966
1967 unsigned NarrowSize = NarrowTy0.getSizeInBits();
1968 // FIXME: Don't know how to handle the situation where the small vectors
1969 // aren't all the same size yet.
1970 if (Size % NarrowSize != 0)
1971 return UnableToLegalize;
1972
1973 NumParts = Size / NarrowSize;
1974
1975 // Need to break down the condition type
1976 if (CondTy.isVector()) {
1977 if (CondTy.getNumElements() == NumParts)
1978 NarrowTy1 = CondTy.getElementType();
1979 else
1980 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
1981 CondTy.getScalarSizeInBits());
1982 }
1983 } else {
1984 NumParts = CondTy.getNumElements();
1985 if (NarrowTy.isVector()) {
1986 // TODO: Handle uneven breakdown.
1987 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
1988 return UnableToLegalize;
1989
1990 return UnableToLegalize;
1991 } else {
1992 NarrowTy0 = DstTy.getElementType();
1993 NarrowTy1 = NarrowTy;
1994 }
1995 }
1996
1997 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1998 if (CondTy.isVector())
1999 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2000
2001 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2002 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2003
2004 for (unsigned i = 0; i < NumParts; ++i) {
2005 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
2006 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2007 Src1Regs[i], Src2Regs[i]);
2008 DstRegs.push_back(DstReg);
2009 }
2010
2011 if (NarrowTy0.isVector())
2012 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2013 else
2014 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2015
2016 MI.eraseFromParent();
2017 return Legalized;
2018}
2019
2020LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002021LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2022 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002023 // FIXME: Don't know how to handle secondary types yet.
2024 if (TypeIdx != 0)
2025 return UnableToLegalize;
2026
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002027 MachineMemOperand *MMO = *MI.memoperands_begin();
2028
2029 // This implementation doesn't work for atomics. Give up instead of doing
2030 // something invalid.
2031 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2032 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2033 return UnableToLegalize;
2034
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002035 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
2036 unsigned ValReg = MI.getOperand(0).getReg();
2037 unsigned AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002038 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002039
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002040 int NumParts = -1;
2041 LLT LeftoverTy;
2042 SmallVector<unsigned, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002043 if (IsLoad) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002044 NumParts = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
2045 } else {
2046 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
2047 NarrowLeftoverRegs))
2048 NumParts = NarrowRegs.size();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002049 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002050
2051 if (NumParts == -1)
2052 return UnableToLegalize;
2053
2054 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2055
2056 unsigned TotalSize = ValTy.getSizeInBits();
2057
2058 // Split the load/store into PartTy sized pieces starting at Offset. If this
2059 // is a load, return the new registers in ValRegs. For a store, each elements
2060 // of ValRegs should be PartTy. Returns the next offset that needs to be
2061 // handled.
2062 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<unsigned> &ValRegs,
2063 unsigned Offset) -> unsigned {
2064 MachineFunction &MF = MIRBuilder.getMF();
2065 unsigned PartSize = PartTy.getSizeInBits();
2066 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2067 Offset += PartSize, ++Idx) {
2068 unsigned ByteSize = PartSize / 8;
2069 unsigned ByteOffset = Offset / 8;
2070 unsigned NewAddrReg = 0;
2071
2072 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2073
2074 MachineMemOperand *NewMMO =
2075 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2076
2077 if (IsLoad) {
2078 unsigned Dst = MRI.createGenericVirtualRegister(PartTy);
2079 ValRegs.push_back(Dst);
2080 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2081 } else {
2082 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2083 }
2084 }
2085
2086 return Offset;
2087 };
2088
2089 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2090
2091 // Handle the rest of the register if this isn't an even type breakdown.
2092 if (LeftoverTy.isValid())
2093 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2094
2095 if (IsLoad) {
2096 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2097 LeftoverTy, NarrowLeftoverRegs);
2098 }
2099
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002100 MI.eraseFromParent();
2101 return Legalized;
2102}
2103
2104LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002105LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2106 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002107 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002108
2109 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002110 switch (MI.getOpcode()) {
2111 case G_IMPLICIT_DEF:
2112 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2113 case G_AND:
2114 case G_OR:
2115 case G_XOR:
2116 case G_ADD:
2117 case G_SUB:
2118 case G_MUL:
2119 case G_SMULH:
2120 case G_UMULH:
2121 case G_FADD:
2122 case G_FMUL:
2123 case G_FSUB:
2124 case G_FNEG:
2125 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002126 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002127 case G_FDIV:
2128 case G_FREM:
2129 case G_FMA:
2130 case G_FPOW:
2131 case G_FEXP:
2132 case G_FEXP2:
2133 case G_FLOG:
2134 case G_FLOG2:
2135 case G_FLOG10:
2136 case G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00002137 case G_FFLOOR:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002138 case G_INTRINSIC_ROUND:
2139 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002140 case G_FCOS:
2141 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002142 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002143 case G_BSWAP:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002144 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002145 case G_SHL:
2146 case G_LSHR:
2147 case G_ASHR:
Matt Arsenault75e30c42019-02-20 16:42:52 +00002148 case G_CTLZ:
2149 case G_CTLZ_ZERO_UNDEF:
2150 case G_CTTZ:
2151 case G_CTTZ_ZERO_UNDEF:
2152 case G_CTPOP:
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002153 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002154 case G_ZEXT:
2155 case G_SEXT:
2156 case G_ANYEXT:
2157 case G_FPEXT:
2158 case G_FPTRUNC:
2159 case G_SITOFP:
2160 case G_UITOFP:
2161 case G_FPTOSI:
2162 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002163 case G_INTTOPTR:
2164 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002165 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002166 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2167 case G_ICMP:
2168 case G_FCMP:
2169 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002170 case G_SELECT:
2171 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002172 case G_LOAD:
2173 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002174 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002175 default:
2176 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002177 }
2178}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002179
2180LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002181LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2182 const LLT HalfTy, const LLT AmtTy) {
2183
2184 unsigned InL = MRI.createGenericVirtualRegister(HalfTy);
2185 unsigned InH = MRI.createGenericVirtualRegister(HalfTy);
2186 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2187
2188 if (Amt.isNullValue()) {
2189 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2190 MI.eraseFromParent();
2191 return Legalized;
2192 }
2193
2194 LLT NVT = HalfTy;
2195 unsigned NVTBits = HalfTy.getSizeInBits();
2196 unsigned VTBits = 2 * NVTBits;
2197
2198 SrcOp Lo(0), Hi(0);
2199 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2200 if (Amt.ugt(VTBits)) {
2201 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2202 } else if (Amt.ugt(NVTBits)) {
2203 Lo = MIRBuilder.buildConstant(NVT, 0);
2204 Hi = MIRBuilder.buildShl(NVT, InL,
2205 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2206 } else if (Amt == NVTBits) {
2207 Lo = MIRBuilder.buildConstant(NVT, 0);
2208 Hi = InL;
2209 } else {
2210 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002211 auto OrLHS =
2212 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2213 auto OrRHS = MIRBuilder.buildLShr(
2214 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2215 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002216 }
2217 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2218 if (Amt.ugt(VTBits)) {
2219 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2220 } else if (Amt.ugt(NVTBits)) {
2221 Lo = MIRBuilder.buildLShr(NVT, InH,
2222 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2223 Hi = MIRBuilder.buildConstant(NVT, 0);
2224 } else if (Amt == NVTBits) {
2225 Lo = InH;
2226 Hi = MIRBuilder.buildConstant(NVT, 0);
2227 } else {
2228 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2229
2230 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2231 auto OrRHS = MIRBuilder.buildShl(
2232 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2233
2234 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2235 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2236 }
2237 } else {
2238 if (Amt.ugt(VTBits)) {
2239 Hi = Lo = MIRBuilder.buildAShr(
2240 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2241 } else if (Amt.ugt(NVTBits)) {
2242 Lo = MIRBuilder.buildAShr(NVT, InH,
2243 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2244 Hi = MIRBuilder.buildAShr(NVT, InH,
2245 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2246 } else if (Amt == NVTBits) {
2247 Lo = InH;
2248 Hi = MIRBuilder.buildAShr(NVT, InH,
2249 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2250 } else {
2251 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2252
2253 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2254 auto OrRHS = MIRBuilder.buildShl(
2255 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2256
2257 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2258 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2259 }
2260 }
2261
2262 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2263 MI.eraseFromParent();
2264
2265 return Legalized;
2266}
2267
2268// TODO: Optimize if constant shift amount.
2269LegalizerHelper::LegalizeResult
2270LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2271 LLT RequestedTy) {
2272 if (TypeIdx == 1) {
2273 Observer.changingInstr(MI);
2274 narrowScalarSrc(MI, RequestedTy, 2);
2275 Observer.changedInstr(MI);
2276 return Legalized;
2277 }
2278
2279 unsigned DstReg = MI.getOperand(0).getReg();
2280 LLT DstTy = MRI.getType(DstReg);
2281 if (DstTy.isVector())
2282 return UnableToLegalize;
2283
2284 unsigned Amt = MI.getOperand(2).getReg();
2285 LLT ShiftAmtTy = MRI.getType(Amt);
2286 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2287 if (DstEltSize % 2 != 0)
2288 return UnableToLegalize;
2289
2290 // Ignore the input type. We can only go to exactly half the size of the
2291 // input. If that isn't small enough, the resulting pieces will be further
2292 // legalized.
2293 const unsigned NewBitSize = DstEltSize / 2;
2294 const LLT HalfTy = LLT::scalar(NewBitSize);
2295 const LLT CondTy = LLT::scalar(1);
2296
2297 if (const MachineInstr *KShiftAmt =
2298 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2299 return narrowScalarShiftByConstant(
2300 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2301 }
2302
2303 // TODO: Expand with known bits.
2304
2305 // Handle the fully general expansion by an unknown amount.
2306 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2307
2308 unsigned InL = MRI.createGenericVirtualRegister(HalfTy);
2309 unsigned InH = MRI.createGenericVirtualRegister(HalfTy);
2310 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2311
2312 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2313 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2314
2315 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2316 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2317 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2318
2319 unsigned ResultRegs[2];
2320 switch (MI.getOpcode()) {
2321 case TargetOpcode::G_SHL: {
2322 // Short: ShAmt < NewBitSize
2323 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2324
2325 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2326 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2327 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2328
2329 // Long: ShAmt >= NewBitSize
2330 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2331 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2332
2333 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2334 auto Hi = MIRBuilder.buildSelect(
2335 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2336
2337 ResultRegs[0] = Lo.getReg(0);
2338 ResultRegs[1] = Hi.getReg(0);
2339 break;
2340 }
2341 case TargetOpcode::G_LSHR: {
2342 // Short: ShAmt < NewBitSize
2343 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2344
2345 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2346 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2347 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2348
2349 // Long: ShAmt >= NewBitSize
2350 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2351 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2352
2353 auto Lo = MIRBuilder.buildSelect(
2354 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2355 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2356
2357 ResultRegs[0] = Lo.getReg(0);
2358 ResultRegs[1] = Hi.getReg(0);
2359 break;
2360 }
2361 case TargetOpcode::G_ASHR: {
2362 // Short: ShAmt < NewBitSize
2363 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2364
2365 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2366 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2367 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2368
2369 // Long: ShAmt >= NewBitSize
2370
2371 // Sign of Hi part.
2372 auto HiL = MIRBuilder.buildAShr(
2373 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2374
2375 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2376
2377 auto Lo = MIRBuilder.buildSelect(
2378 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2379
2380 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2381
2382 ResultRegs[0] = Lo.getReg(0);
2383 ResultRegs[1] = Hi.getReg(0);
2384 break;
2385 }
2386 default:
2387 llvm_unreachable("not a shift");
2388 }
2389
2390 MIRBuilder.buildMerge(DstReg, ResultRegs);
2391 MI.eraseFromParent();
2392 return Legalized;
2393}
2394
2395LegalizerHelper::LegalizeResult
Matt Arsenault72bcf152019-02-28 00:01:05 +00002396LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2397 LLT MoreTy) {
2398 assert(TypeIdx == 0 && "Expecting only Idx 0");
2399
2400 Observer.changingInstr(MI);
2401 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2402 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2403 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2404 moreElementsVectorSrc(MI, MoreTy, I);
2405 }
2406
2407 MachineBasicBlock &MBB = *MI.getParent();
2408 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
2409 moreElementsVectorDst(MI, MoreTy, 0);
2410 Observer.changedInstr(MI);
2411 return Legalized;
2412}
2413
2414LegalizerHelper::LegalizeResult
Matt Arsenault18ec3822019-02-11 22:00:39 +00002415LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
2416 LLT MoreTy) {
2417 MIRBuilder.setInstr(MI);
2418 unsigned Opc = MI.getOpcode();
2419 switch (Opc) {
2420 case TargetOpcode::G_IMPLICIT_DEF: {
2421 Observer.changingInstr(MI);
2422 moreElementsVectorDst(MI, MoreTy, 0);
2423 Observer.changedInstr(MI);
2424 return Legalized;
2425 }
Matt Arsenault26b7e852019-02-19 16:30:19 +00002426 case TargetOpcode::G_AND:
2427 case TargetOpcode::G_OR:
2428 case TargetOpcode::G_XOR: {
2429 Observer.changingInstr(MI);
2430 moreElementsVectorSrc(MI, MoreTy, 1);
2431 moreElementsVectorSrc(MI, MoreTy, 2);
2432 moreElementsVectorDst(MI, MoreTy, 0);
2433 Observer.changedInstr(MI);
2434 return Legalized;
2435 }
Matt Arsenault4d884272019-02-19 16:44:22 +00002436 case TargetOpcode::G_EXTRACT:
2437 if (TypeIdx != 1)
2438 return UnableToLegalize;
2439 Observer.changingInstr(MI);
2440 moreElementsVectorSrc(MI, MoreTy, 1);
2441 Observer.changedInstr(MI);
2442 return Legalized;
Matt Arsenaultc4d07552019-02-20 16:11:22 +00002443 case TargetOpcode::G_INSERT:
2444 if (TypeIdx != 0)
2445 return UnableToLegalize;
2446 Observer.changingInstr(MI);
2447 moreElementsVectorSrc(MI, MoreTy, 1);
2448 moreElementsVectorDst(MI, MoreTy, 0);
2449 Observer.changedInstr(MI);
2450 return Legalized;
Matt Arsenaultb4c95b32019-02-19 17:03:09 +00002451 case TargetOpcode::G_SELECT:
2452 if (TypeIdx != 0)
2453 return UnableToLegalize;
2454 if (MRI.getType(MI.getOperand(1).getReg()).isVector())
2455 return UnableToLegalize;
2456
2457 Observer.changingInstr(MI);
2458 moreElementsVectorSrc(MI, MoreTy, 2);
2459 moreElementsVectorSrc(MI, MoreTy, 3);
2460 moreElementsVectorDst(MI, MoreTy, 0);
2461 Observer.changedInstr(MI);
2462 return Legalized;
Matt Arsenault72bcf152019-02-28 00:01:05 +00002463 case TargetOpcode::G_PHI:
2464 return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +00002465 default:
2466 return UnableToLegalize;
2467 }
2468}
2469
2470LegalizerHelper::LegalizeResult
Matt Arsenault211e89d2019-01-27 00:52:51 +00002471LegalizerHelper::narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT NewTy) {
2472 unsigned DstReg = MI.getOperand(0).getReg();
2473 unsigned Src0 = MI.getOperand(1).getReg();
2474 unsigned Src1 = MI.getOperand(2).getReg();
2475 LLT Ty = MRI.getType(DstReg);
2476 if (Ty.isVector())
2477 return UnableToLegalize;
2478
2479 unsigned Size = Ty.getSizeInBits();
2480 unsigned NewSize = Size / 2;
2481 if (Size != 2 * NewSize)
2482 return UnableToLegalize;
2483
2484 LLT HalfTy = LLT::scalar(NewSize);
2485 // TODO: if HalfTy != NewTy, handle the breakdown all at once?
2486
2487 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
2488 unsigned Lo = MRI.createGenericVirtualRegister(HalfTy);
2489 unsigned Hi = MRI.createGenericVirtualRegister(HalfTy);
2490 unsigned ExtLo = MRI.createGenericVirtualRegister(Ty);
2491 unsigned ExtHi = MRI.createGenericVirtualRegister(Ty);
2492 unsigned ShiftedHi = MRI.createGenericVirtualRegister(Ty);
2493
2494 SmallVector<unsigned, 2> Src0Parts;
2495 SmallVector<unsigned, 2> Src1Parts;
2496
2497 extractParts(Src0, HalfTy, 2, Src0Parts);
2498 extractParts(Src1, HalfTy, 2, Src1Parts);
2499
2500 MIRBuilder.buildMul(Lo, Src0Parts[0], Src1Parts[0]);
2501
2502 // TODO: Use smulh or umulh depending on what the target has.
2503 MIRBuilder.buildUMulH(Hi, Src0Parts[1], Src1Parts[1]);
2504
2505 MIRBuilder.buildConstant(ShiftAmt, NewSize);
2506 MIRBuilder.buildAnyExt(ExtHi, Hi);
2507 MIRBuilder.buildShl(ShiftedHi, ExtHi, ShiftAmt);
2508
2509 MIRBuilder.buildZExt(ExtLo, Lo);
2510 MIRBuilder.buildOr(DstReg, ExtLo, ShiftedHi);
2511 MI.eraseFromParent();
2512 return Legalized;
2513}
2514
Matt Arsenault1cf71362019-02-12 14:54:52 +00002515
2516LegalizerHelper::LegalizeResult
2517LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
2518 LLT NarrowTy) {
2519 if (TypeIdx != 1)
2520 return UnableToLegalize;
2521
2522 uint64_t NarrowSize = NarrowTy.getSizeInBits();
2523
2524 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
2525 // FIXME: add support for when SizeOp1 isn't an exact multiple of
2526 // NarrowSize.
2527 if (SizeOp1 % NarrowSize != 0)
2528 return UnableToLegalize;
2529 int NumParts = SizeOp1 / NarrowSize;
2530
2531 SmallVector<unsigned, 2> SrcRegs, DstRegs;
2532 SmallVector<uint64_t, 2> Indexes;
2533 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
2534
2535 unsigned OpReg = MI.getOperand(0).getReg();
2536 uint64_t OpStart = MI.getOperand(2).getImm();
2537 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
2538 for (int i = 0; i < NumParts; ++i) {
2539 unsigned SrcStart = i * NarrowSize;
2540
2541 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
2542 // No part of the extract uses this subregister, ignore it.
2543 continue;
2544 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
2545 // The entire subregister is extracted, forward the value.
2546 DstRegs.push_back(SrcRegs[i]);
2547 continue;
2548 }
2549
2550 // OpSegStart is where this destination segment would start in OpReg if it
2551 // extended infinitely in both directions.
2552 int64_t ExtractOffset;
2553 uint64_t SegSize;
2554 if (OpStart < SrcStart) {
2555 ExtractOffset = 0;
2556 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
2557 } else {
2558 ExtractOffset = OpStart - SrcStart;
2559 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
2560 }
2561
2562 unsigned SegReg = SrcRegs[i];
2563 if (ExtractOffset != 0 || SegSize != NarrowSize) {
2564 // A genuine extract is needed.
2565 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
2566 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
2567 }
2568
2569 DstRegs.push_back(SegReg);
2570 }
2571
2572 unsigned DstReg = MI.getOperand(0).getReg();
2573 if(MRI.getType(DstReg).isVector())
2574 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2575 else
2576 MIRBuilder.buildMerge(DstReg, DstRegs);
2577 MI.eraseFromParent();
2578 return Legalized;
2579}
2580
2581LegalizerHelper::LegalizeResult
2582LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
2583 LLT NarrowTy) {
2584 // FIXME: Don't know how to handle secondary types yet.
2585 if (TypeIdx != 0)
2586 return UnableToLegalize;
2587
2588 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
2589 uint64_t NarrowSize = NarrowTy.getSizeInBits();
2590
2591 // FIXME: add support for when SizeOp0 isn't an exact multiple of
2592 // NarrowSize.
2593 if (SizeOp0 % NarrowSize != 0)
2594 return UnableToLegalize;
2595
2596 int NumParts = SizeOp0 / NarrowSize;
2597
2598 SmallVector<unsigned, 2> SrcRegs, DstRegs;
2599 SmallVector<uint64_t, 2> Indexes;
2600 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
2601
2602 unsigned OpReg = MI.getOperand(2).getReg();
2603 uint64_t OpStart = MI.getOperand(3).getImm();
2604 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
2605 for (int i = 0; i < NumParts; ++i) {
2606 unsigned DstStart = i * NarrowSize;
2607
2608 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
2609 // No part of the insert affects this subregister, forward the original.
2610 DstRegs.push_back(SrcRegs[i]);
2611 continue;
2612 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
2613 // The entire subregister is defined by this insert, forward the new
2614 // value.
2615 DstRegs.push_back(OpReg);
2616 continue;
2617 }
2618
2619 // OpSegStart is where this destination segment would start in OpReg if it
2620 // extended infinitely in both directions.
2621 int64_t ExtractOffset, InsertOffset;
2622 uint64_t SegSize;
2623 if (OpStart < DstStart) {
2624 InsertOffset = 0;
2625 ExtractOffset = DstStart - OpStart;
2626 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
2627 } else {
2628 InsertOffset = OpStart - DstStart;
2629 ExtractOffset = 0;
2630 SegSize =
2631 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
2632 }
2633
2634 unsigned SegReg = OpReg;
2635 if (ExtractOffset != 0 || SegSize != OpSize) {
2636 // A genuine extract is needed.
2637 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
2638 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
2639 }
2640
2641 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
2642 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
2643 DstRegs.push_back(DstReg);
2644 }
2645
2646 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
2647 unsigned DstReg = MI.getOperand(0).getReg();
2648 if(MRI.getType(DstReg).isVector())
2649 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2650 else
2651 MIRBuilder.buildMerge(DstReg, DstRegs);
2652 MI.eraseFromParent();
2653 return Legalized;
2654}
2655
Matt Arsenault211e89d2019-01-27 00:52:51 +00002656LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00002657LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
2658 LLT NarrowTy) {
2659 if (TypeIdx != 0)
2660 return UnableToLegalize;
2661
2662 unsigned CondReg = MI.getOperand(1).getReg();
2663 LLT CondTy = MRI.getType(CondReg);
2664 if (CondTy.isVector()) // TODO: Handle vselect
2665 return UnableToLegalize;
2666
2667 unsigned DstReg = MI.getOperand(0).getReg();
2668 LLT DstTy = MRI.getType(DstReg);
2669
2670 SmallVector<unsigned, 4> DstRegs, DstLeftoverRegs;
2671 SmallVector<unsigned, 4> Src1Regs, Src1LeftoverRegs;
2672 SmallVector<unsigned, 4> Src2Regs, Src2LeftoverRegs;
2673 LLT LeftoverTy;
2674 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
2675 Src1Regs, Src1LeftoverRegs))
2676 return UnableToLegalize;
2677
2678 LLT Unused;
2679 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
2680 Src2Regs, Src2LeftoverRegs))
2681 llvm_unreachable("inconsistent extractParts result");
2682
2683 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
2684 auto Select = MIRBuilder.buildSelect(NarrowTy,
2685 CondReg, Src1Regs[I], Src2Regs[I]);
2686 DstRegs.push_back(Select->getOperand(0).getReg());
2687 }
2688
2689 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
2690 auto Select = MIRBuilder.buildSelect(
2691 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
2692 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
2693 }
2694
2695 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
2696 LeftoverTy, DstLeftoverRegs);
2697
2698 MI.eraseFromParent();
2699 return Legalized;
2700}
2701
2702LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002703LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
2704 unsigned Opc = MI.getOpcode();
2705 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00002706 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002707 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00002708 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002709 };
2710 switch (Opc) {
2711 default:
2712 return UnableToLegalize;
2713 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
2714 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00002715 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002716 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00002717 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002718 return Legalized;
2719 }
2720 case TargetOpcode::G_CTLZ: {
2721 unsigned SrcReg = MI.getOperand(1).getReg();
2722 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002723 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00002724 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002725 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
2726 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002727 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
2728 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
2729 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
2730 SrcReg, MIBZero);
2731 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
2732 MIBCtlzZU);
2733 MI.eraseFromParent();
2734 return Legalized;
2735 }
2736 // for now, we do this:
2737 // NewLen = NextPowerOf2(Len);
2738 // x = x | (x >> 1);
2739 // x = x | (x >> 2);
2740 // ...
2741 // x = x | (x >>16);
2742 // x = x | (x >>32); // for 64-bit input
2743 // Upto NewLen/2
2744 // return Len - popcount(x);
2745 //
2746 // Ref: "Hacker's Delight" by Henry Warren
2747 unsigned Op = SrcReg;
2748 unsigned NewLen = PowerOf2Ceil(Len);
2749 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
2750 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
2751 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002752 TargetOpcode::G_OR, {Ty},
2753 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
2754 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002755 Op = MIBOp->getOperand(0).getReg();
2756 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002757 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
2758 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2759 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002760 MI.eraseFromParent();
2761 return Legalized;
2762 }
2763 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
2764 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00002765 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002766 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00002767 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002768 return Legalized;
2769 }
2770 case TargetOpcode::G_CTTZ: {
2771 unsigned SrcReg = MI.getOperand(1).getReg();
2772 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002773 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002774 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
2775 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002776 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
2777 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002778 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
2779 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
2780 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
2781 SrcReg, MIBZero);
2782 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
2783 MIBCttzZU);
2784 MI.eraseFromParent();
2785 return Legalized;
2786 }
2787 // for now, we use: { return popcount(~x & (x - 1)); }
2788 // unless the target has ctlz but not ctpop, in which case we use:
2789 // { return 32 - nlz(~x & (x-1)); }
2790 // Ref: "Hacker's Delight" by Henry Warren
2791 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
2792 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002793 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002794 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002795 TargetOpcode::G_AND, {Ty},
2796 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
2797 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002798 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
2799 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002800 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
2801 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002802 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2803 {MIBCstLen,
2804 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002805 MI.eraseFromParent();
2806 return Legalized;
2807 }
2808 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
2809 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
2810 return Legalized;
2811 }
2812 }
2813}