blob: d2c507d4e189dd808fedafbfa66241e38d0f5f80 [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
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000032LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000033 GISelChangeObserver &Observer,
34 MachineIRBuilder &Builder)
35 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
36 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000037 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000038 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000039}
40
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000041LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000042 GISelChangeObserver &Observer,
43 MachineIRBuilder &B)
44 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000045 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000046 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000047}
Tim Northover69fa84a2016-10-14 22:18:18 +000048LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000049LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000050 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000051
Daniel Sanders262ed0e2018-01-24 17:17:46 +000052 auto Step = LI.getAction(MI, MRI);
53 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000054 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000055 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000056 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000057 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000058 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000059 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000060 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000061 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000062 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000063 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000064 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000065 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000066 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000067 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000068 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000069 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000070 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000071 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000072 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000073 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000074 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
75 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000076 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000077 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000078 return UnableToLegalize;
79 }
80}
81
Tim Northover69fa84a2016-10-14 22:18:18 +000082void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
83 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000084 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000085 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000086 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000087}
88
Tim Northovere0418412017-02-08 23:23:39 +000089static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
90 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000091 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000092 assert((Size == 32 || Size == 64) && "Unsupported size");
93 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +000094 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000095 assert((Size == 32 || Size == 64) && "Unsupported size");
96 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000097 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000098 assert((Size == 32 || Size == 64) && "Unsupported size");
99 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000100 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000101 assert((Size == 32 || Size == 64) && "Unsupported size");
102 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000103 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
104 assert(Size == 32 && "Unsupported size");
105 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000106 case TargetOpcode::G_FADD:
107 assert((Size == 32 || Size == 64) && "Unsupported size");
108 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000109 case TargetOpcode::G_FSUB:
110 assert((Size == 32 || Size == 64) && "Unsupported size");
111 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000112 case TargetOpcode::G_FMUL:
113 assert((Size == 32 || Size == 64) && "Unsupported size");
114 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000115 case TargetOpcode::G_FDIV:
116 assert((Size == 32 || Size == 64) && "Unsupported size");
117 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000118 case TargetOpcode::G_FREM:
119 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
120 case TargetOpcode::G_FPOW:
121 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000122 case TargetOpcode::G_FMA:
123 assert((Size == 32 || Size == 64) && "Unsupported size");
124 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000125 }
126 llvm_unreachable("Unknown libcall function");
127}
128
Diana Picusfc1675e2017-07-05 12:57:24 +0000129LegalizerHelper::LegalizeResult
130llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
131 const CallLowering::ArgInfo &Result,
132 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000133 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
134 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000135 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000136
Diana Picuse97822e2017-04-24 07:22:31 +0000137 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000138 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
139 MachineOperand::CreateES(Name), Result, Args))
140 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000141
Diana Picuse97822e2017-04-24 07:22:31 +0000142 return LegalizerHelper::Legalized;
143}
144
Diana Picus65ed3642018-01-17 13:34:10 +0000145// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000146static LegalizerHelper::LegalizeResult
147simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
148 Type *OpType) {
149 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000150
151 SmallVector<CallLowering::ArgInfo, 3> Args;
152 for (unsigned i = 1; i < MI.getNumOperands(); i++)
153 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000154 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000155 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000156}
157
Diana Picus65ed3642018-01-17 13:34:10 +0000158static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
159 Type *FromType) {
160 auto ToMVT = MVT::getVT(ToType);
161 auto FromMVT = MVT::getVT(FromType);
162
163 switch (Opcode) {
164 case TargetOpcode::G_FPEXT:
165 return RTLIB::getFPEXT(FromMVT, ToMVT);
166 case TargetOpcode::G_FPTRUNC:
167 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000168 case TargetOpcode::G_FPTOSI:
169 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
170 case TargetOpcode::G_FPTOUI:
171 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000172 case TargetOpcode::G_SITOFP:
173 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
174 case TargetOpcode::G_UITOFP:
175 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000176 }
177 llvm_unreachable("Unsupported libcall function");
178}
179
180static LegalizerHelper::LegalizeResult
181conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
182 Type *FromType) {
183 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
184 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
185 {{MI.getOperand(1).getReg(), FromType}});
186}
187
Tim Northover69fa84a2016-10-14 22:18:18 +0000188LegalizerHelper::LegalizeResult
189LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000190 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
191 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000192 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000193
Diana Picusfc1675e2017-07-05 12:57:24 +0000194 MIRBuilder.setInstr(MI);
195
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000196 switch (MI.getOpcode()) {
197 default:
198 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000199 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000200 case TargetOpcode::G_UDIV:
201 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000202 case TargetOpcode::G_UREM:
203 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000204 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000205 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
206 if (Status != Legalized)
207 return Status;
208 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000209 }
Diana Picus1314a282017-04-11 10:52:34 +0000210 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000211 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000212 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000213 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000214 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000215 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000216 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000217 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000218 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
219 if (Status != Legalized)
220 return Status;
221 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000222 }
Diana Picus65ed3642018-01-17 13:34:10 +0000223 case TargetOpcode::G_FPEXT: {
224 // FIXME: Support other floating point types (half, fp128 etc)
225 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
226 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
227 if (ToSize != 64 || FromSize != 32)
228 return UnableToLegalize;
229 LegalizeResult Status = conversionLibcall(
230 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
231 if (Status != Legalized)
232 return Status;
233 break;
234 }
235 case TargetOpcode::G_FPTRUNC: {
236 // FIXME: Support other floating point types (half, fp128 etc)
237 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
238 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
239 if (ToSize != 32 || FromSize != 64)
240 return UnableToLegalize;
241 LegalizeResult Status = conversionLibcall(
242 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
243 if (Status != Legalized)
244 return Status;
245 break;
246 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000247 case TargetOpcode::G_FPTOSI:
248 case TargetOpcode::G_FPTOUI: {
249 // FIXME: Support other types
250 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
251 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
252 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
253 return UnableToLegalize;
254 LegalizeResult Status = conversionLibcall(
255 MI, MIRBuilder, Type::getInt32Ty(Ctx),
256 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
257 if (Status != Legalized)
258 return Status;
259 break;
260 }
Diana Picus517531e2018-01-30 09:15:17 +0000261 case TargetOpcode::G_SITOFP:
262 case TargetOpcode::G_UITOFP: {
263 // FIXME: Support other types
264 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
265 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
266 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
267 return UnableToLegalize;
268 LegalizeResult Status = conversionLibcall(
269 MI, MIRBuilder,
270 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
271 Type::getInt32Ty(Ctx));
272 if (Status != Legalized)
273 return Status;
274 break;
275 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000276 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000277
278 MI.eraseFromParent();
279 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000280}
281
Tim Northover69fa84a2016-10-14 22:18:18 +0000282LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
283 unsigned TypeIdx,
284 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000285 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000286 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000287 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000288
289 MIRBuilder.setInstr(MI);
290
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000291 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
292 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000293
Tim Northover9656f142016-08-04 20:54:13 +0000294 switch (MI.getOpcode()) {
295 default:
296 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000297 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000298 // FIXME: add support for when SizeOp0 isn't an exact multiple of
299 // NarrowSize.
300 if (SizeOp0 % NarrowSize != 0)
301 return UnableToLegalize;
302 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000303
304 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000305 for (int i = 0; i < NumParts; ++i)
306 DstRegs.push_back(
307 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000308
309 unsigned DstReg = MI.getOperand(0).getReg();
310 if(MRI.getType(DstReg).isVector())
311 MIRBuilder.buildBuildVector(DstReg, DstRegs);
312 else
313 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000314 MI.eraseFromParent();
315 return Legalized;
316 }
Tim Northover9656f142016-08-04 20:54:13 +0000317 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000318 // FIXME: add support for when SizeOp0 isn't an exact multiple of
319 // NarrowSize.
320 if (SizeOp0 % NarrowSize != 0)
321 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000322 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000323 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000324
Tim Northoverb18ea162016-09-20 15:20:36 +0000325 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000326 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
327 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
328
Tim Northover0f140c72016-09-09 11:46:34 +0000329 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
330 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000331
332 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000333 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
334 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000335
Tim Northover0f140c72016-09-09 11:46:34 +0000336 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000337 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000338
339 DstRegs.push_back(DstReg);
340 CarryIn = CarryOut;
341 }
Tim Northover0f140c72016-09-09 11:46:34 +0000342 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000343 if(MRI.getType(DstReg).isVector())
344 MIRBuilder.buildBuildVector(DstReg, DstRegs);
345 else
346 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000347 MI.eraseFromParent();
348 return Legalized;
349 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000350 case TargetOpcode::G_EXTRACT: {
351 if (TypeIdx != 1)
352 return UnableToLegalize;
353
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000354 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
355 // FIXME: add support for when SizeOp1 isn't an exact multiple of
356 // NarrowSize.
357 if (SizeOp1 % NarrowSize != 0)
358 return UnableToLegalize;
359 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000360
361 SmallVector<unsigned, 2> SrcRegs, DstRegs;
362 SmallVector<uint64_t, 2> Indexes;
363 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
364
365 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000366 uint64_t OpStart = MI.getOperand(2).getImm();
367 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000368 for (int i = 0; i < NumParts; ++i) {
369 unsigned SrcStart = i * NarrowSize;
370
371 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
372 // No part of the extract uses this subregister, ignore it.
373 continue;
374 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
375 // The entire subregister is extracted, forward the value.
376 DstRegs.push_back(SrcRegs[i]);
377 continue;
378 }
379
380 // OpSegStart is where this destination segment would start in OpReg if it
381 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000382 int64_t ExtractOffset;
383 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000384 if (OpStart < SrcStart) {
385 ExtractOffset = 0;
386 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
387 } else {
388 ExtractOffset = OpStart - SrcStart;
389 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
390 }
391
392 unsigned SegReg = SrcRegs[i];
393 if (ExtractOffset != 0 || SegSize != NarrowSize) {
394 // A genuine extract is needed.
395 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
396 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
397 }
398
399 DstRegs.push_back(SegReg);
400 }
401
Amara Emerson5ec14602018-12-10 18:44:58 +0000402 unsigned DstReg = MI.getOperand(0).getReg();
403 if(MRI.getType(DstReg).isVector())
404 MIRBuilder.buildBuildVector(DstReg, DstRegs);
405 else
406 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000407 MI.eraseFromParent();
408 return Legalized;
409 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000410 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000411 // FIXME: add support for when SizeOp0 isn't an exact multiple of
412 // NarrowSize.
413 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000414 return UnableToLegalize;
415
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000416 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000417
418 SmallVector<unsigned, 2> SrcRegs, DstRegs;
419 SmallVector<uint64_t, 2> Indexes;
420 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
421
Tim Northover75e0b912017-03-06 18:23:04 +0000422 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000423 uint64_t OpStart = MI.getOperand(3).getImm();
424 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000425 for (int i = 0; i < NumParts; ++i) {
426 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000427
Tim Northover75e0b912017-03-06 18:23:04 +0000428 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000429 // No part of the insert affects this subregister, forward the original.
430 DstRegs.push_back(SrcRegs[i]);
431 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000432 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000433 // The entire subregister is defined by this insert, forward the new
434 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000435 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000436 continue;
437 }
438
Tim Northover2eb18d32017-03-07 21:24:33 +0000439 // OpSegStart is where this destination segment would start in OpReg if it
440 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000441 int64_t ExtractOffset, InsertOffset;
442 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000443 if (OpStart < DstStart) {
444 InsertOffset = 0;
445 ExtractOffset = DstStart - OpStart;
446 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
447 } else {
448 InsertOffset = OpStart - DstStart;
449 ExtractOffset = 0;
450 SegSize =
451 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
452 }
453
454 unsigned SegReg = OpReg;
455 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000456 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000457 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
458 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000459 }
460
Tim Northover75e0b912017-03-06 18:23:04 +0000461 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000462 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000463 DstRegs.push_back(DstReg);
464 }
465
466 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000467 unsigned DstReg = MI.getOperand(0).getReg();
468 if(MRI.getType(DstReg).isVector())
469 MIRBuilder.buildBuildVector(DstReg, DstRegs);
470 else
471 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000472 MI.eraseFromParent();
473 return Legalized;
474 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000475 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000476 // FIXME: add support for when SizeOp0 isn't an exact multiple of
477 // NarrowSize.
478 if (SizeOp0 % NarrowSize != 0)
479 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000480
481 const auto &MMO = **MI.memoperands_begin();
482 // This implementation doesn't work for atomics. Give up instead of doing
483 // something invalid.
484 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
485 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
486 return UnableToLegalize;
487
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000488 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000489 LLT OffsetTy = LLT::scalar(
490 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000491
492 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000493 for (int i = 0; i < NumParts; ++i) {
494 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000495 unsigned SrcReg = 0;
496 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000497 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000498
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000499 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
500 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000501 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
502 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000503
Daniel Sanders4e523662017-06-13 23:42:32 +0000504 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
505 Adjustment);
506
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000507 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000508
509 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000510 }
511 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000512 if(MRI.getType(DstReg).isVector())
513 MIRBuilder.buildBuildVector(DstReg, DstRegs);
514 else
515 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000516 MI.eraseFromParent();
517 return Legalized;
518 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000519 case TargetOpcode::G_ZEXTLOAD:
520 case TargetOpcode::G_SEXTLOAD: {
521 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
522 unsigned DstReg = MI.getOperand(0).getReg();
523 unsigned PtrReg = MI.getOperand(1).getReg();
524
525 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
526 auto &MMO = **MI.memoperands_begin();
527 if (MMO.getSize() * 8 == NarrowSize) {
528 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
529 } else {
530 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
531 : TargetOpcode::G_SEXTLOAD;
532 MIRBuilder.buildInstr(ExtLoad)
533 .addDef(TmpReg)
534 .addUse(PtrReg)
535 .addMemOperand(&MMO);
536 }
537
538 if (ZExt)
539 MIRBuilder.buildZExt(DstReg, TmpReg);
540 else
541 MIRBuilder.buildSExt(DstReg, TmpReg);
542
543 MI.eraseFromParent();
544 return Legalized;
545 }
Justin Bognerfde01042017-01-18 17:29:54 +0000546 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000547 // FIXME: add support for when SizeOp0 isn't an exact multiple of
548 // NarrowSize.
549 if (SizeOp0 % NarrowSize != 0)
550 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000551
552 const auto &MMO = **MI.memoperands_begin();
553 // This implementation doesn't work for atomics. Give up instead of doing
554 // something invalid.
555 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
556 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
557 return UnableToLegalize;
558
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000559 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000560 LLT OffsetTy = LLT::scalar(
561 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000562
563 SmallVector<unsigned, 2> SrcRegs;
564 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
565
566 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000567 unsigned DstReg = 0;
568 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000569 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Daniel Sanders4e523662017-06-13 23:42:32 +0000570
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000571 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
572 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000573 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
574 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000575
Daniel Sanders4e523662017-06-13 23:42:32 +0000576 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
577 Adjustment);
578
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000579 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000580 }
581 MI.eraseFromParent();
582 return Legalized;
583 }
Igor Breger29537882017-04-07 14:41:59 +0000584 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000585 // FIXME: add support for when SizeOp0 isn't an exact multiple of
586 // NarrowSize.
587 if (SizeOp0 % NarrowSize != 0)
588 return UnableToLegalize;
589 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000590 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000591 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000592
593 SmallVector<unsigned, 2> DstRegs;
594 for (int i = 0; i < NumParts; ++i) {
595 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
596 ConstantInt *CI =
597 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
598 MIRBuilder.buildConstant(DstReg, *CI);
599 DstRegs.push_back(DstReg);
600 }
601 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000602 if(MRI.getType(DstReg).isVector())
603 MIRBuilder.buildBuildVector(DstReg, DstRegs);
604 else
605 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000606 MI.eraseFromParent();
607 return Legalized;
608 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000609 case TargetOpcode::G_AND:
610 case TargetOpcode::G_OR:
611 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000612 // Legalize bitwise operation:
613 // A = BinOp<Ty> B, C
614 // into:
615 // B1, ..., BN = G_UNMERGE_VALUES B
616 // C1, ..., CN = G_UNMERGE_VALUES C
617 // A1 = BinOp<Ty/N> B1, C2
618 // ...
619 // AN = BinOp<Ty/N> BN, CN
620 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000621
622 // FIXME: add support for when SizeOp0 isn't an exact multiple of
623 // NarrowSize.
624 if (SizeOp0 % NarrowSize != 0)
625 return UnableToLegalize;
626 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000627
628 // List the registers where the destination will be scattered.
629 SmallVector<unsigned, 2> DstRegs;
630 // List the registers where the first argument will be split.
631 SmallVector<unsigned, 2> SrcsReg1;
632 // List the registers where the second argument will be split.
633 SmallVector<unsigned, 2> SrcsReg2;
634 // Create all the temporary registers.
635 for (int i = 0; i < NumParts; ++i) {
636 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
637 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
638 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
639
640 DstRegs.push_back(DstReg);
641 SrcsReg1.push_back(SrcReg1);
642 SrcsReg2.push_back(SrcReg2);
643 }
644 // Explode the big arguments into smaller chunks.
645 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
646 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
647
648 // Do the operation on each small part.
649 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000650 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
651 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000652
653 // Gather the destination registers into the final destination.
654 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000655 if(MRI.getType(DstReg).isVector())
656 MIRBuilder.buildBuildVector(DstReg, DstRegs);
657 else
658 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000659 MI.eraseFromParent();
660 return Legalized;
661 }
Tim Northover9656f142016-08-04 20:54:13 +0000662 }
Tim Northover33b07d62016-07-22 20:03:43 +0000663}
664
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000665void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
666 unsigned OpIdx, unsigned ExtOpcode) {
667 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000668 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000669 MO.setReg(ExtB->getOperand(0).getReg());
670}
671
672void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
673 unsigned OpIdx, unsigned TruncOpcode) {
674 MachineOperand &MO = MI.getOperand(OpIdx);
675 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
676 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000677 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000678 MO.setReg(DstExt);
679}
680
Tim Northover69fa84a2016-10-14 22:18:18 +0000681LegalizerHelper::LegalizeResult
682LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000683 MIRBuilder.setInstr(MI);
684
Tim Northover32335812016-08-04 18:35:11 +0000685 switch (MI.getOpcode()) {
686 default:
687 return UnableToLegalize;
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000688 case TargetOpcode::G_UADDO:
689 case TargetOpcode::G_USUBO: {
690 if (TypeIdx == 1)
691 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000692 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
693 {MI.getOperand(2).getReg()});
694 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
695 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000696 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
697 ? TargetOpcode::G_ADD
698 : TargetOpcode::G_SUB;
699 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000700 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000701 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
702 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
703 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000704 TargetOpcode::G_AND, {WideTy},
705 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000706 // There is no overflow if the AndOp is the same as NewOp.
707 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
708 AndOp);
709 // Now trunc the NewOp to the original result.
710 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
711 MI.eraseFromParent();
712 return Legalized;
713 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000714 case TargetOpcode::G_CTTZ:
715 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
716 case TargetOpcode::G_CTLZ:
717 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
718 case TargetOpcode::G_CTPOP: {
719 // First ZEXT the input.
720 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
721 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
722 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
723 // The count is the same in the larger type except if the original
724 // value was zero. This can be handled by setting the bit just off
725 // the top of the original type.
726 auto TopBit =
727 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
728 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000729 TargetOpcode::G_OR, {WideTy},
730 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000731 }
732 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000733 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000734 // This is already the correct result for CTPOP and CTTZs
735 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
736 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
737 // The correct result is NewOp - (Difference in widety and current ty).
738 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000739 MIBNewOp = MIRBuilder.buildInstr(
740 TargetOpcode::G_SUB, {WideTy},
741 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000742 }
743 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +0000744 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000745 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000746 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
747 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000748 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000749 return Legalized;
750 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000751
Tim Northover61c16142016-08-04 21:39:49 +0000752 case TargetOpcode::G_ADD:
753 case TargetOpcode::G_AND:
754 case TargetOpcode::G_MUL:
755 case TargetOpcode::G_OR:
756 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000757 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000758 // Perform operation at larger width (any extension is fine here, high bits
759 // don't affect the result) and then truncate the result back to the
760 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000761 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000762 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
763 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
764 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000765 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000766 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000767
Roman Tereshin6d266382018-05-09 21:43:30 +0000768 case TargetOpcode::G_SHL:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000769 Observer.changingInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000770 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
771 // The "number of bits to shift" operand must preserve its value as an
772 // unsigned integer:
773 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
774 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000775 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000776 return Legalized;
777
Tim Northover7a753d92016-08-26 17:46:06 +0000778 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000779 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000780 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000781 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
782 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
783 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000784 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000785 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000786
Roman Tereshin6d266382018-05-09 21:43:30 +0000787 case TargetOpcode::G_ASHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000788 Observer.changingInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000789 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
790 // The "number of bits to shift" operand must preserve its value as an
791 // unsigned integer:
792 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
793 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000794 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000795 return Legalized;
796
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000797 case TargetOpcode::G_UDIV:
798 case TargetOpcode::G_UREM:
799 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000800 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000801 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
802 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
803 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000804 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000805 return Legalized;
806
807 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000808 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +0000809 if (TypeIdx == 0) {
810 // Perform operation at larger width (any extension is fine here, high
811 // bits don't affect the result) and then truncate the result back to the
812 // original type.
813 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
814 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
815 widenScalarDst(MI, WideTy);
816 } else {
817 // Explicit extension is required here since high bits affect the result.
818 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
819 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000820 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000821 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000822
Ahmed Bougachab6137062017-01-23 21:10:14 +0000823 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000824 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +0000825 if (TypeIdx != 0)
826 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000827 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000828 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000829 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000830 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000831
Ahmed Bougachad2948232017-01-20 01:37:24 +0000832 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +0000833 if (TypeIdx != 1)
834 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000835 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000836 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000837 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000838 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000839
840 case TargetOpcode::G_UITOFP:
841 if (TypeIdx != 1)
842 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000843 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000844 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000845 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000846 return Legalized;
847
848 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +0000849 if (TypeIdx != 0)
850 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000851 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000852 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
853 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000854 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000855 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000856
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000857 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +0000858 // For some types like i24, we might try to widen to i32. To properly handle
859 // this we should be using a dedicated extending load, until then avoid
860 // trying to legalize.
861 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
862 WideTy.getSizeInBits())
863 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000864 LLVM_FALLTHROUGH;
865 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000866 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000867 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000868 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000869 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000870 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000871
Tim Northover3c73e362016-08-23 18:20:09 +0000872 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000873 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
874 WideTy != LLT::scalar(8))
875 return UnableToLegalize;
876
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000877 Observer.changingInstr(MI);
Amara Emerson5a3bb682018-06-01 13:20:32 +0000878 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000879 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000880 return Legalized;
881 }
Tim Northoverea904f92016-08-19 22:40:00 +0000882 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000883 MachineOperand &SrcMO = MI.getOperand(1);
884 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
885 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000886 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000887 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
888
889 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000890 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +0000891 return Legalized;
892 }
Tim Northovera11be042016-08-19 22:40:08 +0000893 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000894 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +0000895 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000896 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +0000897 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000898 switch (WideTy.getSizeInBits()) {
899 case 32:
900 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
901 break;
902 case 64:
903 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
904 break;
905 default:
906 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +0000907 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000908 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000909 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
910
911 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000912 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +0000913 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +0000914 }
Matt Arsenaultbefee402019-01-09 07:34:14 +0000915 case TargetOpcode::G_IMPLICIT_DEF: {
916 Observer.changingInstr(MI);
917 widenScalarDst(MI, WideTy);
918 Observer.changedInstr(MI);
919 return Legalized;
920 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000921 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000922 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000923 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000924 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000925 return Legalized;
926
927 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000928 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000929 if (TypeIdx == 0)
930 widenScalarDst(MI, WideTy);
931 else {
932 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
933 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +0000934 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000935 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000936 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000937
938 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000939 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000940 if (TypeIdx == 0)
941 widenScalarDst(MI, WideTy);
942 else {
943 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
944 MI.getOperand(1).getPredicate()))
945 ? TargetOpcode::G_SEXT
946 : TargetOpcode::G_ZEXT;
947 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
948 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
949 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000950 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000951 return Legalized;
952
953 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +0000954 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000955 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000956 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000957 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +0000958 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000959
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000960 case TargetOpcode::G_PHI: {
961 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000962
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000963 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000964 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
965 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
966 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
967 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000968 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000969
970 MachineBasicBlock &MBB = *MI.getParent();
971 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
972 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000973 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000974 return Legalized;
975 }
Amara Emersoncbd86d82018-10-25 14:04:54 +0000976 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
977 if (TypeIdx != 2)
978 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000979 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +0000980 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000981 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +0000982 return Legalized;
Matt Arsenault745fd9f2019-01-20 19:10:31 +0000983 case TargetOpcode::G_FADD:
984 case TargetOpcode::G_FMUL:
985 case TargetOpcode::G_FSUB:
986 case TargetOpcode::G_FMA:
987 case TargetOpcode::G_FNEG:
988 case TargetOpcode::G_FABS:
989 case TargetOpcode::G_FDIV:
990 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +0000991 case TargetOpcode::G_FCEIL:
Matt Arsenault745fd9f2019-01-20 19:10:31 +0000992 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +0000993 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +0000994
995 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
996 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
997
Jessica Paquette453ab1d2018-12-21 17:05:26 +0000998 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
999 Observer.changedInstr(MI);
1000 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001001 }
Tim Northover33b07d62016-07-22 20:03:43 +00001002}
1003
Tim Northover69fa84a2016-10-14 22:18:18 +00001004LegalizerHelper::LegalizeResult
1005LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001006 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001007 MIRBuilder.setInstr(MI);
1008
1009 switch(MI.getOpcode()) {
1010 default:
1011 return UnableToLegalize;
1012 case TargetOpcode::G_SREM:
1013 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001014 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1015 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001016 .addDef(QuotReg)
1017 .addUse(MI.getOperand(1).getReg())
1018 .addUse(MI.getOperand(2).getReg());
1019
Tim Northover0f140c72016-09-09 11:46:34 +00001020 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1021 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1022 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1023 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001024 MI.eraseFromParent();
1025 return Legalized;
1026 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001027 case TargetOpcode::G_SMULO:
1028 case TargetOpcode::G_UMULO: {
1029 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1030 // result.
1031 unsigned Res = MI.getOperand(0).getReg();
1032 unsigned Overflow = MI.getOperand(1).getReg();
1033 unsigned LHS = MI.getOperand(2).getReg();
1034 unsigned RHS = MI.getOperand(3).getReg();
1035
1036 MIRBuilder.buildMul(Res, LHS, RHS);
1037
1038 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1039 ? TargetOpcode::G_SMULH
1040 : TargetOpcode::G_UMULH;
1041
1042 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1043 MIRBuilder.buildInstr(Opcode)
1044 .addDef(HiPart)
1045 .addUse(LHS)
1046 .addUse(RHS);
1047
1048 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1049 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001050
1051 // For *signed* multiply, overflow is detected by checking:
1052 // (hi != (lo >> bitwidth-1))
1053 if (Opcode == TargetOpcode::G_SMULH) {
1054 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1055 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1056 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1057 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1058 .addDef(Shifted)
1059 .addUse(Res)
1060 .addUse(ShiftAmt);
1061 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1062 } else {
1063 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1064 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001065 MI.eraseFromParent();
1066 return Legalized;
1067 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001068 case TargetOpcode::G_FNEG: {
1069 // TODO: Handle vector types once we are able to
1070 // represent them.
1071 if (Ty.isVector())
1072 return UnableToLegalize;
1073 unsigned Res = MI.getOperand(0).getReg();
1074 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001075 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001076 switch (Ty.getSizeInBits()) {
1077 case 16:
1078 ZeroTy = Type::getHalfTy(Ctx);
1079 break;
1080 case 32:
1081 ZeroTy = Type::getFloatTy(Ctx);
1082 break;
1083 case 64:
1084 ZeroTy = Type::getDoubleTy(Ctx);
1085 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001086 case 128:
1087 ZeroTy = Type::getFP128Ty(Ctx);
1088 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001089 default:
1090 llvm_unreachable("unexpected floating-point type");
1091 }
1092 ConstantFP &ZeroForNegation =
1093 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001094 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001095 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1096 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001097 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001098 .addUse(MI.getOperand(1).getReg());
1099 MI.eraseFromParent();
1100 return Legalized;
1101 }
Volkan Keles225921a2017-03-10 21:25:09 +00001102 case TargetOpcode::G_FSUB: {
1103 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1104 // First, check if G_FNEG is marked as Lower. If so, we may
1105 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001106 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001107 return UnableToLegalize;
1108 unsigned Res = MI.getOperand(0).getReg();
1109 unsigned LHS = MI.getOperand(1).getReg();
1110 unsigned RHS = MI.getOperand(2).getReg();
1111 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1112 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1113 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1114 .addDef(Res)
1115 .addUse(LHS)
1116 .addUse(Neg);
1117 MI.eraseFromParent();
1118 return Legalized;
1119 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001120 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1121 unsigned OldValRes = MI.getOperand(0).getReg();
1122 unsigned SuccessRes = MI.getOperand(1).getReg();
1123 unsigned Addr = MI.getOperand(2).getReg();
1124 unsigned CmpVal = MI.getOperand(3).getReg();
1125 unsigned NewVal = MI.getOperand(4).getReg();
1126 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1127 **MI.memoperands_begin());
1128 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1129 MI.eraseFromParent();
1130 return Legalized;
1131 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001132 case TargetOpcode::G_LOAD:
1133 case TargetOpcode::G_SEXTLOAD:
1134 case TargetOpcode::G_ZEXTLOAD: {
1135 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1136 unsigned DstReg = MI.getOperand(0).getReg();
1137 unsigned PtrReg = MI.getOperand(1).getReg();
1138 LLT DstTy = MRI.getType(DstReg);
1139 auto &MMO = **MI.memoperands_begin();
1140
1141 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001142 // In the case of G_LOAD, this was a non-extending load already and we're
1143 // about to lower to the same instruction.
1144 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1145 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001146 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1147 MI.eraseFromParent();
1148 return Legalized;
1149 }
1150
1151 if (DstTy.isScalar()) {
1152 unsigned TmpReg = MRI.createGenericVirtualRegister(
1153 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1154 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1155 switch (MI.getOpcode()) {
1156 default:
1157 llvm_unreachable("Unexpected opcode");
1158 case TargetOpcode::G_LOAD:
1159 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1160 break;
1161 case TargetOpcode::G_SEXTLOAD:
1162 MIRBuilder.buildSExt(DstReg, TmpReg);
1163 break;
1164 case TargetOpcode::G_ZEXTLOAD:
1165 MIRBuilder.buildZExt(DstReg, TmpReg);
1166 break;
1167 }
1168 MI.eraseFromParent();
1169 return Legalized;
1170 }
1171
1172 return UnableToLegalize;
1173 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001174 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1175 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1176 case TargetOpcode::G_CTLZ:
1177 case TargetOpcode::G_CTTZ:
1178 case TargetOpcode::G_CTPOP:
1179 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001180 case G_UADDE: {
1181 unsigned Res = MI.getOperand(0).getReg();
1182 unsigned CarryOut = MI.getOperand(1).getReg();
1183 unsigned LHS = MI.getOperand(2).getReg();
1184 unsigned RHS = MI.getOperand(3).getReg();
1185 unsigned CarryIn = MI.getOperand(4).getReg();
1186
1187 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1188 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1189
1190 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1191 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1192 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1193 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1194
1195 MI.eraseFromParent();
1196 return Legalized;
1197 }
Tim Northovercecee562016-08-26 17:46:13 +00001198 }
1199}
1200
Tim Northover69fa84a2016-10-14 22:18:18 +00001201LegalizerHelper::LegalizeResult
1202LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1203 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +00001204 // FIXME: Don't know how to handle secondary types yet.
1205 if (TypeIdx != 0)
1206 return UnableToLegalize;
Volkan Keles574d7372018-12-14 22:11:20 +00001207
1208 MIRBuilder.setInstr(MI);
Tim Northover33b07d62016-07-22 20:03:43 +00001209 switch (MI.getOpcode()) {
1210 default:
1211 return UnableToLegalize;
Matt Arsenault3dddb162019-01-09 07:51:52 +00001212 case TargetOpcode::G_IMPLICIT_DEF: {
1213 SmallVector<unsigned, 2> DstRegs;
1214
1215 unsigned NarrowSize = NarrowTy.getSizeInBits();
1216 unsigned DstReg = MI.getOperand(0).getReg();
1217 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1218 int NumParts = Size / NarrowSize;
1219 // FIXME: Don't know how to handle the situation where the small vectors
1220 // aren't all the same size yet.
1221 if (Size % NarrowSize != 0)
1222 return UnableToLegalize;
1223
1224 for (int i = 0; i < NumParts; ++i) {
1225 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1226 MIRBuilder.buildUndef(TmpReg);
1227 DstRegs.push_back(TmpReg);
1228 }
1229
1230 if (NarrowTy.isVector())
1231 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1232 else
1233 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1234
1235 MI.eraseFromParent();
1236 return Legalized;
1237 }
Tim Northover33b07d62016-07-22 20:03:43 +00001238 case TargetOpcode::G_ADD: {
1239 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +00001240 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +00001241 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1242 int NumParts = Size / NarrowSize;
1243 // FIXME: Don't know how to handle the situation where the small vectors
1244 // aren't all the same size yet.
1245 if (Size % NarrowSize != 0)
1246 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001247
Tim Northoverb18ea162016-09-20 15:20:36 +00001248 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +00001249 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
1250 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
1251
1252 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +00001253 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1254 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +00001255 DstRegs.push_back(DstReg);
1256 }
1257
Amara Emerson5ec14602018-12-10 18:44:58 +00001258 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +00001259 MI.eraseFromParent();
1260 return Legalized;
1261 }
Volkan Keles574d7372018-12-14 22:11:20 +00001262 case TargetOpcode::G_LOAD:
1263 case TargetOpcode::G_STORE: {
1264 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1265 unsigned ValReg = MI.getOperand(0).getReg();
1266 unsigned AddrReg = MI.getOperand(1).getReg();
1267 unsigned NarrowSize = NarrowTy.getSizeInBits();
1268 unsigned Size = MRI.getType(ValReg).getSizeInBits();
1269 unsigned NumParts = Size / NarrowSize;
1270
1271 SmallVector<unsigned, 8> NarrowRegs;
1272 if (!IsLoad)
1273 extractParts(ValReg, NarrowTy, NumParts, NarrowRegs);
1274
1275 const LLT OffsetTy =
1276 LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1277 MachineFunction &MF = *MI.getMF();
1278 MachineMemOperand *MMO = *MI.memoperands_begin();
1279 for (unsigned Idx = 0; Idx < NumParts; ++Idx) {
1280 unsigned Adjustment = Idx * NarrowTy.getSizeInBits() / 8;
1281 unsigned Alignment = MinAlign(MMO->getAlignment(), Adjustment);
1282 unsigned NewAddrReg = 0;
1283 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, Adjustment);
1284 MachineMemOperand &NewMMO = *MF.getMachineMemOperand(
1285 MMO->getPointerInfo().getWithOffset(Adjustment), MMO->getFlags(),
1286 NarrowTy.getSizeInBits() / 8, Alignment);
1287 if (IsLoad) {
1288 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
1289 NarrowRegs.push_back(Dst);
1290 MIRBuilder.buildLoad(Dst, NewAddrReg, NewMMO);
1291 } else {
1292 MIRBuilder.buildStore(NarrowRegs[Idx], NewAddrReg, NewMMO);
1293 }
1294 }
1295 if (IsLoad) {
1296 if (NarrowTy.isVector())
1297 MIRBuilder.buildConcatVectors(ValReg, NarrowRegs);
1298 else
1299 MIRBuilder.buildBuildVector(ValReg, NarrowRegs);
1300 }
1301 MI.eraseFromParent();
1302 return Legalized;
1303 }
Tim Northover33b07d62016-07-22 20:03:43 +00001304 }
1305}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001306
1307LegalizerHelper::LegalizeResult
1308LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1309 unsigned Opc = MI.getOpcode();
1310 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00001311 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001312 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00001313 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001314 };
1315 switch (Opc) {
1316 default:
1317 return UnableToLegalize;
1318 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1319 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001320 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001321 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001322 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001323 return Legalized;
1324 }
1325 case TargetOpcode::G_CTLZ: {
1326 unsigned SrcReg = MI.getOperand(1).getReg();
1327 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001328 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1329 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001330 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
1331 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001332 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1333 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1334 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1335 SrcReg, MIBZero);
1336 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1337 MIBCtlzZU);
1338 MI.eraseFromParent();
1339 return Legalized;
1340 }
1341 // for now, we do this:
1342 // NewLen = NextPowerOf2(Len);
1343 // x = x | (x >> 1);
1344 // x = x | (x >> 2);
1345 // ...
1346 // x = x | (x >>16);
1347 // x = x | (x >>32); // for 64-bit input
1348 // Upto NewLen/2
1349 // return Len - popcount(x);
1350 //
1351 // Ref: "Hacker's Delight" by Henry Warren
1352 unsigned Op = SrcReg;
1353 unsigned NewLen = PowerOf2Ceil(Len);
1354 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1355 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1356 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001357 TargetOpcode::G_OR, {Ty},
1358 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
1359 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001360 Op = MIBOp->getOperand(0).getReg();
1361 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001362 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
1363 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1364 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001365 MI.eraseFromParent();
1366 return Legalized;
1367 }
1368 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1369 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001370 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001371 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001372 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001373 return Legalized;
1374 }
1375 case TargetOpcode::G_CTTZ: {
1376 unsigned SrcReg = MI.getOperand(1).getReg();
1377 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001378 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001379 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1380 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001381 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
1382 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001383 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1384 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1385 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1386 SrcReg, MIBZero);
1387 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1388 MIBCttzZU);
1389 MI.eraseFromParent();
1390 return Legalized;
1391 }
1392 // for now, we use: { return popcount(~x & (x - 1)); }
1393 // unless the target has ctlz but not ctpop, in which case we use:
1394 // { return 32 - nlz(~x & (x-1)); }
1395 // Ref: "Hacker's Delight" by Henry Warren
1396 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
1397 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001398 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001399 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001400 TargetOpcode::G_AND, {Ty},
1401 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
1402 {SrcReg, MIBCstNeg1})});
Diana Picus0528e2c2018-11-26 11:07:02 +00001403 if (!isSupported({TargetOpcode::G_CTPOP, {Ty}}) &&
1404 isSupported({TargetOpcode::G_CTLZ, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001405 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
1406 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001407 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1408 {MIBCstLen,
1409 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001410 MI.eraseFromParent();
1411 return Legalized;
1412 }
1413 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
1414 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
1415 return Legalized;
1416 }
1417 }
1418}