blob: b3fc94cdec603e753b1c4c0c7555f5b2eb29a7af [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Tim Northover69fa84a2016-10-14 22:18:18 +000010/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000011/// individual instructions and the LegalizeMachineIR wrapper pass for the
12/// primary legalization.
13//
14//===----------------------------------------------------------------------===//
15
Tim Northover69fa84a2016-10-14 22:18:18 +000016#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000017#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000018#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000019#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000020#include "llvm/CodeGen/MachineRegisterInfo.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000021#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000022#include "llvm/CodeGen/TargetLowering.h"
23#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000024#include "llvm/Support/Debug.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000025#include "llvm/Support/MathExtras.h"
Tim Northover33b07d62016-07-22 20:03:43 +000026#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000027
Daniel Sanders5377fb32017-04-20 15:46:12 +000028#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000029
30using namespace llvm;
Daniel Sanders9ade5592018-01-29 17:37:29 +000031using namespace LegalizeActions;
Tim Northover33b07d62016-07-22 20:03:43 +000032
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000033LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000034 GISelChangeObserver &Observer,
35 MachineIRBuilder &Builder)
36 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
37 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000038 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000039 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000040}
41
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000042LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000043 GISelChangeObserver &Observer,
44 MachineIRBuilder &B)
45 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000046 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000047 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000048}
Tim Northover69fa84a2016-10-14 22:18:18 +000049LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000050LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000051 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000052
Daniel Sanders262ed0e2018-01-24 17:17:46 +000053 auto Step = LI.getAction(MI, MRI);
54 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000055 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000056 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000057 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000058 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000059 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000060 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000061 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000062 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000063 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000064 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000065 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000066 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000067 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000068 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000069 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000070 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000071 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000072 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000073 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000074 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000075 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
76 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000077 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000078 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000079 return UnableToLegalize;
80 }
81}
82
Tim Northover69fa84a2016-10-14 22:18:18 +000083void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
84 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000085 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000086 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000087 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000088}
89
Tim Northovere0418412017-02-08 23:23:39 +000090static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
91 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000092 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000093 assert((Size == 32 || Size == 64) && "Unsupported size");
94 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +000095 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000096 assert((Size == 32 || Size == 64) && "Unsupported size");
97 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000098 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000099 assert((Size == 32 || Size == 64) && "Unsupported size");
100 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000101 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000102 assert((Size == 32 || Size == 64) && "Unsupported size");
103 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000104 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
105 assert(Size == 32 && "Unsupported size");
106 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000107 case TargetOpcode::G_FADD:
108 assert((Size == 32 || Size == 64) && "Unsupported size");
109 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000110 case TargetOpcode::G_FSUB:
111 assert((Size == 32 || Size == 64) && "Unsupported size");
112 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000113 case TargetOpcode::G_FMUL:
114 assert((Size == 32 || Size == 64) && "Unsupported size");
115 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000116 case TargetOpcode::G_FDIV:
117 assert((Size == 32 || Size == 64) && "Unsupported size");
118 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000119 case TargetOpcode::G_FREM:
120 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
121 case TargetOpcode::G_FPOW:
122 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000123 case TargetOpcode::G_FMA:
124 assert((Size == 32 || Size == 64) && "Unsupported size");
125 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000126 }
127 llvm_unreachable("Unknown libcall function");
128}
129
Diana Picusfc1675e2017-07-05 12:57:24 +0000130LegalizerHelper::LegalizeResult
131llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
132 const CallLowering::ArgInfo &Result,
133 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000134 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
135 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000136 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000137
Diana Picuse97822e2017-04-24 07:22:31 +0000138 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000139 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
140 MachineOperand::CreateES(Name), Result, Args))
141 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000142
Diana Picuse97822e2017-04-24 07:22:31 +0000143 return LegalizerHelper::Legalized;
144}
145
Diana Picus65ed3642018-01-17 13:34:10 +0000146// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000147static LegalizerHelper::LegalizeResult
148simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
149 Type *OpType) {
150 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000151
152 SmallVector<CallLowering::ArgInfo, 3> Args;
153 for (unsigned i = 1; i < MI.getNumOperands(); i++)
154 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000155 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000156 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000157}
158
Diana Picus65ed3642018-01-17 13:34:10 +0000159static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
160 Type *FromType) {
161 auto ToMVT = MVT::getVT(ToType);
162 auto FromMVT = MVT::getVT(FromType);
163
164 switch (Opcode) {
165 case TargetOpcode::G_FPEXT:
166 return RTLIB::getFPEXT(FromMVT, ToMVT);
167 case TargetOpcode::G_FPTRUNC:
168 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000169 case TargetOpcode::G_FPTOSI:
170 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
171 case TargetOpcode::G_FPTOUI:
172 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000173 case TargetOpcode::G_SITOFP:
174 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
175 case TargetOpcode::G_UITOFP:
176 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000177 }
178 llvm_unreachable("Unsupported libcall function");
179}
180
181static LegalizerHelper::LegalizeResult
182conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
183 Type *FromType) {
184 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
185 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
186 {{MI.getOperand(1).getReg(), FromType}});
187}
188
Tim Northover69fa84a2016-10-14 22:18:18 +0000189LegalizerHelper::LegalizeResult
190LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000191 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
192 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000193 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000194
Diana Picusfc1675e2017-07-05 12:57:24 +0000195 MIRBuilder.setInstr(MI);
196
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000197 switch (MI.getOpcode()) {
198 default:
199 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000200 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000201 case TargetOpcode::G_UDIV:
202 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000203 case TargetOpcode::G_UREM:
204 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000205 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000206 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
207 if (Status != Legalized)
208 return Status;
209 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000210 }
Diana Picus1314a282017-04-11 10:52:34 +0000211 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000212 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000213 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000214 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000215 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000216 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000217 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000218 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000219 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
220 if (Status != Legalized)
221 return Status;
222 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000223 }
Diana Picus65ed3642018-01-17 13:34:10 +0000224 case TargetOpcode::G_FPEXT: {
225 // FIXME: Support other floating point types (half, fp128 etc)
226 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
227 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
228 if (ToSize != 64 || FromSize != 32)
229 return UnableToLegalize;
230 LegalizeResult Status = conversionLibcall(
231 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
232 if (Status != Legalized)
233 return Status;
234 break;
235 }
236 case TargetOpcode::G_FPTRUNC: {
237 // FIXME: Support other floating point types (half, fp128 etc)
238 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
239 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
240 if (ToSize != 32 || FromSize != 64)
241 return UnableToLegalize;
242 LegalizeResult Status = conversionLibcall(
243 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
244 if (Status != Legalized)
245 return Status;
246 break;
247 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000248 case TargetOpcode::G_FPTOSI:
249 case TargetOpcode::G_FPTOUI: {
250 // FIXME: Support other types
251 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
252 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
253 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
254 return UnableToLegalize;
255 LegalizeResult Status = conversionLibcall(
256 MI, MIRBuilder, Type::getInt32Ty(Ctx),
257 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
258 if (Status != Legalized)
259 return Status;
260 break;
261 }
Diana Picus517531e2018-01-30 09:15:17 +0000262 case TargetOpcode::G_SITOFP:
263 case TargetOpcode::G_UITOFP: {
264 // FIXME: Support other types
265 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
266 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
267 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
268 return UnableToLegalize;
269 LegalizeResult Status = conversionLibcall(
270 MI, MIRBuilder,
271 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
272 Type::getInt32Ty(Ctx));
273 if (Status != Legalized)
274 return Status;
275 break;
276 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000277 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000278
279 MI.eraseFromParent();
280 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000281}
282
Tim Northover69fa84a2016-10-14 22:18:18 +0000283LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
284 unsigned TypeIdx,
285 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000286 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000287 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000288 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000289
290 MIRBuilder.setInstr(MI);
291
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000292 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
293 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000294
Tim Northover9656f142016-08-04 20:54:13 +0000295 switch (MI.getOpcode()) {
296 default:
297 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000298 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000299 // FIXME: add support for when SizeOp0 isn't an exact multiple of
300 // NarrowSize.
301 if (SizeOp0 % NarrowSize != 0)
302 return UnableToLegalize;
303 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000304
305 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000306 for (int i = 0; i < NumParts; ++i)
307 DstRegs.push_back(
308 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000309
310 unsigned DstReg = MI.getOperand(0).getReg();
311 if(MRI.getType(DstReg).isVector())
312 MIRBuilder.buildBuildVector(DstReg, DstRegs);
313 else
314 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000315 MI.eraseFromParent();
316 return Legalized;
317 }
Tim Northover9656f142016-08-04 20:54:13 +0000318 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000319 // FIXME: add support for when SizeOp0 isn't an exact multiple of
320 // NarrowSize.
321 if (SizeOp0 % NarrowSize != 0)
322 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000323 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000324 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000325
Tim Northoverb18ea162016-09-20 15:20:36 +0000326 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000327 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
328 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
329
Tim Northover0f140c72016-09-09 11:46:34 +0000330 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
331 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000332
333 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000334 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
335 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000336
Tim Northover0f140c72016-09-09 11:46:34 +0000337 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000338 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000339
340 DstRegs.push_back(DstReg);
341 CarryIn = CarryOut;
342 }
Tim Northover0f140c72016-09-09 11:46:34 +0000343 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000344 if(MRI.getType(DstReg).isVector())
345 MIRBuilder.buildBuildVector(DstReg, DstRegs);
346 else
347 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000348 MI.eraseFromParent();
349 return Legalized;
350 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000351 case TargetOpcode::G_EXTRACT: {
352 if (TypeIdx != 1)
353 return UnableToLegalize;
354
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000355 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
356 // FIXME: add support for when SizeOp1 isn't an exact multiple of
357 // NarrowSize.
358 if (SizeOp1 % NarrowSize != 0)
359 return UnableToLegalize;
360 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000361
362 SmallVector<unsigned, 2> SrcRegs, DstRegs;
363 SmallVector<uint64_t, 2> Indexes;
364 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
365
366 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000367 uint64_t OpStart = MI.getOperand(2).getImm();
368 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000369 for (int i = 0; i < NumParts; ++i) {
370 unsigned SrcStart = i * NarrowSize;
371
372 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
373 // No part of the extract uses this subregister, ignore it.
374 continue;
375 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
376 // The entire subregister is extracted, forward the value.
377 DstRegs.push_back(SrcRegs[i]);
378 continue;
379 }
380
381 // OpSegStart is where this destination segment would start in OpReg if it
382 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000383 int64_t ExtractOffset;
384 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000385 if (OpStart < SrcStart) {
386 ExtractOffset = 0;
387 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
388 } else {
389 ExtractOffset = OpStart - SrcStart;
390 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
391 }
392
393 unsigned SegReg = SrcRegs[i];
394 if (ExtractOffset != 0 || SegSize != NarrowSize) {
395 // A genuine extract is needed.
396 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
397 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
398 }
399
400 DstRegs.push_back(SegReg);
401 }
402
Amara Emerson5ec14602018-12-10 18:44:58 +0000403 unsigned DstReg = MI.getOperand(0).getReg();
404 if(MRI.getType(DstReg).isVector())
405 MIRBuilder.buildBuildVector(DstReg, DstRegs);
406 else
407 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000408 MI.eraseFromParent();
409 return Legalized;
410 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000411 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000412 // FIXME: add support for when SizeOp0 isn't an exact multiple of
413 // NarrowSize.
414 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000415 return UnableToLegalize;
416
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000417 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000418
419 SmallVector<unsigned, 2> SrcRegs, DstRegs;
420 SmallVector<uint64_t, 2> Indexes;
421 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
422
Tim Northover75e0b912017-03-06 18:23:04 +0000423 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000424 uint64_t OpStart = MI.getOperand(3).getImm();
425 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000426 for (int i = 0; i < NumParts; ++i) {
427 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000428
Tim Northover75e0b912017-03-06 18:23:04 +0000429 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000430 // No part of the insert affects this subregister, forward the original.
431 DstRegs.push_back(SrcRegs[i]);
432 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000433 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000434 // The entire subregister is defined by this insert, forward the new
435 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000436 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000437 continue;
438 }
439
Tim Northover2eb18d32017-03-07 21:24:33 +0000440 // OpSegStart is where this destination segment would start in OpReg if it
441 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000442 int64_t ExtractOffset, InsertOffset;
443 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000444 if (OpStart < DstStart) {
445 InsertOffset = 0;
446 ExtractOffset = DstStart - OpStart;
447 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
448 } else {
449 InsertOffset = OpStart - DstStart;
450 ExtractOffset = 0;
451 SegSize =
452 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
453 }
454
455 unsigned SegReg = OpReg;
456 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000457 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000458 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
459 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000460 }
461
Tim Northover75e0b912017-03-06 18:23:04 +0000462 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000463 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000464 DstRegs.push_back(DstReg);
465 }
466
467 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000468 unsigned DstReg = MI.getOperand(0).getReg();
469 if(MRI.getType(DstReg).isVector())
470 MIRBuilder.buildBuildVector(DstReg, DstRegs);
471 else
472 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000473 MI.eraseFromParent();
474 return Legalized;
475 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000476 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000477 // FIXME: add support for when SizeOp0 isn't an exact multiple of
478 // NarrowSize.
479 if (SizeOp0 % NarrowSize != 0)
480 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000481
482 const auto &MMO = **MI.memoperands_begin();
483 // This implementation doesn't work for atomics. Give up instead of doing
484 // something invalid.
485 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
486 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
487 return UnableToLegalize;
488
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000489 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000490 LLT OffsetTy = LLT::scalar(
491 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000492
493 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000494 for (int i = 0; i < NumParts; ++i) {
495 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000496 unsigned SrcReg = 0;
497 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000498 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000499
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000500 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
501 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000502 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
503 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000504
Daniel Sanders4e523662017-06-13 23:42:32 +0000505 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
506 Adjustment);
507
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000508 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000509
510 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000511 }
512 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000513 if(MRI.getType(DstReg).isVector())
514 MIRBuilder.buildBuildVector(DstReg, DstRegs);
515 else
516 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000517 MI.eraseFromParent();
518 return Legalized;
519 }
Justin Bognerfde01042017-01-18 17:29:54 +0000520 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000521 // FIXME: add support for when SizeOp0 isn't an exact multiple of
522 // NarrowSize.
523 if (SizeOp0 % NarrowSize != 0)
524 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000525
526 const auto &MMO = **MI.memoperands_begin();
527 // This implementation doesn't work for atomics. Give up instead of doing
528 // something invalid.
529 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
530 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
531 return UnableToLegalize;
532
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000533 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000534 LLT OffsetTy = LLT::scalar(
535 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000536
537 SmallVector<unsigned, 2> SrcRegs;
538 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
539
540 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000541 unsigned DstReg = 0;
542 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000543 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Daniel Sanders4e523662017-06-13 23:42:32 +0000544
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000545 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
546 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000547 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
548 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000549
Daniel Sanders4e523662017-06-13 23:42:32 +0000550 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
551 Adjustment);
552
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000553 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000554 }
555 MI.eraseFromParent();
556 return Legalized;
557 }
Igor Breger29537882017-04-07 14:41:59 +0000558 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000559 // FIXME: add support for when SizeOp0 isn't an exact multiple of
560 // NarrowSize.
561 if (SizeOp0 % NarrowSize != 0)
562 return UnableToLegalize;
563 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000564 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000565 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000566
567 SmallVector<unsigned, 2> DstRegs;
568 for (int i = 0; i < NumParts; ++i) {
569 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
570 ConstantInt *CI =
571 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
572 MIRBuilder.buildConstant(DstReg, *CI);
573 DstRegs.push_back(DstReg);
574 }
575 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000576 if(MRI.getType(DstReg).isVector())
577 MIRBuilder.buildBuildVector(DstReg, DstRegs);
578 else
579 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000580 MI.eraseFromParent();
581 return Legalized;
582 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000583 case TargetOpcode::G_AND:
584 case TargetOpcode::G_OR:
585 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000586 // Legalize bitwise operation:
587 // A = BinOp<Ty> B, C
588 // into:
589 // B1, ..., BN = G_UNMERGE_VALUES B
590 // C1, ..., CN = G_UNMERGE_VALUES C
591 // A1 = BinOp<Ty/N> B1, C2
592 // ...
593 // AN = BinOp<Ty/N> BN, CN
594 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000595
596 // FIXME: add support for when SizeOp0 isn't an exact multiple of
597 // NarrowSize.
598 if (SizeOp0 % NarrowSize != 0)
599 return UnableToLegalize;
600 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000601
602 // List the registers where the destination will be scattered.
603 SmallVector<unsigned, 2> DstRegs;
604 // List the registers where the first argument will be split.
605 SmallVector<unsigned, 2> SrcsReg1;
606 // List the registers where the second argument will be split.
607 SmallVector<unsigned, 2> SrcsReg2;
608 // Create all the temporary registers.
609 for (int i = 0; i < NumParts; ++i) {
610 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
611 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
612 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
613
614 DstRegs.push_back(DstReg);
615 SrcsReg1.push_back(SrcReg1);
616 SrcsReg2.push_back(SrcReg2);
617 }
618 // Explode the big arguments into smaller chunks.
619 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
620 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
621
622 // Do the operation on each small part.
623 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000624 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
625 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000626
627 // Gather the destination registers into the final destination.
628 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000629 if(MRI.getType(DstReg).isVector())
630 MIRBuilder.buildBuildVector(DstReg, DstRegs);
631 else
632 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000633 MI.eraseFromParent();
634 return Legalized;
635 }
Tim Northover9656f142016-08-04 20:54:13 +0000636 }
Tim Northover33b07d62016-07-22 20:03:43 +0000637}
638
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000639void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
640 unsigned OpIdx, unsigned ExtOpcode) {
641 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000642 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000643 MO.setReg(ExtB->getOperand(0).getReg());
644}
645
646void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
647 unsigned OpIdx, unsigned TruncOpcode) {
648 MachineOperand &MO = MI.getOperand(OpIdx);
649 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
650 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000651 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000652 MO.setReg(DstExt);
653}
654
Tim Northover69fa84a2016-10-14 22:18:18 +0000655LegalizerHelper::LegalizeResult
656LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000657 MIRBuilder.setInstr(MI);
658
Tim Northover32335812016-08-04 18:35:11 +0000659 switch (MI.getOpcode()) {
660 default:
661 return UnableToLegalize;
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000662 case TargetOpcode::G_UADDO:
663 case TargetOpcode::G_USUBO: {
664 if (TypeIdx == 1)
665 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000666 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
667 {MI.getOperand(2).getReg()});
668 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
669 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000670 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
671 ? TargetOpcode::G_ADD
672 : TargetOpcode::G_SUB;
673 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000674 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000675 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
676 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
677 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000678 TargetOpcode::G_AND, {WideTy},
679 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000680 // There is no overflow if the AndOp is the same as NewOp.
681 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
682 AndOp);
683 // Now trunc the NewOp to the original result.
684 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
685 MI.eraseFromParent();
686 return Legalized;
687 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000688 case TargetOpcode::G_CTTZ:
689 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
690 case TargetOpcode::G_CTLZ:
691 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
692 case TargetOpcode::G_CTPOP: {
693 // First ZEXT the input.
694 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
695 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
696 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
697 // The count is the same in the larger type except if the original
698 // value was zero. This can be handled by setting the bit just off
699 // the top of the original type.
700 auto TopBit =
701 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
702 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000703 TargetOpcode::G_OR, {WideTy},
704 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000705 }
706 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000707 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000708 // This is already the correct result for CTPOP and CTTZs
709 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
710 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
711 // The correct result is NewOp - (Difference in widety and current ty).
712 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000713 MIBNewOp = MIRBuilder.buildInstr(
714 TargetOpcode::G_SUB, {WideTy},
715 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000716 }
717 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +0000718 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000719 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000720 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
721 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000722 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000723 return Legalized;
724 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000725
Tim Northover61c16142016-08-04 21:39:49 +0000726 case TargetOpcode::G_ADD:
727 case TargetOpcode::G_AND:
728 case TargetOpcode::G_MUL:
729 case TargetOpcode::G_OR:
730 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000731 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000732 // Perform operation at larger width (any extension is fine here, high bits
733 // don't affect the result) and then truncate the result back to the
734 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000735 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000736 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
737 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
738 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000739 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000740 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000741
Roman Tereshin6d266382018-05-09 21:43:30 +0000742 case TargetOpcode::G_SHL:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000743 Observer.changingInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000744 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
745 // The "number of bits to shift" operand must preserve its value as an
746 // unsigned integer:
747 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
748 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000749 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000750 return Legalized;
751
Tim Northover7a753d92016-08-26 17:46:06 +0000752 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000753 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000754 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000755 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
756 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
757 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000758 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000759 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000760
Roman Tereshin6d266382018-05-09 21:43:30 +0000761 case TargetOpcode::G_ASHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000762 Observer.changingInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000763 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
764 // The "number of bits to shift" operand must preserve its value as an
765 // unsigned integer:
766 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
767 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000768 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000769 return Legalized;
770
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000771 case TargetOpcode::G_UDIV:
772 case TargetOpcode::G_UREM:
773 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000774 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000775 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
776 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
777 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000778 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000779 return Legalized;
780
781 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000782 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +0000783 if (TypeIdx == 0) {
784 // Perform operation at larger width (any extension is fine here, high
785 // bits don't affect the result) and then truncate the result back to the
786 // original type.
787 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
788 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
789 widenScalarDst(MI, WideTy);
790 } else {
791 // Explicit extension is required here since high bits affect the result.
792 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
793 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000794 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000795 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000796
Ahmed Bougachab6137062017-01-23 21:10:14 +0000797 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000798 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +0000799 if (TypeIdx != 0)
800 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000801 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000802 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000803 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000804 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000805
Ahmed Bougachad2948232017-01-20 01:37:24 +0000806 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +0000807 if (TypeIdx != 1)
808 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000809 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000810 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000811 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000812 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000813
814 case TargetOpcode::G_UITOFP:
815 if (TypeIdx != 1)
816 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000817 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000818 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000819 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000820 return Legalized;
821
822 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +0000823 if (TypeIdx != 0)
824 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000825 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000826 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
827 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000828 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000829 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000830
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000831 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +0000832 // For some types like i24, we might try to widen to i32. To properly handle
833 // this we should be using a dedicated extending load, until then avoid
834 // trying to legalize.
835 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
836 WideTy.getSizeInBits())
837 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000838 LLVM_FALLTHROUGH;
839 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000840 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000841 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000842 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000843 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000844 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000845
Tim Northover3c73e362016-08-23 18:20:09 +0000846 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000847 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
848 WideTy != LLT::scalar(8))
849 return UnableToLegalize;
850
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000851 Observer.changingInstr(MI);
Amara Emerson5a3bb682018-06-01 13:20:32 +0000852 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000853 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000854 return Legalized;
855 }
Tim Northoverea904f92016-08-19 22:40:00 +0000856 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000857 MachineOperand &SrcMO = MI.getOperand(1);
858 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
859 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000860 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000861 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
862
863 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000864 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +0000865 return Legalized;
866 }
Tim Northovera11be042016-08-19 22:40:08 +0000867 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000868 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +0000869 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000870 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +0000871 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000872 switch (WideTy.getSizeInBits()) {
873 case 32:
874 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
875 break;
876 case 64:
877 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
878 break;
879 default:
880 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +0000881 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000882 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000883 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
884
885 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000886 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +0000887 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +0000888 }
Matt Arsenaultbefee402019-01-09 07:34:14 +0000889 case TargetOpcode::G_IMPLICIT_DEF: {
890 Observer.changingInstr(MI);
891 widenScalarDst(MI, WideTy);
892 Observer.changedInstr(MI);
893 return Legalized;
894 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000895 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000896 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000897 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000898 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000899 return Legalized;
900
901 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000902 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000903 if (TypeIdx == 0)
904 widenScalarDst(MI, WideTy);
905 else {
906 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
907 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +0000908 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000909 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000910 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000911
912 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000913 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000914 if (TypeIdx == 0)
915 widenScalarDst(MI, WideTy);
916 else {
917 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
918 MI.getOperand(1).getPredicate()))
919 ? TargetOpcode::G_SEXT
920 : TargetOpcode::G_ZEXT;
921 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
922 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
923 }
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_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +0000928 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000929 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000930 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000931 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +0000932 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000933
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000934 case TargetOpcode::G_PHI: {
935 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000936
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000937 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000938 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
939 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
940 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
941 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000942 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000943
944 MachineBasicBlock &MBB = *MI.getParent();
945 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
946 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000947 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000948 return Legalized;
949 }
Amara Emersoncbd86d82018-10-25 14:04:54 +0000950 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
951 if (TypeIdx != 2)
952 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000953 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +0000954 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000955 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +0000956 return Legalized;
Jessica Paquette453ab1d2018-12-21 17:05:26 +0000957
958 case TargetOpcode::G_FCEIL:
959 if (TypeIdx != 0)
960 return UnableToLegalize;
961 Observer.changingInstr(MI);
962 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_FPEXT);
963 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
964 Observer.changedInstr(MI);
965 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +0000966 }
Tim Northover33b07d62016-07-22 20:03:43 +0000967}
968
Tim Northover69fa84a2016-10-14 22:18:18 +0000969LegalizerHelper::LegalizeResult
970LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000971 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000972 MIRBuilder.setInstr(MI);
973
974 switch(MI.getOpcode()) {
975 default:
976 return UnableToLegalize;
977 case TargetOpcode::G_SREM:
978 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000979 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
980 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000981 .addDef(QuotReg)
982 .addUse(MI.getOperand(1).getReg())
983 .addUse(MI.getOperand(2).getReg());
984
Tim Northover0f140c72016-09-09 11:46:34 +0000985 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
986 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
987 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
988 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000989 MI.eraseFromParent();
990 return Legalized;
991 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000992 case TargetOpcode::G_SMULO:
993 case TargetOpcode::G_UMULO: {
994 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
995 // result.
996 unsigned Res = MI.getOperand(0).getReg();
997 unsigned Overflow = MI.getOperand(1).getReg();
998 unsigned LHS = MI.getOperand(2).getReg();
999 unsigned RHS = MI.getOperand(3).getReg();
1000
1001 MIRBuilder.buildMul(Res, LHS, RHS);
1002
1003 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1004 ? TargetOpcode::G_SMULH
1005 : TargetOpcode::G_UMULH;
1006
1007 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1008 MIRBuilder.buildInstr(Opcode)
1009 .addDef(HiPart)
1010 .addUse(LHS)
1011 .addUse(RHS);
1012
1013 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1014 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001015
1016 // For *signed* multiply, overflow is detected by checking:
1017 // (hi != (lo >> bitwidth-1))
1018 if (Opcode == TargetOpcode::G_SMULH) {
1019 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1020 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1021 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1022 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1023 .addDef(Shifted)
1024 .addUse(Res)
1025 .addUse(ShiftAmt);
1026 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1027 } else {
1028 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1029 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001030 MI.eraseFromParent();
1031 return Legalized;
1032 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001033 case TargetOpcode::G_FNEG: {
1034 // TODO: Handle vector types once we are able to
1035 // represent them.
1036 if (Ty.isVector())
1037 return UnableToLegalize;
1038 unsigned Res = MI.getOperand(0).getReg();
1039 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001040 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001041 switch (Ty.getSizeInBits()) {
1042 case 16:
1043 ZeroTy = Type::getHalfTy(Ctx);
1044 break;
1045 case 32:
1046 ZeroTy = Type::getFloatTy(Ctx);
1047 break;
1048 case 64:
1049 ZeroTy = Type::getDoubleTy(Ctx);
1050 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001051 case 128:
1052 ZeroTy = Type::getFP128Ty(Ctx);
1053 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001054 default:
1055 llvm_unreachable("unexpected floating-point type");
1056 }
1057 ConstantFP &ZeroForNegation =
1058 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001059 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001060 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1061 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001062 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001063 .addUse(MI.getOperand(1).getReg());
1064 MI.eraseFromParent();
1065 return Legalized;
1066 }
Volkan Keles225921a2017-03-10 21:25:09 +00001067 case TargetOpcode::G_FSUB: {
1068 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1069 // First, check if G_FNEG is marked as Lower. If so, we may
1070 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001071 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001072 return UnableToLegalize;
1073 unsigned Res = MI.getOperand(0).getReg();
1074 unsigned LHS = MI.getOperand(1).getReg();
1075 unsigned RHS = MI.getOperand(2).getReg();
1076 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1077 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1078 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1079 .addDef(Res)
1080 .addUse(LHS)
1081 .addUse(Neg);
1082 MI.eraseFromParent();
1083 return Legalized;
1084 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001085 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1086 unsigned OldValRes = MI.getOperand(0).getReg();
1087 unsigned SuccessRes = MI.getOperand(1).getReg();
1088 unsigned Addr = MI.getOperand(2).getReg();
1089 unsigned CmpVal = MI.getOperand(3).getReg();
1090 unsigned NewVal = MI.getOperand(4).getReg();
1091 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1092 **MI.memoperands_begin());
1093 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1094 MI.eraseFromParent();
1095 return Legalized;
1096 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001097 case TargetOpcode::G_LOAD:
1098 case TargetOpcode::G_SEXTLOAD:
1099 case TargetOpcode::G_ZEXTLOAD: {
1100 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1101 unsigned DstReg = MI.getOperand(0).getReg();
1102 unsigned PtrReg = MI.getOperand(1).getReg();
1103 LLT DstTy = MRI.getType(DstReg);
1104 auto &MMO = **MI.memoperands_begin();
1105
1106 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001107 // In the case of G_LOAD, this was a non-extending load already and we're
1108 // about to lower to the same instruction.
1109 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1110 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001111 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1112 MI.eraseFromParent();
1113 return Legalized;
1114 }
1115
1116 if (DstTy.isScalar()) {
1117 unsigned TmpReg = MRI.createGenericVirtualRegister(
1118 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1119 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1120 switch (MI.getOpcode()) {
1121 default:
1122 llvm_unreachable("Unexpected opcode");
1123 case TargetOpcode::G_LOAD:
1124 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1125 break;
1126 case TargetOpcode::G_SEXTLOAD:
1127 MIRBuilder.buildSExt(DstReg, TmpReg);
1128 break;
1129 case TargetOpcode::G_ZEXTLOAD:
1130 MIRBuilder.buildZExt(DstReg, TmpReg);
1131 break;
1132 }
1133 MI.eraseFromParent();
1134 return Legalized;
1135 }
1136
1137 return UnableToLegalize;
1138 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001139 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1140 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1141 case TargetOpcode::G_CTLZ:
1142 case TargetOpcode::G_CTTZ:
1143 case TargetOpcode::G_CTPOP:
1144 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001145 case G_UADDE: {
1146 unsigned Res = MI.getOperand(0).getReg();
1147 unsigned CarryOut = MI.getOperand(1).getReg();
1148 unsigned LHS = MI.getOperand(2).getReg();
1149 unsigned RHS = MI.getOperand(3).getReg();
1150 unsigned CarryIn = MI.getOperand(4).getReg();
1151
1152 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1153 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1154
1155 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1156 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1157 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1158 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1159
1160 MI.eraseFromParent();
1161 return Legalized;
1162 }
Tim Northovercecee562016-08-26 17:46:13 +00001163 }
1164}
1165
Tim Northover69fa84a2016-10-14 22:18:18 +00001166LegalizerHelper::LegalizeResult
1167LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1168 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +00001169 // FIXME: Don't know how to handle secondary types yet.
1170 if (TypeIdx != 0)
1171 return UnableToLegalize;
Volkan Keles574d7372018-12-14 22:11:20 +00001172
1173 MIRBuilder.setInstr(MI);
Tim Northover33b07d62016-07-22 20:03:43 +00001174 switch (MI.getOpcode()) {
1175 default:
1176 return UnableToLegalize;
Matt Arsenault3dddb162019-01-09 07:51:52 +00001177 case TargetOpcode::G_IMPLICIT_DEF: {
1178 SmallVector<unsigned, 2> DstRegs;
1179
1180 unsigned NarrowSize = NarrowTy.getSizeInBits();
1181 unsigned DstReg = MI.getOperand(0).getReg();
1182 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1183 int NumParts = Size / NarrowSize;
1184 // FIXME: Don't know how to handle the situation where the small vectors
1185 // aren't all the same size yet.
1186 if (Size % NarrowSize != 0)
1187 return UnableToLegalize;
1188
1189 for (int i = 0; i < NumParts; ++i) {
1190 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1191 MIRBuilder.buildUndef(TmpReg);
1192 DstRegs.push_back(TmpReg);
1193 }
1194
1195 if (NarrowTy.isVector())
1196 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1197 else
1198 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1199
1200 MI.eraseFromParent();
1201 return Legalized;
1202 }
Tim Northover33b07d62016-07-22 20:03:43 +00001203 case TargetOpcode::G_ADD: {
1204 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +00001205 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +00001206 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1207 int NumParts = Size / NarrowSize;
1208 // FIXME: Don't know how to handle the situation where the small vectors
1209 // aren't all the same size yet.
1210 if (Size % NarrowSize != 0)
1211 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001212
Tim Northoverb18ea162016-09-20 15:20:36 +00001213 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +00001214 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
1215 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
1216
1217 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +00001218 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1219 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +00001220 DstRegs.push_back(DstReg);
1221 }
1222
Amara Emerson5ec14602018-12-10 18:44:58 +00001223 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +00001224 MI.eraseFromParent();
1225 return Legalized;
1226 }
Volkan Keles574d7372018-12-14 22:11:20 +00001227 case TargetOpcode::G_LOAD:
1228 case TargetOpcode::G_STORE: {
1229 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1230 unsigned ValReg = MI.getOperand(0).getReg();
1231 unsigned AddrReg = MI.getOperand(1).getReg();
1232 unsigned NarrowSize = NarrowTy.getSizeInBits();
1233 unsigned Size = MRI.getType(ValReg).getSizeInBits();
1234 unsigned NumParts = Size / NarrowSize;
1235
1236 SmallVector<unsigned, 8> NarrowRegs;
1237 if (!IsLoad)
1238 extractParts(ValReg, NarrowTy, NumParts, NarrowRegs);
1239
1240 const LLT OffsetTy =
1241 LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1242 MachineFunction &MF = *MI.getMF();
1243 MachineMemOperand *MMO = *MI.memoperands_begin();
1244 for (unsigned Idx = 0; Idx < NumParts; ++Idx) {
1245 unsigned Adjustment = Idx * NarrowTy.getSizeInBits() / 8;
1246 unsigned Alignment = MinAlign(MMO->getAlignment(), Adjustment);
1247 unsigned NewAddrReg = 0;
1248 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, Adjustment);
1249 MachineMemOperand &NewMMO = *MF.getMachineMemOperand(
1250 MMO->getPointerInfo().getWithOffset(Adjustment), MMO->getFlags(),
1251 NarrowTy.getSizeInBits() / 8, Alignment);
1252 if (IsLoad) {
1253 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
1254 NarrowRegs.push_back(Dst);
1255 MIRBuilder.buildLoad(Dst, NewAddrReg, NewMMO);
1256 } else {
1257 MIRBuilder.buildStore(NarrowRegs[Idx], NewAddrReg, NewMMO);
1258 }
1259 }
1260 if (IsLoad) {
1261 if (NarrowTy.isVector())
1262 MIRBuilder.buildConcatVectors(ValReg, NarrowRegs);
1263 else
1264 MIRBuilder.buildBuildVector(ValReg, NarrowRegs);
1265 }
1266 MI.eraseFromParent();
1267 return Legalized;
1268 }
Tim Northover33b07d62016-07-22 20:03:43 +00001269 }
1270}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001271
1272LegalizerHelper::LegalizeResult
1273LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1274 unsigned Opc = MI.getOpcode();
1275 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00001276 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001277 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00001278 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001279 };
1280 switch (Opc) {
1281 default:
1282 return UnableToLegalize;
1283 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1284 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001285 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001286 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001287 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001288 return Legalized;
1289 }
1290 case TargetOpcode::G_CTLZ: {
1291 unsigned SrcReg = MI.getOperand(1).getReg();
1292 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001293 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1294 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001295 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
1296 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001297 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1298 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1299 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1300 SrcReg, MIBZero);
1301 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1302 MIBCtlzZU);
1303 MI.eraseFromParent();
1304 return Legalized;
1305 }
1306 // for now, we do this:
1307 // NewLen = NextPowerOf2(Len);
1308 // x = x | (x >> 1);
1309 // x = x | (x >> 2);
1310 // ...
1311 // x = x | (x >>16);
1312 // x = x | (x >>32); // for 64-bit input
1313 // Upto NewLen/2
1314 // return Len - popcount(x);
1315 //
1316 // Ref: "Hacker's Delight" by Henry Warren
1317 unsigned Op = SrcReg;
1318 unsigned NewLen = PowerOf2Ceil(Len);
1319 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1320 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1321 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001322 TargetOpcode::G_OR, {Ty},
1323 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
1324 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001325 Op = MIBOp->getOperand(0).getReg();
1326 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001327 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
1328 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1329 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001330 MI.eraseFromParent();
1331 return Legalized;
1332 }
1333 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1334 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001335 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001336 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001337 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001338 return Legalized;
1339 }
1340 case TargetOpcode::G_CTTZ: {
1341 unsigned SrcReg = MI.getOperand(1).getReg();
1342 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001343 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001344 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1345 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001346 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
1347 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001348 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1349 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1350 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1351 SrcReg, MIBZero);
1352 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1353 MIBCttzZU);
1354 MI.eraseFromParent();
1355 return Legalized;
1356 }
1357 // for now, we use: { return popcount(~x & (x - 1)); }
1358 // unless the target has ctlz but not ctpop, in which case we use:
1359 // { return 32 - nlz(~x & (x-1)); }
1360 // Ref: "Hacker's Delight" by Henry Warren
1361 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
1362 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001363 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001364 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001365 TargetOpcode::G_AND, {Ty},
1366 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
1367 {SrcReg, MIBCstNeg1})});
Diana Picus0528e2c2018-11-26 11:07:02 +00001368 if (!isSupported({TargetOpcode::G_CTPOP, {Ty}}) &&
1369 isSupported({TargetOpcode::G_CTLZ, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001370 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
1371 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001372 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1373 {MIBCstLen,
1374 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001375 MI.eraseFromParent();
1376 return Legalized;
1377 }
1378 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
1379 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
1380 return Legalized;
1381 }
1382 }
1383}