blob: ff2e61c03b47e03c50e237347737d30be153dee7 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Tim Northover69fa84a2016-10-14 22:18:18 +000010/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000011/// individual instructions and the LegalizeMachineIR wrapper pass for the
12/// primary legalization.
13//
14//===----------------------------------------------------------------------===//
15
Tim Northover69fa84a2016-10-14 22:18:18 +000016#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000017#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000018#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
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
Tim Northover69fa84a2016-10-14 22:18:18 +000032LegalizerHelper::LegalizerHelper(MachineFunction &MF)
Volkan Keles685fbda2017-03-10 18:34:57 +000033 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
Tim Northover33b07d62016-07-22 20:03:43 +000034 MIRBuilder.setMF(MF);
35}
36
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000037LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI)
38 : MRI(MF.getRegInfo()), LI(LI) {
39 MIRBuilder.setMF(MF);
40}
Tim Northover69fa84a2016-10-14 22:18:18 +000041LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000042LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000043 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000044
Daniel Sanders262ed0e2018-01-24 17:17:46 +000045 auto Step = LI.getAction(MI, MRI);
46 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000047 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000048 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000049 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000050 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000051 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000052 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000053 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000054 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000055 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000056 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000057 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000058 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000059 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000060 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000061 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000062 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000063 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000064 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000065 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000066 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Volkan Keles685fbda2017-03-10 18:34:57 +000067 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
68 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000069 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000070 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000071 return UnableToLegalize;
72 }
73}
74
Tim Northover69fa84a2016-10-14 22:18:18 +000075void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
76 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000077 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000078 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000079 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000080}
81
Tim Northovere0418412017-02-08 23:23:39 +000082static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
83 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000084 case TargetOpcode::G_SDIV:
85 assert(Size == 32 && "Unsupported size");
86 return RTLIB::SDIV_I32;
87 case TargetOpcode::G_UDIV:
88 assert(Size == 32 && "Unsupported size");
89 return RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000090 case TargetOpcode::G_SREM:
91 assert(Size == 32 && "Unsupported size");
92 return RTLIB::SREM_I32;
93 case TargetOpcode::G_UREM:
94 assert(Size == 32 && "Unsupported size");
95 return RTLIB::UREM_I32;
Diana Picus1314a282017-04-11 10:52:34 +000096 case TargetOpcode::G_FADD:
97 assert((Size == 32 || Size == 64) && "Unsupported size");
98 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +000099 case TargetOpcode::G_FSUB:
100 assert((Size == 32 || Size == 64) && "Unsupported size");
101 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000102 case TargetOpcode::G_FMUL:
103 assert((Size == 32 || Size == 64) && "Unsupported size");
104 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000105 case TargetOpcode::G_FDIV:
106 assert((Size == 32 || Size == 64) && "Unsupported size");
107 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000108 case TargetOpcode::G_FREM:
109 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
110 case TargetOpcode::G_FPOW:
111 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000112 case TargetOpcode::G_FMA:
113 assert((Size == 32 || Size == 64) && "Unsupported size");
114 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000115 }
116 llvm_unreachable("Unknown libcall function");
117}
118
Diana Picusfc1675e2017-07-05 12:57:24 +0000119LegalizerHelper::LegalizeResult
120llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
121 const CallLowering::ArgInfo &Result,
122 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000123 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
124 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000125 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000126
Diana Picuse97822e2017-04-24 07:22:31 +0000127 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000128 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
129 MachineOperand::CreateES(Name), Result, Args))
130 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000131
Diana Picuse97822e2017-04-24 07:22:31 +0000132 return LegalizerHelper::Legalized;
133}
134
Diana Picus65ed3642018-01-17 13:34:10 +0000135// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000136static LegalizerHelper::LegalizeResult
137simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
138 Type *OpType) {
139 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000140
141 SmallVector<CallLowering::ArgInfo, 3> Args;
142 for (unsigned i = 1; i < MI.getNumOperands(); i++)
143 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000144 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000145 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000146}
147
Diana Picus65ed3642018-01-17 13:34:10 +0000148static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
149 Type *FromType) {
150 auto ToMVT = MVT::getVT(ToType);
151 auto FromMVT = MVT::getVT(FromType);
152
153 switch (Opcode) {
154 case TargetOpcode::G_FPEXT:
155 return RTLIB::getFPEXT(FromMVT, ToMVT);
156 case TargetOpcode::G_FPTRUNC:
157 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000158 case TargetOpcode::G_FPTOSI:
159 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
160 case TargetOpcode::G_FPTOUI:
161 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000162 case TargetOpcode::G_SITOFP:
163 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
164 case TargetOpcode::G_UITOFP:
165 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000166 }
167 llvm_unreachable("Unsupported libcall function");
168}
169
170static LegalizerHelper::LegalizeResult
171conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
172 Type *FromType) {
173 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
174 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
175 {{MI.getOperand(1).getReg(), FromType}});
176}
177
Tim Northover69fa84a2016-10-14 22:18:18 +0000178LegalizerHelper::LegalizeResult
179LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000180 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
181 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000182 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000183
Diana Picusfc1675e2017-07-05 12:57:24 +0000184 MIRBuilder.setInstr(MI);
185
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000186 switch (MI.getOpcode()) {
187 default:
188 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000189 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000190 case TargetOpcode::G_UDIV:
191 case TargetOpcode::G_SREM:
192 case TargetOpcode::G_UREM: {
193 Type *HLTy = Type::getInt32Ty(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000194 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
195 if (Status != Legalized)
196 return Status;
197 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000198 }
Diana Picus1314a282017-04-11 10:52:34 +0000199 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000200 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000201 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000202 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000203 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000204 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000205 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000206 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000207 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
208 if (Status != Legalized)
209 return Status;
210 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000211 }
Diana Picus65ed3642018-01-17 13:34:10 +0000212 case TargetOpcode::G_FPEXT: {
213 // FIXME: Support other floating point types (half, fp128 etc)
214 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
215 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
216 if (ToSize != 64 || FromSize != 32)
217 return UnableToLegalize;
218 LegalizeResult Status = conversionLibcall(
219 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
220 if (Status != Legalized)
221 return Status;
222 break;
223 }
224 case TargetOpcode::G_FPTRUNC: {
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 != 32 || FromSize != 64)
229 return UnableToLegalize;
230 LegalizeResult Status = conversionLibcall(
231 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
232 if (Status != Legalized)
233 return Status;
234 break;
235 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000236 case TargetOpcode::G_FPTOSI:
237 case TargetOpcode::G_FPTOUI: {
238 // FIXME: Support other types
239 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
240 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
241 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
242 return UnableToLegalize;
243 LegalizeResult Status = conversionLibcall(
244 MI, MIRBuilder, Type::getInt32Ty(Ctx),
245 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
246 if (Status != Legalized)
247 return Status;
248 break;
249 }
Diana Picus517531e2018-01-30 09:15:17 +0000250 case TargetOpcode::G_SITOFP:
251 case TargetOpcode::G_UITOFP: {
252 // FIXME: Support other types
253 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
254 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
255 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
256 return UnableToLegalize;
257 LegalizeResult Status = conversionLibcall(
258 MI, MIRBuilder,
259 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
260 Type::getInt32Ty(Ctx));
261 if (Status != Legalized)
262 return Status;
263 break;
264 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000265 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000266
267 MI.eraseFromParent();
268 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000269}
270
Tim Northover69fa84a2016-10-14 22:18:18 +0000271LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
272 unsigned TypeIdx,
273 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000274 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000275 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000276 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000277
278 MIRBuilder.setInstr(MI);
279
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000280 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
281 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000282
Tim Northover9656f142016-08-04 20:54:13 +0000283 switch (MI.getOpcode()) {
284 default:
285 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000286 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000287 // FIXME: add support for when SizeOp0 isn't an exact multiple of
288 // NarrowSize.
289 if (SizeOp0 % NarrowSize != 0)
290 return UnableToLegalize;
291 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000292
293 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000294 for (int i = 0; i < NumParts; ++i)
295 DstRegs.push_back(
296 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Tim Northoverff5e7e12017-06-30 20:27:36 +0000297 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
298 MI.eraseFromParent();
299 return Legalized;
300 }
Tim Northover9656f142016-08-04 20:54:13 +0000301 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000302 // FIXME: add support for when SizeOp0 isn't an exact multiple of
303 // NarrowSize.
304 if (SizeOp0 % NarrowSize != 0)
305 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000306 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000307 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000308
Tim Northoverb18ea162016-09-20 15:20:36 +0000309 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000310 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
311 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
312
Tim Northover0f140c72016-09-09 11:46:34 +0000313 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
314 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000315
316 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000317 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
318 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000319
Tim Northover0f140c72016-09-09 11:46:34 +0000320 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000321 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000322
323 DstRegs.push_back(DstReg);
324 CarryIn = CarryOut;
325 }
Tim Northover0f140c72016-09-09 11:46:34 +0000326 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000327 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000328 MI.eraseFromParent();
329 return Legalized;
330 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000331 case TargetOpcode::G_EXTRACT: {
332 if (TypeIdx != 1)
333 return UnableToLegalize;
334
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000335 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
336 // FIXME: add support for when SizeOp1 isn't an exact multiple of
337 // NarrowSize.
338 if (SizeOp1 % NarrowSize != 0)
339 return UnableToLegalize;
340 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000341
342 SmallVector<unsigned, 2> SrcRegs, DstRegs;
343 SmallVector<uint64_t, 2> Indexes;
344 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
345
346 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000347 uint64_t OpStart = MI.getOperand(2).getImm();
348 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000349 for (int i = 0; i < NumParts; ++i) {
350 unsigned SrcStart = i * NarrowSize;
351
352 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
353 // No part of the extract uses this subregister, ignore it.
354 continue;
355 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
356 // The entire subregister is extracted, forward the value.
357 DstRegs.push_back(SrcRegs[i]);
358 continue;
359 }
360
361 // OpSegStart is where this destination segment would start in OpReg if it
362 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000363 int64_t ExtractOffset;
364 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000365 if (OpStart < SrcStart) {
366 ExtractOffset = 0;
367 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
368 } else {
369 ExtractOffset = OpStart - SrcStart;
370 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
371 }
372
373 unsigned SegReg = SrcRegs[i];
374 if (ExtractOffset != 0 || SegSize != NarrowSize) {
375 // A genuine extract is needed.
376 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
377 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
378 }
379
380 DstRegs.push_back(SegReg);
381 }
382
383 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
384 MI.eraseFromParent();
385 return Legalized;
386 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000387 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000388 // FIXME: add support for when SizeOp0 isn't an exact multiple of
389 // NarrowSize.
390 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000391 return UnableToLegalize;
392
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000393 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000394
395 SmallVector<unsigned, 2> SrcRegs, DstRegs;
396 SmallVector<uint64_t, 2> Indexes;
397 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
398
Tim Northover75e0b912017-03-06 18:23:04 +0000399 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000400 uint64_t OpStart = MI.getOperand(3).getImm();
401 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000402 for (int i = 0; i < NumParts; ++i) {
403 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000404
Tim Northover75e0b912017-03-06 18:23:04 +0000405 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000406 // No part of the insert affects this subregister, forward the original.
407 DstRegs.push_back(SrcRegs[i]);
408 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000409 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000410 // The entire subregister is defined by this insert, forward the new
411 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000412 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000413 continue;
414 }
415
Tim Northover2eb18d32017-03-07 21:24:33 +0000416 // OpSegStart is where this destination segment would start in OpReg if it
417 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000418 int64_t ExtractOffset, InsertOffset;
419 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000420 if (OpStart < DstStart) {
421 InsertOffset = 0;
422 ExtractOffset = DstStart - OpStart;
423 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
424 } else {
425 InsertOffset = OpStart - DstStart;
426 ExtractOffset = 0;
427 SegSize =
428 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
429 }
430
431 unsigned SegReg = OpReg;
432 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000433 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000434 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
435 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000436 }
437
Tim Northover75e0b912017-03-06 18:23:04 +0000438 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000439 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000440 DstRegs.push_back(DstReg);
441 }
442
443 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000444 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000445 MI.eraseFromParent();
446 return Legalized;
447 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000448 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000449 // FIXME: add support for when SizeOp0 isn't an exact multiple of
450 // NarrowSize.
451 if (SizeOp0 % NarrowSize != 0)
452 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000453
454 const auto &MMO = **MI.memoperands_begin();
455 // This implementation doesn't work for atomics. Give up instead of doing
456 // something invalid.
457 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
458 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
459 return UnableToLegalize;
460
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000461 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000462 LLT OffsetTy = LLT::scalar(
463 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000464
465 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000466 for (int i = 0; i < NumParts; ++i) {
467 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000468 unsigned SrcReg = 0;
469 unsigned Adjustment = i * NarrowSize / 8;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000470
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000471 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
472 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
473 NarrowSize / 8, i == 0 ? MMO.getAlignment() : NarrowSize / 8,
474 MMO.getAAInfo(), MMO.getRanges(), MMO.getSyncScopeID(),
475 MMO.getOrdering(), MMO.getFailureOrdering());
476
Daniel Sanders4e523662017-06-13 23:42:32 +0000477 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
478 Adjustment);
479
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000480 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000481
482 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000483 }
484 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000485 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000486 MI.eraseFromParent();
487 return Legalized;
488 }
Justin Bognerfde01042017-01-18 17:29:54 +0000489 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000490 // FIXME: add support for when SizeOp0 isn't an exact multiple of
491 // NarrowSize.
492 if (SizeOp0 % NarrowSize != 0)
493 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000494
495 const auto &MMO = **MI.memoperands_begin();
496 // This implementation doesn't work for atomics. Give up instead of doing
497 // something invalid.
498 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
499 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
500 return UnableToLegalize;
501
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000502 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000503 LLT OffsetTy = LLT::scalar(
504 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000505
506 SmallVector<unsigned, 2> SrcRegs;
507 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
508
509 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000510 unsigned DstReg = 0;
511 unsigned Adjustment = i * NarrowSize / 8;
512
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000513 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
514 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
515 NarrowSize / 8, i == 0 ? MMO.getAlignment() : NarrowSize / 8,
516 MMO.getAAInfo(), MMO.getRanges(), MMO.getSyncScopeID(),
517 MMO.getOrdering(), MMO.getFailureOrdering());
518
Daniel Sanders4e523662017-06-13 23:42:32 +0000519 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
520 Adjustment);
521
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000522 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000523 }
524 MI.eraseFromParent();
525 return Legalized;
526 }
Igor Breger29537882017-04-07 14:41:59 +0000527 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000528 // FIXME: add support for when SizeOp0 isn't an exact multiple of
529 // NarrowSize.
530 if (SizeOp0 % NarrowSize != 0)
531 return UnableToLegalize;
532 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000533 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000534 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000535
536 SmallVector<unsigned, 2> DstRegs;
537 for (int i = 0; i < NumParts; ++i) {
538 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
539 ConstantInt *CI =
540 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
541 MIRBuilder.buildConstant(DstReg, *CI);
542 DstRegs.push_back(DstReg);
543 }
544 unsigned DstReg = MI.getOperand(0).getReg();
545 MIRBuilder.buildMerge(DstReg, DstRegs);
546 MI.eraseFromParent();
547 return Legalized;
548 }
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000549 case TargetOpcode::G_OR: {
550 // Legalize bitwise operation:
551 // A = BinOp<Ty> B, C
552 // into:
553 // B1, ..., BN = G_UNMERGE_VALUES B
554 // C1, ..., CN = G_UNMERGE_VALUES C
555 // A1 = BinOp<Ty/N> B1, C2
556 // ...
557 // AN = BinOp<Ty/N> BN, CN
558 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000559
560 // FIXME: add support for when SizeOp0 isn't an exact multiple of
561 // NarrowSize.
562 if (SizeOp0 % NarrowSize != 0)
563 return UnableToLegalize;
564 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000565
566 // List the registers where the destination will be scattered.
567 SmallVector<unsigned, 2> DstRegs;
568 // List the registers where the first argument will be split.
569 SmallVector<unsigned, 2> SrcsReg1;
570 // List the registers where the second argument will be split.
571 SmallVector<unsigned, 2> SrcsReg2;
572 // Create all the temporary registers.
573 for (int i = 0; i < NumParts; ++i) {
574 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
575 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
576 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
577
578 DstRegs.push_back(DstReg);
579 SrcsReg1.push_back(SrcReg1);
580 SrcsReg2.push_back(SrcReg2);
581 }
582 // Explode the big arguments into smaller chunks.
583 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
584 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
585
586 // Do the operation on each small part.
587 for (int i = 0; i < NumParts; ++i)
588 MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
589
590 // Gather the destination registers into the final destination.
591 unsigned DstReg = MI.getOperand(0).getReg();
592 MIRBuilder.buildMerge(DstReg, DstRegs);
593 MI.eraseFromParent();
594 return Legalized;
595 }
Tim Northover9656f142016-08-04 20:54:13 +0000596 }
Tim Northover33b07d62016-07-22 20:03:43 +0000597}
598
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000599void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
600 unsigned OpIdx, unsigned ExtOpcode) {
601 MachineOperand &MO = MI.getOperand(OpIdx);
602 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, WideTy, MO.getReg());
603 MO.setReg(ExtB->getOperand(0).getReg());
604}
605
606void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
607 unsigned OpIdx, unsigned TruncOpcode) {
608 MachineOperand &MO = MI.getOperand(OpIdx);
609 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
610 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
611 MIRBuilder.buildInstr(TruncOpcode, MO.getReg(), DstExt);
612 MO.setReg(DstExt);
613}
614
Tim Northover69fa84a2016-10-14 22:18:18 +0000615LegalizerHelper::LegalizeResult
616LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000617 MIRBuilder.setInstr(MI);
618
Tim Northover32335812016-08-04 18:35:11 +0000619 switch (MI.getOpcode()) {
620 default:
621 return UnableToLegalize;
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000622 case TargetOpcode::G_UADDO:
623 case TargetOpcode::G_USUBO: {
624 if (TypeIdx == 1)
625 return UnableToLegalize; // TODO
626 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, WideTy,
627 MI.getOperand(2).getReg());
628 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, WideTy,
629 MI.getOperand(3).getReg());
630 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
631 ? TargetOpcode::G_ADD
632 : TargetOpcode::G_SUB;
633 // Do the arithmetic in the larger type.
634 auto NewOp = MIRBuilder.buildInstr(Opcode, WideTy, LHSZext, RHSZext);
635 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
636 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
637 auto AndOp = MIRBuilder.buildInstr(
638 TargetOpcode::G_AND, WideTy, NewOp,
639 MIRBuilder.buildConstant(WideTy, Mask.getZExtValue()));
640 // There is no overflow if the AndOp is the same as NewOp.
641 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
642 AndOp);
643 // Now trunc the NewOp to the original result.
644 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
645 MI.eraseFromParent();
646 return Legalized;
647 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000648 case TargetOpcode::G_CTTZ:
649 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
650 case TargetOpcode::G_CTLZ:
651 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
652 case TargetOpcode::G_CTPOP: {
653 // First ZEXT the input.
654 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
655 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
656 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
657 // The count is the same in the larger type except if the original
658 // value was zero. This can be handled by setting the bit just off
659 // the top of the original type.
660 auto TopBit =
661 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
662 MIBSrc = MIRBuilder.buildInstr(
663 TargetOpcode::G_OR, WideTy, MIBSrc,
664 MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue()));
665 }
666 // Perform the operation at the larger size.
667 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), WideTy, MIBSrc);
668 // This is already the correct result for CTPOP and CTTZs
669 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
670 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
671 // The correct result is NewOp - (Difference in widety and current ty).
672 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
673 MIBNewOp =
674 MIRBuilder.buildInstr(TargetOpcode::G_SUB, WideTy, MIBNewOp,
675 MIRBuilder.buildConstant(WideTy, SizeDiff));
676 }
677 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
678 // Make the original instruction a trunc now, and update it's source.
679 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
680 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
681 MIRBuilder.recordInsertion(&MI);
682 return Legalized;
683 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000684
Tim Northover61c16142016-08-04 21:39:49 +0000685 case TargetOpcode::G_ADD:
686 case TargetOpcode::G_AND:
687 case TargetOpcode::G_MUL:
688 case TargetOpcode::G_OR:
689 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000690 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000691 // Perform operation at larger width (any extension is fine here, high bits
692 // don't affect the result) and then truncate the result back to the
693 // original type.
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000694 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
695 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
696 widenScalarDst(MI, WideTy);
697 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000698 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000699
Roman Tereshin6d266382018-05-09 21:43:30 +0000700 case TargetOpcode::G_SHL:
701 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
702 // The "number of bits to shift" operand must preserve its value as an
703 // unsigned integer:
704 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
705 widenScalarDst(MI, WideTy);
706 MIRBuilder.recordInsertion(&MI);
707 return Legalized;
708
Tim Northover7a753d92016-08-26 17:46:06 +0000709 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000710 case TargetOpcode::G_SREM:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000711 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
712 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
713 widenScalarDst(MI, WideTy);
714 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000715 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000716
Roman Tereshin6d266382018-05-09 21:43:30 +0000717 case TargetOpcode::G_ASHR:
718 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
719 // The "number of bits to shift" operand must preserve its value as an
720 // unsigned integer:
721 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
722 widenScalarDst(MI, WideTy);
723 MIRBuilder.recordInsertion(&MI);
724 return Legalized;
725
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000726 case TargetOpcode::G_UDIV:
727 case TargetOpcode::G_UREM:
728 case TargetOpcode::G_LSHR:
729 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
730 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
731 widenScalarDst(MI, WideTy);
732 MIRBuilder.recordInsertion(&MI);
733 return Legalized;
734
735 case TargetOpcode::G_SELECT:
Tim Northover868332d2017-02-06 23:41:27 +0000736 if (TypeIdx != 0)
737 return UnableToLegalize;
Tim Northover868332d2017-02-06 23:41:27 +0000738 // Perform operation at larger width (any extension is fine here, high bits
739 // don't affect the result) and then truncate the result back to the
740 // original type.
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000741 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
742 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
743 widenScalarDst(MI, WideTy);
744 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000745 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000746
Ahmed Bougachab6137062017-01-23 21:10:14 +0000747 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000748 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +0000749 if (TypeIdx != 0)
750 return UnableToLegalize;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000751 widenScalarDst(MI, WideTy);
752 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000753 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000754
Ahmed Bougachad2948232017-01-20 01:37:24 +0000755 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +0000756 if (TypeIdx != 1)
757 return UnableToLegalize;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000758 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
759 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000760 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000761
762 case TargetOpcode::G_UITOFP:
763 if (TypeIdx != 1)
764 return UnableToLegalize;
765 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
766 MIRBuilder.recordInsertion(&MI);
767 return Legalized;
768
769 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +0000770 if (TypeIdx != 0)
771 return UnableToLegalize;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000772 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
773 widenScalarDst(MI, WideTy);
774 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000775 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000776
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000777 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +0000778 // For some types like i24, we might try to widen to i32. To properly handle
779 // this we should be using a dedicated extending load, until then avoid
780 // trying to legalize.
781 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
782 WideTy.getSizeInBits())
783 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000784 LLVM_FALLTHROUGH;
785 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000786 case TargetOpcode::G_ZEXTLOAD:
787 widenScalarDst(MI, WideTy);
788 MIRBuilder.recordInsertion(&MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000789 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000790
Tim Northover3c73e362016-08-23 18:20:09 +0000791 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000792 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
793 WideTy != LLT::scalar(8))
794 return UnableToLegalize;
795
Amara Emerson5a3bb682018-06-01 13:20:32 +0000796 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000797 MIRBuilder.recordInsertion(&MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000798 return Legalized;
799 }
Tim Northoverea904f92016-08-19 22:40:00 +0000800 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000801 MachineOperand &SrcMO = MI.getOperand(1);
802 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
803 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
804 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
805
806 widenScalarDst(MI, WideTy);
807 MIRBuilder.recordInsertion(&MI);
Tim Northoverea904f92016-08-19 22:40:00 +0000808 return Legalized;
809 }
Tim Northovera11be042016-08-19 22:40:08 +0000810 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000811 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +0000812 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000813 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +0000814 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000815 switch (WideTy.getSizeInBits()) {
816 case 32:
817 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
818 break;
819 case 64:
820 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
821 break;
822 default:
823 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +0000824 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000825 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
826
827 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
828 MIRBuilder.recordInsertion(&MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +0000829 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +0000830 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000831 case TargetOpcode::G_BRCOND:
832 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
833 MIRBuilder.recordInsertion(&MI);
834 return Legalized;
835
836 case TargetOpcode::G_FCMP:
837 if (TypeIdx == 0)
838 widenScalarDst(MI, WideTy);
839 else {
840 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
841 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +0000842 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000843 MIRBuilder.recordInsertion(&MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000844 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000845
846 case TargetOpcode::G_ICMP:
847 if (TypeIdx == 0)
848 widenScalarDst(MI, WideTy);
849 else {
850 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
851 MI.getOperand(1).getPredicate()))
852 ? TargetOpcode::G_SEXT
853 : TargetOpcode::G_ZEXT;
854 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
855 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
856 }
857 MIRBuilder.recordInsertion(&MI);
858 return Legalized;
859
860 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +0000861 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000862 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
863 MIRBuilder.recordInsertion(&MI);
Tim Northover22d82cf2016-09-15 11:02:19 +0000864 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000865
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000866 case TargetOpcode::G_PHI: {
867 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000868
869 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
870 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
871 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
872 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000873 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000874
875 MachineBasicBlock &MBB = *MI.getParent();
876 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
877 widenScalarDst(MI, WideTy);
878 MIRBuilder.recordInsertion(&MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000879 return Legalized;
880 }
Tim Northover32335812016-08-04 18:35:11 +0000881 }
Tim Northover33b07d62016-07-22 20:03:43 +0000882}
883
Tim Northover69fa84a2016-10-14 22:18:18 +0000884LegalizerHelper::LegalizeResult
885LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000886 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000887 MIRBuilder.setInstr(MI);
888
889 switch(MI.getOpcode()) {
890 default:
891 return UnableToLegalize;
892 case TargetOpcode::G_SREM:
893 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000894 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
895 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000896 .addDef(QuotReg)
897 .addUse(MI.getOperand(1).getReg())
898 .addUse(MI.getOperand(2).getReg());
899
Tim Northover0f140c72016-09-09 11:46:34 +0000900 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
901 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
902 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
903 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000904 MI.eraseFromParent();
905 return Legalized;
906 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000907 case TargetOpcode::G_SMULO:
908 case TargetOpcode::G_UMULO: {
909 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
910 // result.
911 unsigned Res = MI.getOperand(0).getReg();
912 unsigned Overflow = MI.getOperand(1).getReg();
913 unsigned LHS = MI.getOperand(2).getReg();
914 unsigned RHS = MI.getOperand(3).getReg();
915
916 MIRBuilder.buildMul(Res, LHS, RHS);
917
918 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
919 ? TargetOpcode::G_SMULH
920 : TargetOpcode::G_UMULH;
921
922 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
923 MIRBuilder.buildInstr(Opcode)
924 .addDef(HiPart)
925 .addUse(LHS)
926 .addUse(RHS);
927
928 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
929 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +0000930
931 // For *signed* multiply, overflow is detected by checking:
932 // (hi != (lo >> bitwidth-1))
933 if (Opcode == TargetOpcode::G_SMULH) {
934 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
935 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
936 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
937 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
938 .addDef(Shifted)
939 .addUse(Res)
940 .addUse(ShiftAmt);
941 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
942 } else {
943 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
944 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000945 MI.eraseFromParent();
946 return Legalized;
947 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000948 case TargetOpcode::G_FNEG: {
949 // TODO: Handle vector types once we are able to
950 // represent them.
951 if (Ty.isVector())
952 return UnableToLegalize;
953 unsigned Res = MI.getOperand(0).getReg();
954 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +0000955 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +0000956 switch (Ty.getSizeInBits()) {
957 case 16:
958 ZeroTy = Type::getHalfTy(Ctx);
959 break;
960 case 32:
961 ZeroTy = Type::getFloatTy(Ctx);
962 break;
963 case 64:
964 ZeroTy = Type::getDoubleTy(Ctx);
965 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +0000966 case 128:
967 ZeroTy = Type::getFP128Ty(Ctx);
968 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +0000969 default:
970 llvm_unreachable("unexpected floating-point type");
971 }
972 ConstantFP &ZeroForNegation =
973 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +0000974 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +0000975 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
976 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +0000977 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +0000978 .addUse(MI.getOperand(1).getReg());
979 MI.eraseFromParent();
980 return Legalized;
981 }
Volkan Keles225921a2017-03-10 21:25:09 +0000982 case TargetOpcode::G_FSUB: {
983 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
984 // First, check if G_FNEG is marked as Lower. If so, we may
985 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +0000986 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +0000987 return UnableToLegalize;
988 unsigned Res = MI.getOperand(0).getReg();
989 unsigned LHS = MI.getOperand(1).getReg();
990 unsigned RHS = MI.getOperand(2).getReg();
991 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
992 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
993 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
994 .addDef(Res)
995 .addUse(LHS)
996 .addUse(Neg);
997 MI.eraseFromParent();
998 return Legalized;
999 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001000 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1001 unsigned OldValRes = MI.getOperand(0).getReg();
1002 unsigned SuccessRes = MI.getOperand(1).getReg();
1003 unsigned Addr = MI.getOperand(2).getReg();
1004 unsigned CmpVal = MI.getOperand(3).getReg();
1005 unsigned NewVal = MI.getOperand(4).getReg();
1006 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1007 **MI.memoperands_begin());
1008 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1009 MI.eraseFromParent();
1010 return Legalized;
1011 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001012 case TargetOpcode::G_LOAD:
1013 case TargetOpcode::G_SEXTLOAD:
1014 case TargetOpcode::G_ZEXTLOAD: {
1015 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1016 unsigned DstReg = MI.getOperand(0).getReg();
1017 unsigned PtrReg = MI.getOperand(1).getReg();
1018 LLT DstTy = MRI.getType(DstReg);
1019 auto &MMO = **MI.memoperands_begin();
1020
1021 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001022 // In the case of G_LOAD, this was a non-extending load already and we're
1023 // about to lower to the same instruction.
1024 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1025 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001026 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1027 MI.eraseFromParent();
1028 return Legalized;
1029 }
1030
1031 if (DstTy.isScalar()) {
1032 unsigned TmpReg = MRI.createGenericVirtualRegister(
1033 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1034 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1035 switch (MI.getOpcode()) {
1036 default:
1037 llvm_unreachable("Unexpected opcode");
1038 case TargetOpcode::G_LOAD:
1039 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1040 break;
1041 case TargetOpcode::G_SEXTLOAD:
1042 MIRBuilder.buildSExt(DstReg, TmpReg);
1043 break;
1044 case TargetOpcode::G_ZEXTLOAD:
1045 MIRBuilder.buildZExt(DstReg, TmpReg);
1046 break;
1047 }
1048 MI.eraseFromParent();
1049 return Legalized;
1050 }
1051
1052 return UnableToLegalize;
1053 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001054 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1055 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1056 case TargetOpcode::G_CTLZ:
1057 case TargetOpcode::G_CTTZ:
1058 case TargetOpcode::G_CTPOP:
1059 return lowerBitCount(MI, TypeIdx, Ty);
Tim Northovercecee562016-08-26 17:46:13 +00001060 }
1061}
1062
Tim Northover69fa84a2016-10-14 22:18:18 +00001063LegalizerHelper::LegalizeResult
1064LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1065 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +00001066 // FIXME: Don't know how to handle secondary types yet.
1067 if (TypeIdx != 0)
1068 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001069 switch (MI.getOpcode()) {
1070 default:
1071 return UnableToLegalize;
1072 case TargetOpcode::G_ADD: {
1073 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +00001074 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +00001075 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1076 int NumParts = Size / NarrowSize;
1077 // FIXME: Don't know how to handle the situation where the small vectors
1078 // aren't all the same size yet.
1079 if (Size % NarrowSize != 0)
1080 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001081
1082 MIRBuilder.setInstr(MI);
1083
Tim Northoverb18ea162016-09-20 15:20:36 +00001084 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +00001085 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
1086 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
1087
1088 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +00001089 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1090 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +00001091 DstRegs.push_back(DstReg);
1092 }
1093
Tim Northoverbf017292017-03-03 22:46:09 +00001094 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +00001095 MI.eraseFromParent();
1096 return Legalized;
1097 }
1098 }
1099}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001100
1101LegalizerHelper::LegalizeResult
1102LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1103 unsigned Opc = MI.getOpcode();
1104 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
1105 auto isLegalOrCustom = [this](const LegalityQuery &Q) {
1106 auto QAction = LI.getAction(Q).Action;
1107 return QAction == Legal || QAction == Custom;
1108 };
1109 switch (Opc) {
1110 default:
1111 return UnableToLegalize;
1112 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1113 // This trivially expands to CTLZ.
1114 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
1115 MIRBuilder.recordInsertion(&MI);
1116 return Legalized;
1117 }
1118 case TargetOpcode::G_CTLZ: {
1119 unsigned SrcReg = MI.getOperand(1).getReg();
1120 unsigned Len = Ty.getSizeInBits();
1121 if (isLegalOrCustom({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1122 // If CTLZ_ZERO_UNDEF is legal or custom, emit that and a select with
1123 // zero.
1124 auto MIBCtlzZU =
1125 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, Ty, SrcReg);
1126 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1127 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1128 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1129 SrcReg, MIBZero);
1130 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1131 MIBCtlzZU);
1132 MI.eraseFromParent();
1133 return Legalized;
1134 }
1135 // for now, we do this:
1136 // NewLen = NextPowerOf2(Len);
1137 // x = x | (x >> 1);
1138 // x = x | (x >> 2);
1139 // ...
1140 // x = x | (x >>16);
1141 // x = x | (x >>32); // for 64-bit input
1142 // Upto NewLen/2
1143 // return Len - popcount(x);
1144 //
1145 // Ref: "Hacker's Delight" by Henry Warren
1146 unsigned Op = SrcReg;
1147 unsigned NewLen = PowerOf2Ceil(Len);
1148 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1149 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1150 auto MIBOp = MIRBuilder.buildInstr(
1151 TargetOpcode::G_OR, Ty, Op,
1152 MIRBuilder.buildInstr(TargetOpcode::G_LSHR, Ty, Op, MIBShiftAmt));
1153 Op = MIBOp->getOperand(0).getReg();
1154 }
1155 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, Ty, Op);
1156 MIRBuilder.buildInstr(TargetOpcode::G_SUB, MI.getOperand(0).getReg(),
1157 MIRBuilder.buildConstant(Ty, Len), MIBPop);
1158 MI.eraseFromParent();
1159 return Legalized;
1160 }
1161 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1162 // This trivially expands to CTTZ.
1163 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
1164 MIRBuilder.recordInsertion(&MI);
1165 return Legalized;
1166 }
1167 case TargetOpcode::G_CTTZ: {
1168 unsigned SrcReg = MI.getOperand(1).getReg();
1169 unsigned Len = Ty.getSizeInBits();
1170 if (isLegalOrCustom({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
1171 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1172 // zero.
1173 auto MIBCttzZU =
1174 MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, Ty, SrcReg);
1175 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1176 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1177 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1178 SrcReg, MIBZero);
1179 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1180 MIBCttzZU);
1181 MI.eraseFromParent();
1182 return Legalized;
1183 }
1184 // for now, we use: { return popcount(~x & (x - 1)); }
1185 // unless the target has ctlz but not ctpop, in which case we use:
1186 // { return 32 - nlz(~x & (x-1)); }
1187 // Ref: "Hacker's Delight" by Henry Warren
1188 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
1189 auto MIBNot =
1190 MIRBuilder.buildInstr(TargetOpcode::G_XOR, Ty, SrcReg, MIBCstNeg1);
1191 auto MIBTmp = MIRBuilder.buildInstr(
1192 TargetOpcode::G_AND, Ty, MIBNot,
1193 MIRBuilder.buildInstr(TargetOpcode::G_ADD, Ty, SrcReg, MIBCstNeg1));
1194 if (!isLegalOrCustom({TargetOpcode::G_CTPOP, {Ty}}) &&
1195 isLegalOrCustom({TargetOpcode::G_CTLZ, {Ty}})) {
1196 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
1197 MIRBuilder.buildInstr(
1198 TargetOpcode::G_SUB, MI.getOperand(0).getReg(),
1199 MIBCstLen,
1200 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, Ty, MIBTmp));
1201 MI.eraseFromParent();
1202 return Legalized;
1203 }
1204 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
1205 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
1206 return Legalized;
1207 }
1208 }
1209}