blob: 2ab35645064268952a299c273aee459ff47c5341 [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 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000346 case TargetOpcode::G_MUL:
347 return narrowScalarMul(MI, TypeIdx, NarrowTy);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000348 case TargetOpcode::G_EXTRACT: {
349 if (TypeIdx != 1)
350 return UnableToLegalize;
351
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000352 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
353 // FIXME: add support for when SizeOp1 isn't an exact multiple of
354 // NarrowSize.
355 if (SizeOp1 % NarrowSize != 0)
356 return UnableToLegalize;
357 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000358
359 SmallVector<unsigned, 2> SrcRegs, DstRegs;
360 SmallVector<uint64_t, 2> Indexes;
361 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
362
363 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000364 uint64_t OpStart = MI.getOperand(2).getImm();
365 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000366 for (int i = 0; i < NumParts; ++i) {
367 unsigned SrcStart = i * NarrowSize;
368
369 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
370 // No part of the extract uses this subregister, ignore it.
371 continue;
372 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
373 // The entire subregister is extracted, forward the value.
374 DstRegs.push_back(SrcRegs[i]);
375 continue;
376 }
377
378 // OpSegStart is where this destination segment would start in OpReg if it
379 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000380 int64_t ExtractOffset;
381 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000382 if (OpStart < SrcStart) {
383 ExtractOffset = 0;
384 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
385 } else {
386 ExtractOffset = OpStart - SrcStart;
387 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
388 }
389
390 unsigned SegReg = SrcRegs[i];
391 if (ExtractOffset != 0 || SegSize != NarrowSize) {
392 // A genuine extract is needed.
393 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
394 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
395 }
396
397 DstRegs.push_back(SegReg);
398 }
399
Amara Emerson5ec14602018-12-10 18:44:58 +0000400 unsigned DstReg = MI.getOperand(0).getReg();
401 if(MRI.getType(DstReg).isVector())
402 MIRBuilder.buildBuildVector(DstReg, DstRegs);
403 else
404 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000405 MI.eraseFromParent();
406 return Legalized;
407 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000408 case TargetOpcode::G_INSERT: {
Matt Arsenault30989e42019-01-22 21:42:11 +0000409 // FIXME: Don't know how to handle secondary types yet.
410 if (TypeIdx != 0)
411 return UnableToLegalize;
412
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000413 // FIXME: add support for when SizeOp0 isn't an exact multiple of
414 // NarrowSize.
415 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000416 return UnableToLegalize;
417
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000418 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000419
420 SmallVector<unsigned, 2> SrcRegs, DstRegs;
421 SmallVector<uint64_t, 2> Indexes;
422 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
423
Tim Northover75e0b912017-03-06 18:23:04 +0000424 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000425 uint64_t OpStart = MI.getOperand(3).getImm();
426 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000427 for (int i = 0; i < NumParts; ++i) {
428 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000429
Tim Northover75e0b912017-03-06 18:23:04 +0000430 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000431 // No part of the insert affects this subregister, forward the original.
432 DstRegs.push_back(SrcRegs[i]);
433 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000434 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000435 // The entire subregister is defined by this insert, forward the new
436 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000437 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000438 continue;
439 }
440
Tim Northover2eb18d32017-03-07 21:24:33 +0000441 // OpSegStart is where this destination segment would start in OpReg if it
442 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000443 int64_t ExtractOffset, InsertOffset;
444 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000445 if (OpStart < DstStart) {
446 InsertOffset = 0;
447 ExtractOffset = DstStart - OpStart;
448 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
449 } else {
450 InsertOffset = OpStart - DstStart;
451 ExtractOffset = 0;
452 SegSize =
453 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
454 }
455
456 unsigned SegReg = OpReg;
457 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000458 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000459 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
460 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000461 }
462
Tim Northover75e0b912017-03-06 18:23:04 +0000463 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000464 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000465 DstRegs.push_back(DstReg);
466 }
467
468 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000469 unsigned DstReg = MI.getOperand(0).getReg();
470 if(MRI.getType(DstReg).isVector())
471 MIRBuilder.buildBuildVector(DstReg, DstRegs);
472 else
473 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000474 MI.eraseFromParent();
475 return Legalized;
476 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000477 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000478 // FIXME: add support for when SizeOp0 isn't an exact multiple of
479 // NarrowSize.
480 if (SizeOp0 % NarrowSize != 0)
481 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000482
483 const auto &MMO = **MI.memoperands_begin();
484 // This implementation doesn't work for atomics. Give up instead of doing
485 // something invalid.
486 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
487 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
488 return UnableToLegalize;
489
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000490 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000491 LLT OffsetTy = LLT::scalar(
492 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000493
494 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000495 for (int i = 0; i < NumParts; ++i) {
496 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000497 unsigned SrcReg = 0;
498 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000499 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000500
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000501 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
502 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000503 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
504 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000505
Daniel Sanders4e523662017-06-13 23:42:32 +0000506 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
507 Adjustment);
508
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000509 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000510
511 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000512 }
513 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000514 if(MRI.getType(DstReg).isVector())
515 MIRBuilder.buildBuildVector(DstReg, DstRegs);
516 else
517 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000518 MI.eraseFromParent();
519 return Legalized;
520 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000521 case TargetOpcode::G_ZEXTLOAD:
522 case TargetOpcode::G_SEXTLOAD: {
523 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
524 unsigned DstReg = MI.getOperand(0).getReg();
525 unsigned PtrReg = MI.getOperand(1).getReg();
526
527 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
528 auto &MMO = **MI.memoperands_begin();
529 if (MMO.getSize() * 8 == NarrowSize) {
530 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
531 } else {
532 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
533 : TargetOpcode::G_SEXTLOAD;
534 MIRBuilder.buildInstr(ExtLoad)
535 .addDef(TmpReg)
536 .addUse(PtrReg)
537 .addMemOperand(&MMO);
538 }
539
540 if (ZExt)
541 MIRBuilder.buildZExt(DstReg, TmpReg);
542 else
543 MIRBuilder.buildSExt(DstReg, TmpReg);
544
545 MI.eraseFromParent();
546 return Legalized;
547 }
Justin Bognerfde01042017-01-18 17:29:54 +0000548 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000549 // FIXME: add support for when SizeOp0 isn't an exact multiple of
550 // NarrowSize.
551 if (SizeOp0 % NarrowSize != 0)
552 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000553
554 const auto &MMO = **MI.memoperands_begin();
555 // This implementation doesn't work for atomics. Give up instead of doing
556 // something invalid.
557 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
558 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
559 return UnableToLegalize;
560
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000561 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000562 LLT OffsetTy = LLT::scalar(
563 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000564
565 SmallVector<unsigned, 2> SrcRegs;
566 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
567
568 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000569 unsigned DstReg = 0;
570 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000571 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Daniel Sanders4e523662017-06-13 23:42:32 +0000572
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000573 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
574 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000575 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
576 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000577
Daniel Sanders4e523662017-06-13 23:42:32 +0000578 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
579 Adjustment);
580
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000581 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000582 }
583 MI.eraseFromParent();
584 return Legalized;
585 }
Igor Breger29537882017-04-07 14:41:59 +0000586 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000587 // FIXME: add support for when SizeOp0 isn't an exact multiple of
588 // NarrowSize.
589 if (SizeOp0 % NarrowSize != 0)
590 return UnableToLegalize;
591 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000592 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000593 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000594
595 SmallVector<unsigned, 2> DstRegs;
596 for (int i = 0; i < NumParts; ++i) {
597 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
598 ConstantInt *CI =
599 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
600 MIRBuilder.buildConstant(DstReg, *CI);
601 DstRegs.push_back(DstReg);
602 }
603 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000604 if(MRI.getType(DstReg).isVector())
605 MIRBuilder.buildBuildVector(DstReg, DstRegs);
606 else
607 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000608 MI.eraseFromParent();
609 return Legalized;
610 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000611 case TargetOpcode::G_AND:
612 case TargetOpcode::G_OR:
613 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000614 // Legalize bitwise operation:
615 // A = BinOp<Ty> B, C
616 // into:
617 // B1, ..., BN = G_UNMERGE_VALUES B
618 // C1, ..., CN = G_UNMERGE_VALUES C
619 // A1 = BinOp<Ty/N> B1, C2
620 // ...
621 // AN = BinOp<Ty/N> BN, CN
622 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000623
624 // FIXME: add support for when SizeOp0 isn't an exact multiple of
625 // NarrowSize.
626 if (SizeOp0 % NarrowSize != 0)
627 return UnableToLegalize;
628 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000629
630 // List the registers where the destination will be scattered.
631 SmallVector<unsigned, 2> DstRegs;
632 // List the registers where the first argument will be split.
633 SmallVector<unsigned, 2> SrcsReg1;
634 // List the registers where the second argument will be split.
635 SmallVector<unsigned, 2> SrcsReg2;
636 // Create all the temporary registers.
637 for (int i = 0; i < NumParts; ++i) {
638 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
639 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
640 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
641
642 DstRegs.push_back(DstReg);
643 SrcsReg1.push_back(SrcReg1);
644 SrcsReg2.push_back(SrcReg2);
645 }
646 // Explode the big arguments into smaller chunks.
647 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
648 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
649
650 // Do the operation on each small part.
651 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000652 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
653 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000654
655 // Gather the destination registers into the final destination.
656 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000657 if(MRI.getType(DstReg).isVector())
658 MIRBuilder.buildBuildVector(DstReg, DstRegs);
659 else
660 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000661 MI.eraseFromParent();
662 return Legalized;
663 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000664 case TargetOpcode::G_SHL:
665 case TargetOpcode::G_LSHR:
666 case TargetOpcode::G_ASHR: {
667 if (TypeIdx != 1)
668 return UnableToLegalize; // TODO
669 narrowScalarSrc(MI, NarrowTy, 2);
670 return Legalized;
671 }
Tim Northover9656f142016-08-04 20:54:13 +0000672 }
Tim Northover33b07d62016-07-22 20:03:43 +0000673}
674
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000675void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
676 unsigned OpIdx, unsigned ExtOpcode) {
677 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000678 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000679 MO.setReg(ExtB->getOperand(0).getReg());
680}
681
Matt Arsenault30989e42019-01-22 21:42:11 +0000682void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
683 unsigned OpIdx) {
684 MachineOperand &MO = MI.getOperand(OpIdx);
685 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
686 {MO.getReg()});
687 MO.setReg(ExtB->getOperand(0).getReg());
688}
689
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000690void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
691 unsigned OpIdx, unsigned TruncOpcode) {
692 MachineOperand &MO = MI.getOperand(OpIdx);
693 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
694 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000695 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000696 MO.setReg(DstExt);
697}
698
Tim Northover69fa84a2016-10-14 22:18:18 +0000699LegalizerHelper::LegalizeResult
700LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000701 MIRBuilder.setInstr(MI);
702
Tim Northover32335812016-08-04 18:35:11 +0000703 switch (MI.getOpcode()) {
704 default:
705 return UnableToLegalize;
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000706 case TargetOpcode::G_UADDO:
707 case TargetOpcode::G_USUBO: {
708 if (TypeIdx == 1)
709 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000710 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
711 {MI.getOperand(2).getReg()});
712 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
713 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000714 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
715 ? TargetOpcode::G_ADD
716 : TargetOpcode::G_SUB;
717 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000718 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000719 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
720 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
721 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000722 TargetOpcode::G_AND, {WideTy},
723 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000724 // There is no overflow if the AndOp is the same as NewOp.
725 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
726 AndOp);
727 // Now trunc the NewOp to the original result.
728 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
729 MI.eraseFromParent();
730 return Legalized;
731 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000732 case TargetOpcode::G_CTTZ:
733 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
734 case TargetOpcode::G_CTLZ:
735 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
736 case TargetOpcode::G_CTPOP: {
737 // First ZEXT the input.
738 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
739 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
740 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
741 // The count is the same in the larger type except if the original
742 // value was zero. This can be handled by setting the bit just off
743 // the top of the original type.
744 auto TopBit =
745 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
746 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000747 TargetOpcode::G_OR, {WideTy},
748 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000749 }
750 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000751 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000752 // This is already the correct result for CTPOP and CTTZs
753 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
754 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
755 // The correct result is NewOp - (Difference in widety and current ty).
756 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000757 MIBNewOp = MIRBuilder.buildInstr(
758 TargetOpcode::G_SUB, {WideTy},
759 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000760 }
761 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +0000762 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000763 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000764 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
765 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000766 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000767 return Legalized;
768 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000769
Tim Northover61c16142016-08-04 21:39:49 +0000770 case TargetOpcode::G_ADD:
771 case TargetOpcode::G_AND:
772 case TargetOpcode::G_MUL:
773 case TargetOpcode::G_OR:
774 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000775 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000776 // Perform operation at larger width (any extension is fine here, high bits
777 // don't affect the result) and then truncate the result back to the
778 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000779 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000780 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
781 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
782 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000783 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000784 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000785
Roman Tereshin6d266382018-05-09 21:43:30 +0000786 case TargetOpcode::G_SHL:
Matt Arsenault30989e42019-01-22 21:42:11 +0000787 Observer.changingInstr(MI);
788
789 if (TypeIdx == 0) {
790 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
791 widenScalarDst(MI, WideTy);
792 } else {
793 assert(TypeIdx == 1);
794 // The "number of bits to shift" operand must preserve its value as an
795 // unsigned integer:
796 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
797 }
798
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000799 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000800 return Legalized;
801
Tim Northover7a753d92016-08-26 17:46:06 +0000802 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000803 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000804 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000805 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
806 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
807 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000808 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000809 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000810
Roman Tereshin6d266382018-05-09 21:43:30 +0000811 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +0000812 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000813 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +0000814
815 if (TypeIdx == 0) {
816 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
817 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
818
819 widenScalarSrc(MI, WideTy, 1, CvtOp);
820 widenScalarDst(MI, WideTy);
821 } else {
822 assert(TypeIdx == 1);
823 // The "number of bits to shift" operand must preserve its value as an
824 // unsigned integer:
825 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
826 }
827
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000828 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000829 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000830 case TargetOpcode::G_UDIV:
831 case TargetOpcode::G_UREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000832 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000833 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
834 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
835 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000836 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000837 return Legalized;
838
839 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000840 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +0000841 if (TypeIdx == 0) {
842 // Perform operation at larger width (any extension is fine here, high
843 // bits don't affect the result) and then truncate the result back to the
844 // original type.
845 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
846 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
847 widenScalarDst(MI, WideTy);
848 } else {
849 // Explicit extension is required here since high bits affect the result.
850 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
851 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000852 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000853 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000854
Ahmed Bougachab6137062017-01-23 21:10:14 +0000855 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000856 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +0000857 if (TypeIdx != 0)
858 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000859 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000860 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000861 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000862 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000863
Ahmed Bougachad2948232017-01-20 01:37:24 +0000864 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +0000865 if (TypeIdx != 1)
866 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000867 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000868 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000869 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000870 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000871
872 case TargetOpcode::G_UITOFP:
873 if (TypeIdx != 1)
874 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000875 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000876 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000877 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000878 return Legalized;
879
880 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +0000881 if (TypeIdx != 0)
882 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000883 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000884 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
885 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000886 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000887 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000888
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000889 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +0000890 // For some types like i24, we might try to widen to i32. To properly handle
891 // this we should be using a dedicated extending load, until then avoid
892 // trying to legalize.
893 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
894 WideTy.getSizeInBits())
895 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000896 LLVM_FALLTHROUGH;
897 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000898 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000899 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000900 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000901 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000902 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000903
Tim Northover3c73e362016-08-23 18:20:09 +0000904 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000905 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
906 WideTy != LLT::scalar(8))
907 return UnableToLegalize;
908
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000909 Observer.changingInstr(MI);
Amara Emerson5a3bb682018-06-01 13:20:32 +0000910 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000911 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000912 return Legalized;
913 }
Tim Northoverea904f92016-08-19 22:40:00 +0000914 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000915 MachineOperand &SrcMO = MI.getOperand(1);
916 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
917 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000918 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000919 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
920
921 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000922 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +0000923 return Legalized;
924 }
Tim Northovera11be042016-08-19 22:40:08 +0000925 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000926 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +0000927 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000928 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +0000929 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000930 switch (WideTy.getSizeInBits()) {
931 case 32:
932 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
933 break;
934 case 64:
935 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
936 break;
937 default:
938 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +0000939 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000940 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000941 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
942
943 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000944 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +0000945 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +0000946 }
Matt Arsenaultbefee402019-01-09 07:34:14 +0000947 case TargetOpcode::G_IMPLICIT_DEF: {
948 Observer.changingInstr(MI);
949 widenScalarDst(MI, WideTy);
950 Observer.changedInstr(MI);
951 return Legalized;
952 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000953 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000954 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000955 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000956 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000957 return Legalized;
958
959 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000960 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000961 if (TypeIdx == 0)
962 widenScalarDst(MI, WideTy);
963 else {
964 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
965 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +0000966 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000967 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000968 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000969
970 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000971 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000972 if (TypeIdx == 0)
973 widenScalarDst(MI, WideTy);
974 else {
975 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
976 MI.getOperand(1).getPredicate()))
977 ? TargetOpcode::G_SEXT
978 : TargetOpcode::G_ZEXT;
979 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
980 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
981 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000982 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000983 return Legalized;
984
985 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +0000986 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000987 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000988 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000989 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +0000990 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000991
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000992 case TargetOpcode::G_PHI: {
993 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000994
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000995 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000996 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
997 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
998 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
999 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001000 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001001
1002 MachineBasicBlock &MBB = *MI.getParent();
1003 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1004 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001005 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001006 return Legalized;
1007 }
Matt Arsenault63786292019-01-22 20:38:15 +00001008 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1009 if (TypeIdx == 0) {
1010 unsigned VecReg = MI.getOperand(1).getReg();
1011 LLT VecTy = MRI.getType(VecReg);
1012 Observer.changingInstr(MI);
1013
1014 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1015 WideTy.getSizeInBits()),
1016 1, TargetOpcode::G_SEXT);
1017
1018 widenScalarDst(MI, WideTy, 0);
1019 Observer.changedInstr(MI);
1020 return Legalized;
1021 }
1022
Amara Emersoncbd86d82018-10-25 14:04:54 +00001023 if (TypeIdx != 2)
1024 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001025 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001026 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001027 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001028 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001029 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001030 case TargetOpcode::G_FADD:
1031 case TargetOpcode::G_FMUL:
1032 case TargetOpcode::G_FSUB:
1033 case TargetOpcode::G_FMA:
1034 case TargetOpcode::G_FNEG:
1035 case TargetOpcode::G_FABS:
1036 case TargetOpcode::G_FDIV:
1037 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001038 case TargetOpcode::G_FCEIL:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001039 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001040 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001041
1042 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1043 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1044
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001045 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1046 Observer.changedInstr(MI);
1047 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001048 }
Tim Northover33b07d62016-07-22 20:03:43 +00001049}
1050
Tim Northover69fa84a2016-10-14 22:18:18 +00001051LegalizerHelper::LegalizeResult
1052LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001053 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001054 MIRBuilder.setInstr(MI);
1055
1056 switch(MI.getOpcode()) {
1057 default:
1058 return UnableToLegalize;
1059 case TargetOpcode::G_SREM:
1060 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001061 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1062 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001063 .addDef(QuotReg)
1064 .addUse(MI.getOperand(1).getReg())
1065 .addUse(MI.getOperand(2).getReg());
1066
Tim Northover0f140c72016-09-09 11:46:34 +00001067 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1068 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1069 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1070 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001071 MI.eraseFromParent();
1072 return Legalized;
1073 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001074 case TargetOpcode::G_SMULO:
1075 case TargetOpcode::G_UMULO: {
1076 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1077 // result.
1078 unsigned Res = MI.getOperand(0).getReg();
1079 unsigned Overflow = MI.getOperand(1).getReg();
1080 unsigned LHS = MI.getOperand(2).getReg();
1081 unsigned RHS = MI.getOperand(3).getReg();
1082
1083 MIRBuilder.buildMul(Res, LHS, RHS);
1084
1085 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1086 ? TargetOpcode::G_SMULH
1087 : TargetOpcode::G_UMULH;
1088
1089 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1090 MIRBuilder.buildInstr(Opcode)
1091 .addDef(HiPart)
1092 .addUse(LHS)
1093 .addUse(RHS);
1094
1095 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1096 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001097
1098 // For *signed* multiply, overflow is detected by checking:
1099 // (hi != (lo >> bitwidth-1))
1100 if (Opcode == TargetOpcode::G_SMULH) {
1101 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1102 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1103 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1104 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1105 .addDef(Shifted)
1106 .addUse(Res)
1107 .addUse(ShiftAmt);
1108 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1109 } else {
1110 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1111 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001112 MI.eraseFromParent();
1113 return Legalized;
1114 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001115 case TargetOpcode::G_FNEG: {
1116 // TODO: Handle vector types once we are able to
1117 // represent them.
1118 if (Ty.isVector())
1119 return UnableToLegalize;
1120 unsigned Res = MI.getOperand(0).getReg();
1121 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001122 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001123 switch (Ty.getSizeInBits()) {
1124 case 16:
1125 ZeroTy = Type::getHalfTy(Ctx);
1126 break;
1127 case 32:
1128 ZeroTy = Type::getFloatTy(Ctx);
1129 break;
1130 case 64:
1131 ZeroTy = Type::getDoubleTy(Ctx);
1132 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001133 case 128:
1134 ZeroTy = Type::getFP128Ty(Ctx);
1135 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001136 default:
1137 llvm_unreachable("unexpected floating-point type");
1138 }
1139 ConstantFP &ZeroForNegation =
1140 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001141 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001142 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1143 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001144 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001145 .addUse(MI.getOperand(1).getReg());
1146 MI.eraseFromParent();
1147 return Legalized;
1148 }
Volkan Keles225921a2017-03-10 21:25:09 +00001149 case TargetOpcode::G_FSUB: {
1150 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1151 // First, check if G_FNEG is marked as Lower. If so, we may
1152 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001153 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001154 return UnableToLegalize;
1155 unsigned Res = MI.getOperand(0).getReg();
1156 unsigned LHS = MI.getOperand(1).getReg();
1157 unsigned RHS = MI.getOperand(2).getReg();
1158 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1159 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1160 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1161 .addDef(Res)
1162 .addUse(LHS)
1163 .addUse(Neg);
1164 MI.eraseFromParent();
1165 return Legalized;
1166 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001167 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1168 unsigned OldValRes = MI.getOperand(0).getReg();
1169 unsigned SuccessRes = MI.getOperand(1).getReg();
1170 unsigned Addr = MI.getOperand(2).getReg();
1171 unsigned CmpVal = MI.getOperand(3).getReg();
1172 unsigned NewVal = MI.getOperand(4).getReg();
1173 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1174 **MI.memoperands_begin());
1175 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1176 MI.eraseFromParent();
1177 return Legalized;
1178 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001179 case TargetOpcode::G_LOAD:
1180 case TargetOpcode::G_SEXTLOAD:
1181 case TargetOpcode::G_ZEXTLOAD: {
1182 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1183 unsigned DstReg = MI.getOperand(0).getReg();
1184 unsigned PtrReg = MI.getOperand(1).getReg();
1185 LLT DstTy = MRI.getType(DstReg);
1186 auto &MMO = **MI.memoperands_begin();
1187
1188 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001189 // In the case of G_LOAD, this was a non-extending load already and we're
1190 // about to lower to the same instruction.
1191 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1192 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001193 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1194 MI.eraseFromParent();
1195 return Legalized;
1196 }
1197
1198 if (DstTy.isScalar()) {
1199 unsigned TmpReg = MRI.createGenericVirtualRegister(
1200 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1201 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1202 switch (MI.getOpcode()) {
1203 default:
1204 llvm_unreachable("Unexpected opcode");
1205 case TargetOpcode::G_LOAD:
1206 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1207 break;
1208 case TargetOpcode::G_SEXTLOAD:
1209 MIRBuilder.buildSExt(DstReg, TmpReg);
1210 break;
1211 case TargetOpcode::G_ZEXTLOAD:
1212 MIRBuilder.buildZExt(DstReg, TmpReg);
1213 break;
1214 }
1215 MI.eraseFromParent();
1216 return Legalized;
1217 }
1218
1219 return UnableToLegalize;
1220 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001221 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1222 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1223 case TargetOpcode::G_CTLZ:
1224 case TargetOpcode::G_CTTZ:
1225 case TargetOpcode::G_CTPOP:
1226 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001227 case G_UADDE: {
1228 unsigned Res = MI.getOperand(0).getReg();
1229 unsigned CarryOut = MI.getOperand(1).getReg();
1230 unsigned LHS = MI.getOperand(2).getReg();
1231 unsigned RHS = MI.getOperand(3).getReg();
1232 unsigned CarryIn = MI.getOperand(4).getReg();
1233
1234 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1235 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1236
1237 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1238 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1239 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1240 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1241
1242 MI.eraseFromParent();
1243 return Legalized;
1244 }
Tim Northovercecee562016-08-26 17:46:13 +00001245 }
1246}
1247
Tim Northover69fa84a2016-10-14 22:18:18 +00001248LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001249LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1250 LLT NarrowTy) {
1251 if (TypeIdx != 0)
1252 return UnableToLegalize;
1253
1254 unsigned DstReg = MI.getOperand(0).getReg();
1255 unsigned SrcReg = MI.getOperand(1).getReg();
1256 LLT DstTy = MRI.getType(DstReg);
1257 LLT SrcTy = MRI.getType(SrcReg);
1258
1259 LLT NarrowTy0 = NarrowTy;
1260 LLT NarrowTy1;
1261 unsigned NumParts;
1262
1263 if (NarrowTy.isScalar()) {
1264 NumParts = DstTy.getNumElements();
1265 NarrowTy1 = SrcTy.getElementType();
1266 } else {
1267 // Uneven breakdown not handled.
1268 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1269 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1270 return UnableToLegalize;
1271
1272 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
1273 }
1274
1275 SmallVector<unsigned, 4> SrcRegs, DstRegs;
1276 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1277
1278 for (unsigned I = 0; I < NumParts; ++I) {
1279 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1280 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1281 .addDef(DstReg)
1282 .addUse(SrcRegs[I]);
1283
1284 NewInst->setFlags(MI.getFlags());
1285 DstRegs.push_back(DstReg);
1286 }
1287
1288 if (NarrowTy.isVector())
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001289 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1290 else
1291 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1292
1293 MI.eraseFromParent();
1294 return Legalized;
1295}
1296
1297LegalizerHelper::LegalizeResult
1298LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1299 LLT NarrowTy) {
1300 unsigned DstReg = MI.getOperand(0).getReg();
1301 unsigned Src0Reg = MI.getOperand(2).getReg();
1302 LLT DstTy = MRI.getType(DstReg);
1303 LLT SrcTy = MRI.getType(Src0Reg);
1304
1305 unsigned NumParts;
1306 LLT NarrowTy0, NarrowTy1;
1307
1308 if (TypeIdx == 0) {
1309 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1310 unsigned OldElts = DstTy.getNumElements();
1311
1312 NarrowTy0 = NarrowTy;
1313 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
1314 NarrowTy1 = NarrowTy.isVector() ?
1315 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
1316 SrcTy.getElementType();
1317
1318 } else {
1319 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1320 unsigned OldElts = SrcTy.getNumElements();
1321
1322 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
1323 NarrowTy.getNumElements();
1324 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
1325 DstTy.getScalarSizeInBits());
1326 NarrowTy1 = NarrowTy;
1327 }
1328
1329 // FIXME: Don't know how to handle the situation where the small vectors
1330 // aren't all the same size yet.
1331 if (NarrowTy1.isVector() &&
1332 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
1333 return UnableToLegalize;
1334
1335 CmpInst::Predicate Pred
1336 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
1337
1338 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1339 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
1340 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
1341
1342 for (unsigned I = 0; I < NumParts; ++I) {
1343 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1344 DstRegs.push_back(DstReg);
1345
1346 if (MI.getOpcode() == TargetOpcode::G_ICMP)
1347 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1348 else {
1349 MachineInstr *NewCmp
1350 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1351 NewCmp->setFlags(MI.getFlags());
1352 }
1353 }
1354
1355 if (NarrowTy0.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00001356 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1357 else
1358 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1359
1360 MI.eraseFromParent();
1361 return Legalized;
1362}
1363
1364LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001365LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1366 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001367 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00001368
1369 MIRBuilder.setInstr(MI);
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001370 unsigned Opc = MI.getOpcode();
1371 switch (Opc) {
Tim Northover33b07d62016-07-22 20:03:43 +00001372 default:
1373 return UnableToLegalize;
Matt Arsenault3dddb162019-01-09 07:51:52 +00001374 case TargetOpcode::G_IMPLICIT_DEF: {
1375 SmallVector<unsigned, 2> DstRegs;
1376
1377 unsigned NarrowSize = NarrowTy.getSizeInBits();
1378 unsigned DstReg = MI.getOperand(0).getReg();
1379 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1380 int NumParts = Size / NarrowSize;
1381 // FIXME: Don't know how to handle the situation where the small vectors
1382 // aren't all the same size yet.
1383 if (Size % NarrowSize != 0)
1384 return UnableToLegalize;
1385
1386 for (int i = 0; i < NumParts; ++i) {
1387 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1388 MIRBuilder.buildUndef(TmpReg);
1389 DstRegs.push_back(TmpReg);
1390 }
1391
1392 if (NarrowTy.isVector())
1393 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1394 else
1395 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1396
1397 MI.eraseFromParent();
1398 return Legalized;
1399 }
Matt Arsenault26a6c742019-01-26 23:47:07 +00001400 case TargetOpcode::G_AND:
1401 case TargetOpcode::G_OR:
1402 case TargetOpcode::G_XOR:
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001403 case TargetOpcode::G_ADD:
Matt Arsenault3e08b772019-01-25 04:53:57 +00001404 case TargetOpcode::G_SUB:
Matt Arsenault5d622fb2019-01-25 03:23:04 +00001405 case TargetOpcode::G_MUL:
1406 case TargetOpcode::G_SMULH:
1407 case TargetOpcode::G_UMULH:
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001408 case TargetOpcode::G_FADD:
1409 case TargetOpcode::G_FMUL:
1410 case TargetOpcode::G_FSUB:
1411 case TargetOpcode::G_FNEG:
1412 case TargetOpcode::G_FABS:
1413 case TargetOpcode::G_FDIV:
1414 case TargetOpcode::G_FREM:
Jessica Paquette245047d2019-01-24 22:00:41 +00001415 case TargetOpcode::G_FMA:
Matt Arsenault95fd95c2019-01-25 04:03:38 +00001416 case TargetOpcode::G_FPOW:
1417 case TargetOpcode::G_FEXP:
1418 case TargetOpcode::G_FEXP2:
1419 case TargetOpcode::G_FLOG:
1420 case TargetOpcode::G_FLOG2:
1421 case TargetOpcode::G_FLOG10:
Matt Arsenault2e5f9002019-01-27 00:12:21 +00001422 case TargetOpcode::G_FCEIL:
1423 case TargetOpcode::G_INTRINSIC_ROUND:
1424 case TargetOpcode::G_INTRINSIC_TRUNC: {
Tim Northover33b07d62016-07-22 20:03:43 +00001425 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +00001426 unsigned DstReg = MI.getOperand(0).getReg();
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001427 unsigned Flags = MI.getFlags();
Kristof Beylsaf9814a2017-11-07 10:34:34 +00001428 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1429 int NumParts = Size / NarrowSize;
1430 // FIXME: Don't know how to handle the situation where the small vectors
1431 // aren't all the same size yet.
1432 if (Size % NarrowSize != 0)
1433 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001434
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001435 unsigned NumOps = MI.getNumOperands() - 1;
1436 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1437
1438 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1439
1440 if (NumOps >= 2)
1441 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1442
1443 if (NumOps >= 3)
1444 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
Tim Northover33b07d62016-07-22 20:03:43 +00001445
1446 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +00001447 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001448
1449 if (NumOps == 1)
1450 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1451 else if (NumOps == 2) {
1452 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1453 } else if (NumOps == 3) {
1454 MIRBuilder.buildInstr(Opc, {DstReg},
1455 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1456 }
1457
Tim Northover33b07d62016-07-22 20:03:43 +00001458 DstRegs.push_back(DstReg);
1459 }
1460
Matt Arsenaultaebb2ee2019-01-22 20:14:29 +00001461 if (NarrowTy.isVector())
1462 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1463 else
1464 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1465
Tim Northover33b07d62016-07-22 20:03:43 +00001466 MI.eraseFromParent();
1467 return Legalized;
1468 }
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001469 case TargetOpcode::G_ICMP:
1470 case TargetOpcode::G_FCMP:
1471 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Volkan Keles574d7372018-12-14 22:11:20 +00001472 case TargetOpcode::G_LOAD:
1473 case TargetOpcode::G_STORE: {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001474 // FIXME: Don't know how to handle secondary types yet.
1475 if (TypeIdx != 0)
1476 return UnableToLegalize;
1477
Volkan Keles574d7372018-12-14 22:11:20 +00001478 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1479 unsigned ValReg = MI.getOperand(0).getReg();
1480 unsigned AddrReg = MI.getOperand(1).getReg();
1481 unsigned NarrowSize = NarrowTy.getSizeInBits();
1482 unsigned Size = MRI.getType(ValReg).getSizeInBits();
1483 unsigned NumParts = Size / NarrowSize;
1484
1485 SmallVector<unsigned, 8> NarrowRegs;
1486 if (!IsLoad)
1487 extractParts(ValReg, NarrowTy, NumParts, NarrowRegs);
1488
1489 const LLT OffsetTy =
1490 LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1491 MachineFunction &MF = *MI.getMF();
1492 MachineMemOperand *MMO = *MI.memoperands_begin();
1493 for (unsigned Idx = 0; Idx < NumParts; ++Idx) {
1494 unsigned Adjustment = Idx * NarrowTy.getSizeInBits() / 8;
1495 unsigned Alignment = MinAlign(MMO->getAlignment(), Adjustment);
1496 unsigned NewAddrReg = 0;
1497 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, Adjustment);
1498 MachineMemOperand &NewMMO = *MF.getMachineMemOperand(
1499 MMO->getPointerInfo().getWithOffset(Adjustment), MMO->getFlags(),
1500 NarrowTy.getSizeInBits() / 8, Alignment);
1501 if (IsLoad) {
1502 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
1503 NarrowRegs.push_back(Dst);
1504 MIRBuilder.buildLoad(Dst, NewAddrReg, NewMMO);
1505 } else {
1506 MIRBuilder.buildStore(NarrowRegs[Idx], NewAddrReg, NewMMO);
1507 }
1508 }
1509 if (IsLoad) {
1510 if (NarrowTy.isVector())
1511 MIRBuilder.buildConcatVectors(ValReg, NarrowRegs);
1512 else
1513 MIRBuilder.buildBuildVector(ValReg, NarrowRegs);
1514 }
1515 MI.eraseFromParent();
1516 return Legalized;
1517 }
Matt Arsenaultca676342019-01-25 02:36:32 +00001518 case TargetOpcode::G_ZEXT:
1519 case TargetOpcode::G_SEXT:
1520 case TargetOpcode::G_ANYEXT:
1521 case TargetOpcode::G_FPEXT:
Matt Arsenaulte6cebd02019-01-25 04:37:33 +00001522 case TargetOpcode::G_FPTRUNC:
1523 case TargetOpcode::G_SITOFP:
1524 case TargetOpcode::G_UITOFP:
1525 case TargetOpcode::G_FPTOSI:
1526 case TargetOpcode::G_FPTOUI:
Matt Arsenaultca676342019-01-25 02:36:32 +00001527 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00001528 }
1529}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001530
1531LegalizerHelper::LegalizeResult
Matt Arsenault211e89d2019-01-27 00:52:51 +00001532LegalizerHelper::narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT NewTy) {
1533 unsigned DstReg = MI.getOperand(0).getReg();
1534 unsigned Src0 = MI.getOperand(1).getReg();
1535 unsigned Src1 = MI.getOperand(2).getReg();
1536 LLT Ty = MRI.getType(DstReg);
1537 if (Ty.isVector())
1538 return UnableToLegalize;
1539
1540 unsigned Size = Ty.getSizeInBits();
1541 unsigned NewSize = Size / 2;
1542 if (Size != 2 * NewSize)
1543 return UnableToLegalize;
1544
1545 LLT HalfTy = LLT::scalar(NewSize);
1546 // TODO: if HalfTy != NewTy, handle the breakdown all at once?
1547
1548 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1549 unsigned Lo = MRI.createGenericVirtualRegister(HalfTy);
1550 unsigned Hi = MRI.createGenericVirtualRegister(HalfTy);
1551 unsigned ExtLo = MRI.createGenericVirtualRegister(Ty);
1552 unsigned ExtHi = MRI.createGenericVirtualRegister(Ty);
1553 unsigned ShiftedHi = MRI.createGenericVirtualRegister(Ty);
1554
1555 SmallVector<unsigned, 2> Src0Parts;
1556 SmallVector<unsigned, 2> Src1Parts;
1557
1558 extractParts(Src0, HalfTy, 2, Src0Parts);
1559 extractParts(Src1, HalfTy, 2, Src1Parts);
1560
1561 MIRBuilder.buildMul(Lo, Src0Parts[0], Src1Parts[0]);
1562
1563 // TODO: Use smulh or umulh depending on what the target has.
1564 MIRBuilder.buildUMulH(Hi, Src0Parts[1], Src1Parts[1]);
1565
1566 MIRBuilder.buildConstant(ShiftAmt, NewSize);
1567 MIRBuilder.buildAnyExt(ExtHi, Hi);
1568 MIRBuilder.buildShl(ShiftedHi, ExtHi, ShiftAmt);
1569
1570 MIRBuilder.buildZExt(ExtLo, Lo);
1571 MIRBuilder.buildOr(DstReg, ExtLo, ShiftedHi);
1572 MI.eraseFromParent();
1573 return Legalized;
1574}
1575
1576LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001577LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1578 unsigned Opc = MI.getOpcode();
1579 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00001580 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001581 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00001582 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001583 };
1584 switch (Opc) {
1585 default:
1586 return UnableToLegalize;
1587 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1588 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001589 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001590 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001591 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001592 return Legalized;
1593 }
1594 case TargetOpcode::G_CTLZ: {
1595 unsigned SrcReg = MI.getOperand(1).getReg();
1596 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001597 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1598 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001599 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
1600 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001601 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1602 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1603 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1604 SrcReg, MIBZero);
1605 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1606 MIBCtlzZU);
1607 MI.eraseFromParent();
1608 return Legalized;
1609 }
1610 // for now, we do this:
1611 // NewLen = NextPowerOf2(Len);
1612 // x = x | (x >> 1);
1613 // x = x | (x >> 2);
1614 // ...
1615 // x = x | (x >>16);
1616 // x = x | (x >>32); // for 64-bit input
1617 // Upto NewLen/2
1618 // return Len - popcount(x);
1619 //
1620 // Ref: "Hacker's Delight" by Henry Warren
1621 unsigned Op = SrcReg;
1622 unsigned NewLen = PowerOf2Ceil(Len);
1623 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1624 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1625 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001626 TargetOpcode::G_OR, {Ty},
1627 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
1628 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001629 Op = MIBOp->getOperand(0).getReg();
1630 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001631 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
1632 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1633 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001634 MI.eraseFromParent();
1635 return Legalized;
1636 }
1637 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1638 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001639 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001640 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001641 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001642 return Legalized;
1643 }
1644 case TargetOpcode::G_CTTZ: {
1645 unsigned SrcReg = MI.getOperand(1).getReg();
1646 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001647 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001648 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1649 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001650 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
1651 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001652 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1653 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1654 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1655 SrcReg, MIBZero);
1656 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1657 MIBCttzZU);
1658 MI.eraseFromParent();
1659 return Legalized;
1660 }
1661 // for now, we use: { return popcount(~x & (x - 1)); }
1662 // unless the target has ctlz but not ctpop, in which case we use:
1663 // { return 32 - nlz(~x & (x-1)); }
1664 // Ref: "Hacker's Delight" by Henry Warren
1665 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
1666 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001667 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001668 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001669 TargetOpcode::G_AND, {Ty},
1670 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
1671 {SrcReg, MIBCstNeg1})});
Diana Picus0528e2c2018-11-26 11:07:02 +00001672 if (!isSupported({TargetOpcode::G_CTPOP, {Ty}}) &&
1673 isSupported({TargetOpcode::G_CTLZ, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001674 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
1675 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001676 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1677 {MIBCstLen,
1678 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001679 MI.eraseFromParent();
1680 return Legalized;
1681 }
1682 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
1683 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
1684 return Legalized;
1685 }
1686 }
1687}