blob: a06d4f565cb1324f1c5623e29df6237fd41c1652 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tim Northover33b07d62016-07-22 20:03:43 +00006//
7//===----------------------------------------------------------------------===//
8//
Tim Northover69fa84a2016-10-14 22:18:18 +00009/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000010/// individual instructions and the LegalizeMachineIR wrapper pass for the
11/// primary legalization.
12//
13//===----------------------------------------------------------------------===//
14
Tim Northover69fa84a2016-10-14 22:18:18 +000015#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000016#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000017#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000018#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000020#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000021#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000023#include "llvm/Support/Debug.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000024#include "llvm/Support/MathExtras.h"
Tim Northover33b07d62016-07-22 20:03:43 +000025#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000026
Daniel Sanders5377fb32017-04-20 15:46:12 +000027#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000028
29using namespace llvm;
Daniel Sanders9ade5592018-01-29 17:37:29 +000030using namespace LegalizeActions;
Tim Northover33b07d62016-07-22 20:03:43 +000031
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000032LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000033 GISelChangeObserver &Observer,
34 MachineIRBuilder &Builder)
35 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
36 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000037 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000038 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000039}
40
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000041LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000042 GISelChangeObserver &Observer,
43 MachineIRBuilder &B)
44 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000045 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000046 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000047}
Tim Northover69fa84a2016-10-14 22:18:18 +000048LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000049LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000050 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000051
Daniel Sanders262ed0e2018-01-24 17:17:46 +000052 auto Step = LI.getAction(MI, MRI);
53 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000054 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000055 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000056 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000057 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000058 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000059 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000060 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000061 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000062 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000063 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000064 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000065 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000066 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000067 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000068 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000069 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000070 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000071 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000072 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000073 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000074 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
75 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000076 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000077 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000078 return UnableToLegalize;
79 }
80}
81
Tim Northover69fa84a2016-10-14 22:18:18 +000082void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
83 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000084 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000085 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000086 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000087}
88
Tim Northovere0418412017-02-08 23:23:39 +000089static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
90 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000091 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000092 assert((Size == 32 || Size == 64) && "Unsupported size");
93 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +000094 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000095 assert((Size == 32 || Size == 64) && "Unsupported size");
96 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000097 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000098 assert((Size == 32 || Size == 64) && "Unsupported size");
99 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000100 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000101 assert((Size == 32 || Size == 64) && "Unsupported size");
102 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000103 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
104 assert(Size == 32 && "Unsupported size");
105 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000106 case TargetOpcode::G_FADD:
107 assert((Size == 32 || Size == 64) && "Unsupported size");
108 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000109 case TargetOpcode::G_FSUB:
110 assert((Size == 32 || Size == 64) && "Unsupported size");
111 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000112 case TargetOpcode::G_FMUL:
113 assert((Size == 32 || Size == 64) && "Unsupported size");
114 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000115 case TargetOpcode::G_FDIV:
116 assert((Size == 32 || Size == 64) && "Unsupported size");
117 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000118 case TargetOpcode::G_FREM:
119 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
120 case TargetOpcode::G_FPOW:
121 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000122 case TargetOpcode::G_FMA:
123 assert((Size == 32 || Size == 64) && "Unsupported size");
124 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000125 }
126 llvm_unreachable("Unknown libcall function");
127}
128
Diana Picusfc1675e2017-07-05 12:57:24 +0000129LegalizerHelper::LegalizeResult
130llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
131 const CallLowering::ArgInfo &Result,
132 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000133 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
134 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000135 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000136
Diana Picuse97822e2017-04-24 07:22:31 +0000137 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000138 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
139 MachineOperand::CreateES(Name), Result, Args))
140 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000141
Diana Picuse97822e2017-04-24 07:22:31 +0000142 return LegalizerHelper::Legalized;
143}
144
Diana Picus65ed3642018-01-17 13:34:10 +0000145// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000146static LegalizerHelper::LegalizeResult
147simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
148 Type *OpType) {
149 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000150
151 SmallVector<CallLowering::ArgInfo, 3> Args;
152 for (unsigned i = 1; i < MI.getNumOperands(); i++)
153 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000154 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000155 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000156}
157
Diana Picus65ed3642018-01-17 13:34:10 +0000158static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
159 Type *FromType) {
160 auto ToMVT = MVT::getVT(ToType);
161 auto FromMVT = MVT::getVT(FromType);
162
163 switch (Opcode) {
164 case TargetOpcode::G_FPEXT:
165 return RTLIB::getFPEXT(FromMVT, ToMVT);
166 case TargetOpcode::G_FPTRUNC:
167 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000168 case TargetOpcode::G_FPTOSI:
169 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
170 case TargetOpcode::G_FPTOUI:
171 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000172 case TargetOpcode::G_SITOFP:
173 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
174 case TargetOpcode::G_UITOFP:
175 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000176 }
177 llvm_unreachable("Unsupported libcall function");
178}
179
180static LegalizerHelper::LegalizeResult
181conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
182 Type *FromType) {
183 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
184 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
185 {{MI.getOperand(1).getReg(), FromType}});
186}
187
Tim Northover69fa84a2016-10-14 22:18:18 +0000188LegalizerHelper::LegalizeResult
189LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000190 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
191 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000192 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000193
Diana Picusfc1675e2017-07-05 12:57:24 +0000194 MIRBuilder.setInstr(MI);
195
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000196 switch (MI.getOpcode()) {
197 default:
198 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000199 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000200 case TargetOpcode::G_UDIV:
201 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000202 case TargetOpcode::G_UREM:
203 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000204 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000205 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
206 if (Status != Legalized)
207 return Status;
208 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000209 }
Diana Picus1314a282017-04-11 10:52:34 +0000210 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000211 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000212 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000213 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000214 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000215 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000216 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000217 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000218 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
219 if (Status != Legalized)
220 return Status;
221 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000222 }
Diana Picus65ed3642018-01-17 13:34:10 +0000223 case TargetOpcode::G_FPEXT: {
224 // FIXME: Support other floating point types (half, fp128 etc)
225 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
226 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
227 if (ToSize != 64 || FromSize != 32)
228 return UnableToLegalize;
229 LegalizeResult Status = conversionLibcall(
230 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
231 if (Status != Legalized)
232 return Status;
233 break;
234 }
235 case TargetOpcode::G_FPTRUNC: {
236 // FIXME: Support other floating point types (half, fp128 etc)
237 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
238 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
239 if (ToSize != 32 || FromSize != 64)
240 return UnableToLegalize;
241 LegalizeResult Status = conversionLibcall(
242 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
243 if (Status != Legalized)
244 return Status;
245 break;
246 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000247 case TargetOpcode::G_FPTOSI:
248 case TargetOpcode::G_FPTOUI: {
249 // FIXME: Support other types
250 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
251 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
252 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
253 return UnableToLegalize;
254 LegalizeResult Status = conversionLibcall(
255 MI, MIRBuilder, Type::getInt32Ty(Ctx),
256 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
257 if (Status != Legalized)
258 return Status;
259 break;
260 }
Diana Picus517531e2018-01-30 09:15:17 +0000261 case TargetOpcode::G_SITOFP:
262 case TargetOpcode::G_UITOFP: {
263 // FIXME: Support other types
264 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
265 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
266 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
267 return UnableToLegalize;
268 LegalizeResult Status = conversionLibcall(
269 MI, MIRBuilder,
270 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
271 Type::getInt32Ty(Ctx));
272 if (Status != Legalized)
273 return Status;
274 break;
275 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000276 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000277
278 MI.eraseFromParent();
279 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000280}
281
Tim Northover69fa84a2016-10-14 22:18:18 +0000282LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
283 unsigned TypeIdx,
284 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000285 MIRBuilder.setInstr(MI);
286
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000287 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
288 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000289
Tim Northover9656f142016-08-04 20:54:13 +0000290 switch (MI.getOpcode()) {
291 default:
292 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000293 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000294 // FIXME: add support for when SizeOp0 isn't an exact multiple of
295 // NarrowSize.
296 if (SizeOp0 % NarrowSize != 0)
297 return UnableToLegalize;
298 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000299
300 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000301 for (int i = 0; i < NumParts; ++i)
302 DstRegs.push_back(
303 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000304
305 unsigned DstReg = MI.getOperand(0).getReg();
306 if(MRI.getType(DstReg).isVector())
307 MIRBuilder.buildBuildVector(DstReg, DstRegs);
308 else
309 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000310 MI.eraseFromParent();
311 return Legalized;
312 }
Tim Northover9656f142016-08-04 20:54:13 +0000313 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000314 // FIXME: add support for when SizeOp0 isn't an exact multiple of
315 // NarrowSize.
316 if (SizeOp0 % NarrowSize != 0)
317 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000318 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000319 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000320
Tim Northoverb18ea162016-09-20 15:20:36 +0000321 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000322 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
323 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
324
Tim Northover0f140c72016-09-09 11:46:34 +0000325 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
326 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000327
328 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000329 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
330 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000331
Tim Northover0f140c72016-09-09 11:46:34 +0000332 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000333 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000334
335 DstRegs.push_back(DstReg);
336 CarryIn = CarryOut;
337 }
Tim Northover0f140c72016-09-09 11:46:34 +0000338 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000339 if(MRI.getType(DstReg).isVector())
340 MIRBuilder.buildBuildVector(DstReg, DstRegs);
341 else
342 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000343 MI.eraseFromParent();
344 return Legalized;
345 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000346 case TargetOpcode::G_EXTRACT: {
347 if (TypeIdx != 1)
348 return UnableToLegalize;
349
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000350 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
351 // FIXME: add support for when SizeOp1 isn't an exact multiple of
352 // NarrowSize.
353 if (SizeOp1 % NarrowSize != 0)
354 return UnableToLegalize;
355 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000356
357 SmallVector<unsigned, 2> SrcRegs, DstRegs;
358 SmallVector<uint64_t, 2> Indexes;
359 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
360
361 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000362 uint64_t OpStart = MI.getOperand(2).getImm();
363 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000364 for (int i = 0; i < NumParts; ++i) {
365 unsigned SrcStart = i * NarrowSize;
366
367 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
368 // No part of the extract uses this subregister, ignore it.
369 continue;
370 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
371 // The entire subregister is extracted, forward the value.
372 DstRegs.push_back(SrcRegs[i]);
373 continue;
374 }
375
376 // OpSegStart is where this destination segment would start in OpReg if it
377 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000378 int64_t ExtractOffset;
379 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000380 if (OpStart < SrcStart) {
381 ExtractOffset = 0;
382 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
383 } else {
384 ExtractOffset = OpStart - SrcStart;
385 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
386 }
387
388 unsigned SegReg = SrcRegs[i];
389 if (ExtractOffset != 0 || SegSize != NarrowSize) {
390 // A genuine extract is needed.
391 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
392 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
393 }
394
395 DstRegs.push_back(SegReg);
396 }
397
Amara Emerson5ec14602018-12-10 18:44:58 +0000398 unsigned DstReg = MI.getOperand(0).getReg();
399 if(MRI.getType(DstReg).isVector())
400 MIRBuilder.buildBuildVector(DstReg, DstRegs);
401 else
402 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000403 MI.eraseFromParent();
404 return Legalized;
405 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000406 case TargetOpcode::G_INSERT: {
Matt Arsenault30989e42019-01-22 21:42:11 +0000407 // FIXME: Don't know how to handle secondary types yet.
408 if (TypeIdx != 0)
409 return UnableToLegalize;
410
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000411 // FIXME: add support for when SizeOp0 isn't an exact multiple of
412 // NarrowSize.
413 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000414 return UnableToLegalize;
415
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000416 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000417
418 SmallVector<unsigned, 2> SrcRegs, DstRegs;
419 SmallVector<uint64_t, 2> Indexes;
420 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
421
Tim Northover75e0b912017-03-06 18:23:04 +0000422 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000423 uint64_t OpStart = MI.getOperand(3).getImm();
424 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000425 for (int i = 0; i < NumParts; ++i) {
426 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000427
Tim Northover75e0b912017-03-06 18:23:04 +0000428 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000429 // No part of the insert affects this subregister, forward the original.
430 DstRegs.push_back(SrcRegs[i]);
431 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000432 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000433 // The entire subregister is defined by this insert, forward the new
434 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000435 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000436 continue;
437 }
438
Tim Northover2eb18d32017-03-07 21:24:33 +0000439 // OpSegStart is where this destination segment would start in OpReg if it
440 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000441 int64_t ExtractOffset, InsertOffset;
442 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000443 if (OpStart < DstStart) {
444 InsertOffset = 0;
445 ExtractOffset = DstStart - OpStart;
446 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
447 } else {
448 InsertOffset = OpStart - DstStart;
449 ExtractOffset = 0;
450 SegSize =
451 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
452 }
453
454 unsigned SegReg = OpReg;
455 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000456 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000457 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
458 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000459 }
460
Tim Northover75e0b912017-03-06 18:23:04 +0000461 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000462 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000463 DstRegs.push_back(DstReg);
464 }
465
466 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000467 unsigned DstReg = MI.getOperand(0).getReg();
468 if(MRI.getType(DstReg).isVector())
469 MIRBuilder.buildBuildVector(DstReg, DstRegs);
470 else
471 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000472 MI.eraseFromParent();
473 return Legalized;
474 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000475 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000476 // FIXME: add support for when SizeOp0 isn't an exact multiple of
477 // NarrowSize.
478 if (SizeOp0 % NarrowSize != 0)
479 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000480
481 const auto &MMO = **MI.memoperands_begin();
482 // This implementation doesn't work for atomics. Give up instead of doing
483 // something invalid.
484 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
485 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
486 return UnableToLegalize;
487
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000488 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000489 LLT OffsetTy = LLT::scalar(
490 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000491
492 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000493 for (int i = 0; i < NumParts; ++i) {
494 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000495 unsigned SrcReg = 0;
496 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000497 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000498
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000499 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
500 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000501 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
502 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000503
Daniel Sanders4e523662017-06-13 23:42:32 +0000504 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
505 Adjustment);
506
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000507 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000508
509 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000510 }
511 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000512 if(MRI.getType(DstReg).isVector())
513 MIRBuilder.buildBuildVector(DstReg, DstRegs);
514 else
515 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000516 MI.eraseFromParent();
517 return Legalized;
518 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000519 case TargetOpcode::G_ZEXTLOAD:
520 case TargetOpcode::G_SEXTLOAD: {
521 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
522 unsigned DstReg = MI.getOperand(0).getReg();
523 unsigned PtrReg = MI.getOperand(1).getReg();
524
525 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
526 auto &MMO = **MI.memoperands_begin();
527 if (MMO.getSize() * 8 == NarrowSize) {
528 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
529 } else {
530 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
531 : TargetOpcode::G_SEXTLOAD;
532 MIRBuilder.buildInstr(ExtLoad)
533 .addDef(TmpReg)
534 .addUse(PtrReg)
535 .addMemOperand(&MMO);
536 }
537
538 if (ZExt)
539 MIRBuilder.buildZExt(DstReg, TmpReg);
540 else
541 MIRBuilder.buildSExt(DstReg, TmpReg);
542
543 MI.eraseFromParent();
544 return Legalized;
545 }
Justin Bognerfde01042017-01-18 17:29:54 +0000546 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000547 // FIXME: add support for when SizeOp0 isn't an exact multiple of
548 // NarrowSize.
549 if (SizeOp0 % NarrowSize != 0)
550 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000551
552 const auto &MMO = **MI.memoperands_begin();
553 // This implementation doesn't work for atomics. Give up instead of doing
554 // something invalid.
555 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
556 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
557 return UnableToLegalize;
558
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000559 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000560 LLT OffsetTy = LLT::scalar(
561 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000562
563 SmallVector<unsigned, 2> SrcRegs;
564 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
565
566 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000567 unsigned DstReg = 0;
568 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000569 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Daniel Sanders4e523662017-06-13 23:42:32 +0000570
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000571 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
572 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000573 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
574 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000575
Daniel Sanders4e523662017-06-13 23:42:32 +0000576 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
577 Adjustment);
578
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000579 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000580 }
581 MI.eraseFromParent();
582 return Legalized;
583 }
Igor Breger29537882017-04-07 14:41:59 +0000584 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000585 // FIXME: add support for when SizeOp0 isn't an exact multiple of
586 // NarrowSize.
587 if (SizeOp0 % NarrowSize != 0)
588 return UnableToLegalize;
589 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000590 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000591 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000592
593 SmallVector<unsigned, 2> DstRegs;
594 for (int i = 0; i < NumParts; ++i) {
595 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
596 ConstantInt *CI =
597 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
598 MIRBuilder.buildConstant(DstReg, *CI);
599 DstRegs.push_back(DstReg);
600 }
601 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000602 if(MRI.getType(DstReg).isVector())
603 MIRBuilder.buildBuildVector(DstReg, DstRegs);
604 else
605 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000606 MI.eraseFromParent();
607 return Legalized;
608 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000609 case TargetOpcode::G_AND:
610 case TargetOpcode::G_OR:
611 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000612 // Legalize bitwise operation:
613 // A = BinOp<Ty> B, C
614 // into:
615 // B1, ..., BN = G_UNMERGE_VALUES B
616 // C1, ..., CN = G_UNMERGE_VALUES C
617 // A1 = BinOp<Ty/N> B1, C2
618 // ...
619 // AN = BinOp<Ty/N> BN, CN
620 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000621
622 // FIXME: add support for when SizeOp0 isn't an exact multiple of
623 // NarrowSize.
624 if (SizeOp0 % NarrowSize != 0)
625 return UnableToLegalize;
626 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000627
628 // List the registers where the destination will be scattered.
629 SmallVector<unsigned, 2> DstRegs;
630 // List the registers where the first argument will be split.
631 SmallVector<unsigned, 2> SrcsReg1;
632 // List the registers where the second argument will be split.
633 SmallVector<unsigned, 2> SrcsReg2;
634 // Create all the temporary registers.
635 for (int i = 0; i < NumParts; ++i) {
636 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
637 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
638 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
639
640 DstRegs.push_back(DstReg);
641 SrcsReg1.push_back(SrcReg1);
642 SrcsReg2.push_back(SrcReg2);
643 }
644 // Explode the big arguments into smaller chunks.
645 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
646 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
647
648 // Do the operation on each small part.
649 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000650 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
651 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000652
653 // Gather the destination registers into the final destination.
654 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000655 if(MRI.getType(DstReg).isVector())
656 MIRBuilder.buildBuildVector(DstReg, DstRegs);
657 else
658 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000659 MI.eraseFromParent();
660 return Legalized;
661 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000662 case TargetOpcode::G_SHL:
663 case TargetOpcode::G_LSHR:
664 case TargetOpcode::G_ASHR: {
665 if (TypeIdx != 1)
666 return UnableToLegalize; // TODO
667 narrowScalarSrc(MI, NarrowTy, 2);
668 return Legalized;
669 }
Tim Northover9656f142016-08-04 20:54:13 +0000670 }
Tim Northover33b07d62016-07-22 20:03:43 +0000671}
672
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000673void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
674 unsigned OpIdx, unsigned ExtOpcode) {
675 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000676 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000677 MO.setReg(ExtB->getOperand(0).getReg());
678}
679
Matt Arsenault30989e42019-01-22 21:42:11 +0000680void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
681 unsigned OpIdx) {
682 MachineOperand &MO = MI.getOperand(OpIdx);
683 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
684 {MO.getReg()});
685 MO.setReg(ExtB->getOperand(0).getReg());
686}
687
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000688void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
689 unsigned OpIdx, unsigned TruncOpcode) {
690 MachineOperand &MO = MI.getOperand(OpIdx);
691 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
692 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000693 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000694 MO.setReg(DstExt);
695}
696
Tim Northover69fa84a2016-10-14 22:18:18 +0000697LegalizerHelper::LegalizeResult
698LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000699 MIRBuilder.setInstr(MI);
700
Tim Northover32335812016-08-04 18:35:11 +0000701 switch (MI.getOpcode()) {
702 default:
703 return UnableToLegalize;
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000704 case TargetOpcode::G_UADDO:
705 case TargetOpcode::G_USUBO: {
706 if (TypeIdx == 1)
707 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000708 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
709 {MI.getOperand(2).getReg()});
710 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
711 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000712 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
713 ? TargetOpcode::G_ADD
714 : TargetOpcode::G_SUB;
715 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000716 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000717 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
718 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
719 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000720 TargetOpcode::G_AND, {WideTy},
721 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000722 // There is no overflow if the AndOp is the same as NewOp.
723 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
724 AndOp);
725 // Now trunc the NewOp to the original result.
726 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
727 MI.eraseFromParent();
728 return Legalized;
729 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000730 case TargetOpcode::G_CTTZ:
731 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
732 case TargetOpcode::G_CTLZ:
733 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
734 case TargetOpcode::G_CTPOP: {
735 // First ZEXT the input.
736 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
737 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
738 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
739 // The count is the same in the larger type except if the original
740 // value was zero. This can be handled by setting the bit just off
741 // the top of the original type.
742 auto TopBit =
743 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
744 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000745 TargetOpcode::G_OR, {WideTy},
746 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000747 }
748 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000749 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000750 // This is already the correct result for CTPOP and CTTZs
751 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
752 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
753 // The correct result is NewOp - (Difference in widety and current ty).
754 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000755 MIBNewOp = MIRBuilder.buildInstr(
756 TargetOpcode::G_SUB, {WideTy},
757 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000758 }
759 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +0000760 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000761 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000762 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
763 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000764 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000765 return Legalized;
766 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000767
Tim Northover61c16142016-08-04 21:39:49 +0000768 case TargetOpcode::G_ADD:
769 case TargetOpcode::G_AND:
770 case TargetOpcode::G_MUL:
771 case TargetOpcode::G_OR:
772 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000773 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000774 // Perform operation at larger width (any extension is fine here, high bits
775 // don't affect the result) and then truncate the result back to the
776 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000777 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000778 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
779 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
780 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000781 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000782 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000783
Roman Tereshin6d266382018-05-09 21:43:30 +0000784 case TargetOpcode::G_SHL:
Matt Arsenault30989e42019-01-22 21:42:11 +0000785 Observer.changingInstr(MI);
786
787 if (TypeIdx == 0) {
788 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
789 widenScalarDst(MI, WideTy);
790 } else {
791 assert(TypeIdx == 1);
792 // The "number of bits to shift" operand must preserve its value as an
793 // unsigned integer:
794 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
795 }
796
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000797 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000798 return Legalized;
799
Tim Northover7a753d92016-08-26 17:46:06 +0000800 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000801 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000802 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000803 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
804 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
805 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000806 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000807 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000808
Roman Tereshin6d266382018-05-09 21:43:30 +0000809 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +0000810 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000811 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +0000812
813 if (TypeIdx == 0) {
814 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
815 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
816
817 widenScalarSrc(MI, WideTy, 1, CvtOp);
818 widenScalarDst(MI, WideTy);
819 } else {
820 assert(TypeIdx == 1);
821 // The "number of bits to shift" operand must preserve its value as an
822 // unsigned integer:
823 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
824 }
825
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000826 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000827 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000828 case TargetOpcode::G_UDIV:
829 case TargetOpcode::G_UREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000830 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000831 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
832 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
833 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000834 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000835 return Legalized;
836
837 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000838 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +0000839 if (TypeIdx == 0) {
840 // Perform operation at larger width (any extension is fine here, high
841 // bits don't affect the result) and then truncate the result back to the
842 // original type.
843 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
844 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
845 widenScalarDst(MI, WideTy);
846 } else {
847 // Explicit extension is required here since high bits affect the result.
848 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
849 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000850 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000851 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000852
Ahmed Bougachab6137062017-01-23 21:10:14 +0000853 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000854 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +0000855 if (TypeIdx != 0)
856 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000857 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000858 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000859 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000860 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000861
Ahmed Bougachad2948232017-01-20 01:37:24 +0000862 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +0000863 if (TypeIdx != 1)
864 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000865 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000866 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000867 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000868 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000869
870 case TargetOpcode::G_UITOFP:
871 if (TypeIdx != 1)
872 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000873 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000874 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000875 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000876 return Legalized;
877
878 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +0000879 if (TypeIdx != 0)
880 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000881 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000882 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
883 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000884 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000885 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000886
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000887 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +0000888 // For some types like i24, we might try to widen to i32. To properly handle
889 // this we should be using a dedicated extending load, until then avoid
890 // trying to legalize.
891 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
892 WideTy.getSizeInBits())
893 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000894 LLVM_FALLTHROUGH;
895 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000896 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000897 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000898 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000899 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000900 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000901
Tim Northover3c73e362016-08-23 18:20:09 +0000902 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000903 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
904 WideTy != LLT::scalar(8))
905 return UnableToLegalize;
906
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000907 Observer.changingInstr(MI);
Amara Emerson5a3bb682018-06-01 13:20:32 +0000908 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000909 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000910 return Legalized;
911 }
Tim Northoverea904f92016-08-19 22:40:00 +0000912 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000913 MachineOperand &SrcMO = MI.getOperand(1);
914 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
915 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000916 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000917 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
918
919 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000920 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +0000921 return Legalized;
922 }
Tim Northovera11be042016-08-19 22:40:08 +0000923 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000924 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +0000925 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000926 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +0000927 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000928 switch (WideTy.getSizeInBits()) {
929 case 32:
930 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
931 break;
932 case 64:
933 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
934 break;
935 default:
936 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +0000937 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000938 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000939 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
940
941 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000942 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +0000943 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +0000944 }
Matt Arsenaultbefee402019-01-09 07:34:14 +0000945 case TargetOpcode::G_IMPLICIT_DEF: {
946 Observer.changingInstr(MI);
947 widenScalarDst(MI, WideTy);
948 Observer.changedInstr(MI);
949 return Legalized;
950 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000951 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000952 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000953 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000954 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000955 return Legalized;
956
957 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000958 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000959 if (TypeIdx == 0)
960 widenScalarDst(MI, WideTy);
961 else {
962 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
963 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +0000964 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000965 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000966 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000967
968 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000969 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000970 if (TypeIdx == 0)
971 widenScalarDst(MI, WideTy);
972 else {
973 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
974 MI.getOperand(1).getPredicate()))
975 ? TargetOpcode::G_SEXT
976 : TargetOpcode::G_ZEXT;
977 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
978 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
979 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000980 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000981 return Legalized;
982
983 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +0000984 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000985 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000986 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000987 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +0000988 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000989
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000990 case TargetOpcode::G_PHI: {
991 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000992
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000993 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000994 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
995 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
996 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
997 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000998 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000999
1000 MachineBasicBlock &MBB = *MI.getParent();
1001 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1002 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001003 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001004 return Legalized;
1005 }
Matt Arsenault63786292019-01-22 20:38:15 +00001006 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1007 if (TypeIdx == 0) {
1008 unsigned VecReg = MI.getOperand(1).getReg();
1009 LLT VecTy = MRI.getType(VecReg);
1010 Observer.changingInstr(MI);
1011
1012 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1013 WideTy.getSizeInBits()),
1014 1, TargetOpcode::G_SEXT);
1015
1016 widenScalarDst(MI, WideTy, 0);
1017 Observer.changedInstr(MI);
1018 return Legalized;
1019 }
1020
Amara Emersoncbd86d82018-10-25 14:04:54 +00001021 if (TypeIdx != 2)
1022 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001023 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001024 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001025 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001026 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001027 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001028 case TargetOpcode::G_FADD:
1029 case TargetOpcode::G_FMUL:
1030 case TargetOpcode::G_FSUB:
1031 case TargetOpcode::G_FMA:
1032 case TargetOpcode::G_FNEG:
1033 case TargetOpcode::G_FABS:
1034 case TargetOpcode::G_FDIV:
1035 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001036 case TargetOpcode::G_FCEIL:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001037 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001038 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001039
1040 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1041 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1042
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001043 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1044 Observer.changedInstr(MI);
1045 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001046 }
Tim Northover33b07d62016-07-22 20:03:43 +00001047}
1048
Tim Northover69fa84a2016-10-14 22:18:18 +00001049LegalizerHelper::LegalizeResult
1050LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001051 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001052 MIRBuilder.setInstr(MI);
1053
1054 switch(MI.getOpcode()) {
1055 default:
1056 return UnableToLegalize;
1057 case TargetOpcode::G_SREM:
1058 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001059 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1060 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001061 .addDef(QuotReg)
1062 .addUse(MI.getOperand(1).getReg())
1063 .addUse(MI.getOperand(2).getReg());
1064
Tim Northover0f140c72016-09-09 11:46:34 +00001065 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1066 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1067 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1068 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001069 MI.eraseFromParent();
1070 return Legalized;
1071 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001072 case TargetOpcode::G_SMULO:
1073 case TargetOpcode::G_UMULO: {
1074 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1075 // result.
1076 unsigned Res = MI.getOperand(0).getReg();
1077 unsigned Overflow = MI.getOperand(1).getReg();
1078 unsigned LHS = MI.getOperand(2).getReg();
1079 unsigned RHS = MI.getOperand(3).getReg();
1080
1081 MIRBuilder.buildMul(Res, LHS, RHS);
1082
1083 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1084 ? TargetOpcode::G_SMULH
1085 : TargetOpcode::G_UMULH;
1086
1087 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1088 MIRBuilder.buildInstr(Opcode)
1089 .addDef(HiPart)
1090 .addUse(LHS)
1091 .addUse(RHS);
1092
1093 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1094 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001095
1096 // For *signed* multiply, overflow is detected by checking:
1097 // (hi != (lo >> bitwidth-1))
1098 if (Opcode == TargetOpcode::G_SMULH) {
1099 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1100 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1101 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1102 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1103 .addDef(Shifted)
1104 .addUse(Res)
1105 .addUse(ShiftAmt);
1106 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1107 } else {
1108 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1109 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001110 MI.eraseFromParent();
1111 return Legalized;
1112 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001113 case TargetOpcode::G_FNEG: {
1114 // TODO: Handle vector types once we are able to
1115 // represent them.
1116 if (Ty.isVector())
1117 return UnableToLegalize;
1118 unsigned Res = MI.getOperand(0).getReg();
1119 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001120 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001121 switch (Ty.getSizeInBits()) {
1122 case 16:
1123 ZeroTy = Type::getHalfTy(Ctx);
1124 break;
1125 case 32:
1126 ZeroTy = Type::getFloatTy(Ctx);
1127 break;
1128 case 64:
1129 ZeroTy = Type::getDoubleTy(Ctx);
1130 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001131 case 128:
1132 ZeroTy = Type::getFP128Ty(Ctx);
1133 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001134 default:
1135 llvm_unreachable("unexpected floating-point type");
1136 }
1137 ConstantFP &ZeroForNegation =
1138 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001139 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001140 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1141 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001142 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001143 .addUse(MI.getOperand(1).getReg());
1144 MI.eraseFromParent();
1145 return Legalized;
1146 }
Volkan Keles225921a2017-03-10 21:25:09 +00001147 case TargetOpcode::G_FSUB: {
1148 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1149 // First, check if G_FNEG is marked as Lower. If so, we may
1150 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001151 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001152 return UnableToLegalize;
1153 unsigned Res = MI.getOperand(0).getReg();
1154 unsigned LHS = MI.getOperand(1).getReg();
1155 unsigned RHS = MI.getOperand(2).getReg();
1156 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1157 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1158 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1159 .addDef(Res)
1160 .addUse(LHS)
1161 .addUse(Neg);
1162 MI.eraseFromParent();
1163 return Legalized;
1164 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001165 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1166 unsigned OldValRes = MI.getOperand(0).getReg();
1167 unsigned SuccessRes = MI.getOperand(1).getReg();
1168 unsigned Addr = MI.getOperand(2).getReg();
1169 unsigned CmpVal = MI.getOperand(3).getReg();
1170 unsigned NewVal = MI.getOperand(4).getReg();
1171 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1172 **MI.memoperands_begin());
1173 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1174 MI.eraseFromParent();
1175 return Legalized;
1176 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001177 case TargetOpcode::G_LOAD:
1178 case TargetOpcode::G_SEXTLOAD:
1179 case TargetOpcode::G_ZEXTLOAD: {
1180 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1181 unsigned DstReg = MI.getOperand(0).getReg();
1182 unsigned PtrReg = MI.getOperand(1).getReg();
1183 LLT DstTy = MRI.getType(DstReg);
1184 auto &MMO = **MI.memoperands_begin();
1185
1186 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001187 // In the case of G_LOAD, this was a non-extending load already and we're
1188 // about to lower to the same instruction.
1189 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1190 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001191 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1192 MI.eraseFromParent();
1193 return Legalized;
1194 }
1195
1196 if (DstTy.isScalar()) {
1197 unsigned TmpReg = MRI.createGenericVirtualRegister(
1198 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1199 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1200 switch (MI.getOpcode()) {
1201 default:
1202 llvm_unreachable("Unexpected opcode");
1203 case TargetOpcode::G_LOAD:
1204 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1205 break;
1206 case TargetOpcode::G_SEXTLOAD:
1207 MIRBuilder.buildSExt(DstReg, TmpReg);
1208 break;
1209 case TargetOpcode::G_ZEXTLOAD:
1210 MIRBuilder.buildZExt(DstReg, TmpReg);
1211 break;
1212 }
1213 MI.eraseFromParent();
1214 return Legalized;
1215 }
1216
1217 return UnableToLegalize;
1218 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001219 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1220 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1221 case TargetOpcode::G_CTLZ:
1222 case TargetOpcode::G_CTTZ:
1223 case TargetOpcode::G_CTPOP:
1224 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001225 case G_UADDE: {
1226 unsigned Res = MI.getOperand(0).getReg();
1227 unsigned CarryOut = MI.getOperand(1).getReg();
1228 unsigned LHS = MI.getOperand(2).getReg();
1229 unsigned RHS = MI.getOperand(3).getReg();
1230 unsigned CarryIn = MI.getOperand(4).getReg();
1231
1232 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1233 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1234
1235 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1236 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1237 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1238 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1239
1240 MI.eraseFromParent();
1241 return Legalized;
1242 }
Tim Northovercecee562016-08-26 17:46:13 +00001243 }
1244}
1245
Tim Northover69fa84a2016-10-14 22:18:18 +00001246LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001247LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1248 LLT NarrowTy) {
1249 if (TypeIdx != 0)
1250 return UnableToLegalize;
1251
1252 unsigned DstReg = MI.getOperand(0).getReg();
1253 unsigned SrcReg = MI.getOperand(1).getReg();
1254 LLT DstTy = MRI.getType(DstReg);
1255 LLT SrcTy = MRI.getType(SrcReg);
1256
1257 LLT NarrowTy0 = NarrowTy;
1258 LLT NarrowTy1;
1259 unsigned NumParts;
1260
1261 if (NarrowTy.isScalar()) {
1262 NumParts = DstTy.getNumElements();
1263 NarrowTy1 = SrcTy.getElementType();
1264 } else {
1265 // Uneven breakdown not handled.
1266 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1267 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1268 return UnableToLegalize;
1269
1270 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
1271 }
1272
1273 SmallVector<unsigned, 4> SrcRegs, DstRegs;
1274 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1275
1276 for (unsigned I = 0; I < NumParts; ++I) {
1277 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1278 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1279 .addDef(DstReg)
1280 .addUse(SrcRegs[I]);
1281
1282 NewInst->setFlags(MI.getFlags());
1283 DstRegs.push_back(DstReg);
1284 }
1285
1286 if (NarrowTy.isVector())
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001287 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1288 else
1289 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1290
1291 MI.eraseFromParent();
1292 return Legalized;
1293}
1294
1295LegalizerHelper::LegalizeResult
1296LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1297 LLT NarrowTy) {
1298 unsigned DstReg = MI.getOperand(0).getReg();
1299 unsigned Src0Reg = MI.getOperand(2).getReg();
1300 LLT DstTy = MRI.getType(DstReg);
1301 LLT SrcTy = MRI.getType(Src0Reg);
1302
1303 unsigned NumParts;
1304 LLT NarrowTy0, NarrowTy1;
1305
1306 if (TypeIdx == 0) {
1307 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1308 unsigned OldElts = DstTy.getNumElements();
1309
1310 NarrowTy0 = NarrowTy;
1311 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
1312 NarrowTy1 = NarrowTy.isVector() ?
1313 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
1314 SrcTy.getElementType();
1315
1316 } else {
1317 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1318 unsigned OldElts = SrcTy.getNumElements();
1319
1320 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
1321 NarrowTy.getNumElements();
1322 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
1323 DstTy.getScalarSizeInBits());
1324 NarrowTy1 = NarrowTy;
1325 }
1326
1327 // FIXME: Don't know how to handle the situation where the small vectors
1328 // aren't all the same size yet.
1329 if (NarrowTy1.isVector() &&
1330 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
1331 return UnableToLegalize;
1332
1333 CmpInst::Predicate Pred
1334 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
1335
1336 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1337 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
1338 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
1339
1340 for (unsigned I = 0; I < NumParts; ++I) {
1341 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1342 DstRegs.push_back(DstReg);
1343
1344 if (MI.getOpcode() == TargetOpcode::G_ICMP)
1345 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1346 else {
1347 MachineInstr *NewCmp
1348 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1349 NewCmp->setFlags(MI.getFlags());
1350 }
1351 }
1352
1353 if (NarrowTy0.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00001354 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1355 else
1356 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1357
1358 MI.eraseFromParent();
1359 return Legalized;
1360}
1361
1362LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001363LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1364 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001365 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00001366
1367 MIRBuilder.setInstr(MI);
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001368 unsigned Opc = MI.getOpcode();
1369 switch (Opc) {
Tim Northover33b07d62016-07-22 20:03:43 +00001370 default:
1371 return UnableToLegalize;
Matt Arsenault3dddb162019-01-09 07:51:52 +00001372 case TargetOpcode::G_IMPLICIT_DEF: {
1373 SmallVector<unsigned, 2> DstRegs;
1374
1375 unsigned NarrowSize = NarrowTy.getSizeInBits();
1376 unsigned DstReg = MI.getOperand(0).getReg();
1377 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1378 int NumParts = Size / NarrowSize;
1379 // FIXME: Don't know how to handle the situation where the small vectors
1380 // aren't all the same size yet.
1381 if (Size % NarrowSize != 0)
1382 return UnableToLegalize;
1383
1384 for (int i = 0; i < NumParts; ++i) {
1385 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1386 MIRBuilder.buildUndef(TmpReg);
1387 DstRegs.push_back(TmpReg);
1388 }
1389
1390 if (NarrowTy.isVector())
1391 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1392 else
1393 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1394
1395 MI.eraseFromParent();
1396 return Legalized;
1397 }
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001398 case TargetOpcode::G_ADD:
1399 case TargetOpcode::G_FADD:
1400 case TargetOpcode::G_FMUL:
1401 case TargetOpcode::G_FSUB:
1402 case TargetOpcode::G_FNEG:
1403 case TargetOpcode::G_FABS:
1404 case TargetOpcode::G_FDIV:
1405 case TargetOpcode::G_FREM:
Jessica Paquette245047d2019-01-24 22:00:41 +00001406 case TargetOpcode::G_FMA:
1407 case TargetOpcode::G_FCEIL: {
Tim Northover33b07d62016-07-22 20:03:43 +00001408 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +00001409 unsigned DstReg = MI.getOperand(0).getReg();
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001410 unsigned Flags = MI.getFlags();
Kristof Beylsaf9814a2017-11-07 10:34:34 +00001411 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1412 int NumParts = Size / NarrowSize;
1413 // FIXME: Don't know how to handle the situation where the small vectors
1414 // aren't all the same size yet.
1415 if (Size % NarrowSize != 0)
1416 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001417
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001418 unsigned NumOps = MI.getNumOperands() - 1;
1419 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1420
1421 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1422
1423 if (NumOps >= 2)
1424 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1425
1426 if (NumOps >= 3)
1427 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
Tim Northover33b07d62016-07-22 20:03:43 +00001428
1429 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +00001430 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001431
1432 if (NumOps == 1)
1433 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1434 else if (NumOps == 2) {
1435 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1436 } else if (NumOps == 3) {
1437 MIRBuilder.buildInstr(Opc, {DstReg},
1438 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1439 }
1440
Tim Northover33b07d62016-07-22 20:03:43 +00001441 DstRegs.push_back(DstReg);
1442 }
1443
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001444 if (NarrowTy.isVector())
1445 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1446 else
1447 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1448
Tim Northover33b07d62016-07-22 20:03:43 +00001449 MI.eraseFromParent();
1450 return Legalized;
1451 }
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001452 case TargetOpcode::G_ICMP:
1453 case TargetOpcode::G_FCMP:
1454 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Volkan Keles574d7372018-12-14 22:11:20 +00001455 case TargetOpcode::G_LOAD:
1456 case TargetOpcode::G_STORE: {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001457 // FIXME: Don't know how to handle secondary types yet.
1458 if (TypeIdx != 0)
1459 return UnableToLegalize;
1460
Volkan Keles574d7372018-12-14 22:11:20 +00001461 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1462 unsigned ValReg = MI.getOperand(0).getReg();
1463 unsigned AddrReg = MI.getOperand(1).getReg();
1464 unsigned NarrowSize = NarrowTy.getSizeInBits();
1465 unsigned Size = MRI.getType(ValReg).getSizeInBits();
1466 unsigned NumParts = Size / NarrowSize;
1467
1468 SmallVector<unsigned, 8> NarrowRegs;
1469 if (!IsLoad)
1470 extractParts(ValReg, NarrowTy, NumParts, NarrowRegs);
1471
1472 const LLT OffsetTy =
1473 LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1474 MachineFunction &MF = *MI.getMF();
1475 MachineMemOperand *MMO = *MI.memoperands_begin();
1476 for (unsigned Idx = 0; Idx < NumParts; ++Idx) {
1477 unsigned Adjustment = Idx * NarrowTy.getSizeInBits() / 8;
1478 unsigned Alignment = MinAlign(MMO->getAlignment(), Adjustment);
1479 unsigned NewAddrReg = 0;
1480 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, Adjustment);
1481 MachineMemOperand &NewMMO = *MF.getMachineMemOperand(
1482 MMO->getPointerInfo().getWithOffset(Adjustment), MMO->getFlags(),
1483 NarrowTy.getSizeInBits() / 8, Alignment);
1484 if (IsLoad) {
1485 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
1486 NarrowRegs.push_back(Dst);
1487 MIRBuilder.buildLoad(Dst, NewAddrReg, NewMMO);
1488 } else {
1489 MIRBuilder.buildStore(NarrowRegs[Idx], NewAddrReg, NewMMO);
1490 }
1491 }
1492 if (IsLoad) {
1493 if (NarrowTy.isVector())
1494 MIRBuilder.buildConcatVectors(ValReg, NarrowRegs);
1495 else
1496 MIRBuilder.buildBuildVector(ValReg, NarrowRegs);
1497 }
1498 MI.eraseFromParent();
1499 return Legalized;
1500 }
Matt Arsenaultca676342019-01-25 02:36:32 +00001501 case TargetOpcode::G_ZEXT:
1502 case TargetOpcode::G_SEXT:
1503 case TargetOpcode::G_ANYEXT:
1504 case TargetOpcode::G_FPEXT:
1505 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00001506 }
1507}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001508
1509LegalizerHelper::LegalizeResult
1510LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1511 unsigned Opc = MI.getOpcode();
1512 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00001513 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001514 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00001515 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001516 };
1517 switch (Opc) {
1518 default:
1519 return UnableToLegalize;
1520 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1521 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001522 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001523 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001524 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001525 return Legalized;
1526 }
1527 case TargetOpcode::G_CTLZ: {
1528 unsigned SrcReg = MI.getOperand(1).getReg();
1529 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001530 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1531 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001532 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
1533 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001534 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1535 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1536 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1537 SrcReg, MIBZero);
1538 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1539 MIBCtlzZU);
1540 MI.eraseFromParent();
1541 return Legalized;
1542 }
1543 // for now, we do this:
1544 // NewLen = NextPowerOf2(Len);
1545 // x = x | (x >> 1);
1546 // x = x | (x >> 2);
1547 // ...
1548 // x = x | (x >>16);
1549 // x = x | (x >>32); // for 64-bit input
1550 // Upto NewLen/2
1551 // return Len - popcount(x);
1552 //
1553 // Ref: "Hacker's Delight" by Henry Warren
1554 unsigned Op = SrcReg;
1555 unsigned NewLen = PowerOf2Ceil(Len);
1556 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1557 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1558 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001559 TargetOpcode::G_OR, {Ty},
1560 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
1561 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001562 Op = MIBOp->getOperand(0).getReg();
1563 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001564 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
1565 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1566 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001567 MI.eraseFromParent();
1568 return Legalized;
1569 }
1570 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1571 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001572 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001573 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001574 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001575 return Legalized;
1576 }
1577 case TargetOpcode::G_CTTZ: {
1578 unsigned SrcReg = MI.getOperand(1).getReg();
1579 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001580 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001581 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1582 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001583 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
1584 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001585 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1586 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1587 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1588 SrcReg, MIBZero);
1589 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1590 MIBCttzZU);
1591 MI.eraseFromParent();
1592 return Legalized;
1593 }
1594 // for now, we use: { return popcount(~x & (x - 1)); }
1595 // unless the target has ctlz but not ctpop, in which case we use:
1596 // { return 32 - nlz(~x & (x-1)); }
1597 // Ref: "Hacker's Delight" by Henry Warren
1598 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
1599 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001600 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001601 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001602 TargetOpcode::G_AND, {Ty},
1603 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
1604 {SrcReg, MIBCstNeg1})});
Diana Picus0528e2c2018-11-26 11:07:02 +00001605 if (!isSupported({TargetOpcode::G_CTPOP, {Ty}}) &&
1606 isSupported({TargetOpcode::G_CTLZ, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001607 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
1608 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001609 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1610 {MIBCstLen,
1611 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001612 MI.eraseFromParent();
1613 return Legalized;
1614 }
1615 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
1616 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
1617 return Legalized;
1618 }
1619 }
1620}