blob: 5fb5aae1c6d1b7d55da7883e75efdd5e92ebed86 [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;
Jessica Paquette7db82d72019-01-28 18:34:18 +0000125 case TargetOpcode::G_FSIN:
126 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
127 return Size == 128 ? RTLIB::SIN_F128
128 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32;
129 case TargetOpcode::G_FCOS:
130 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
131 return Size == 128 ? RTLIB::COS_F128
132 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32;
Jessica Paquettec49428a2019-01-28 19:53:14 +0000133 case TargetOpcode::G_FLOG10:
134 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
135 return Size == 128 ? RTLIB::LOG10_F128
136 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32;
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000137 case TargetOpcode::G_FLOG:
138 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
139 return Size == 128 ? RTLIB::LOG_F128
140 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000141 }
142 llvm_unreachable("Unknown libcall function");
143}
144
Diana Picusfc1675e2017-07-05 12:57:24 +0000145LegalizerHelper::LegalizeResult
146llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
147 const CallLowering::ArgInfo &Result,
148 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000149 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
150 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000151 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000152
Diana Picuse97822e2017-04-24 07:22:31 +0000153 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000154 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
155 MachineOperand::CreateES(Name), Result, Args))
156 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000157
Diana Picuse97822e2017-04-24 07:22:31 +0000158 return LegalizerHelper::Legalized;
159}
160
Diana Picus65ed3642018-01-17 13:34:10 +0000161// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000162static LegalizerHelper::LegalizeResult
163simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
164 Type *OpType) {
165 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000166
167 SmallVector<CallLowering::ArgInfo, 3> Args;
168 for (unsigned i = 1; i < MI.getNumOperands(); i++)
169 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000170 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000171 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000172}
173
Diana Picus65ed3642018-01-17 13:34:10 +0000174static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
175 Type *FromType) {
176 auto ToMVT = MVT::getVT(ToType);
177 auto FromMVT = MVT::getVT(FromType);
178
179 switch (Opcode) {
180 case TargetOpcode::G_FPEXT:
181 return RTLIB::getFPEXT(FromMVT, ToMVT);
182 case TargetOpcode::G_FPTRUNC:
183 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000184 case TargetOpcode::G_FPTOSI:
185 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
186 case TargetOpcode::G_FPTOUI:
187 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000188 case TargetOpcode::G_SITOFP:
189 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
190 case TargetOpcode::G_UITOFP:
191 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000192 }
193 llvm_unreachable("Unsupported libcall function");
194}
195
196static LegalizerHelper::LegalizeResult
197conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
198 Type *FromType) {
199 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
200 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
201 {{MI.getOperand(1).getReg(), FromType}});
202}
203
Tim Northover69fa84a2016-10-14 22:18:18 +0000204LegalizerHelper::LegalizeResult
205LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000206 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
207 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000208 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000209
Diana Picusfc1675e2017-07-05 12:57:24 +0000210 MIRBuilder.setInstr(MI);
211
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000212 switch (MI.getOpcode()) {
213 default:
214 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000215 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000216 case TargetOpcode::G_UDIV:
217 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000218 case TargetOpcode::G_UREM:
219 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000220 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000221 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
222 if (Status != Legalized)
223 return Status;
224 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000225 }
Diana Picus1314a282017-04-11 10:52:34 +0000226 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000227 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000228 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000229 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000230 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000231 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000232 case TargetOpcode::G_FREM:
233 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000234 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000235 case TargetOpcode::G_FLOG10:
236 case TargetOpcode::G_FLOG: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000237 if (Size > 64) {
238 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
239 return UnableToLegalize;
240 }
Diana Picus02e11012017-06-15 10:53:31 +0000241 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000242 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
243 if (Status != Legalized)
244 return Status;
245 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000246 }
Diana Picus65ed3642018-01-17 13:34:10 +0000247 case TargetOpcode::G_FPEXT: {
248 // FIXME: Support other floating point types (half, fp128 etc)
249 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
250 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
251 if (ToSize != 64 || FromSize != 32)
252 return UnableToLegalize;
253 LegalizeResult Status = conversionLibcall(
254 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
255 if (Status != Legalized)
256 return Status;
257 break;
258 }
259 case TargetOpcode::G_FPTRUNC: {
260 // FIXME: Support other floating point types (half, fp128 etc)
261 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
262 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
263 if (ToSize != 32 || FromSize != 64)
264 return UnableToLegalize;
265 LegalizeResult Status = conversionLibcall(
266 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
267 if (Status != Legalized)
268 return Status;
269 break;
270 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000271 case TargetOpcode::G_FPTOSI:
272 case TargetOpcode::G_FPTOUI: {
273 // FIXME: Support other types
274 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
275 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
276 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
277 return UnableToLegalize;
278 LegalizeResult Status = conversionLibcall(
279 MI, MIRBuilder, Type::getInt32Ty(Ctx),
280 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
281 if (Status != Legalized)
282 return Status;
283 break;
284 }
Diana Picus517531e2018-01-30 09:15:17 +0000285 case TargetOpcode::G_SITOFP:
286 case TargetOpcode::G_UITOFP: {
287 // FIXME: Support other types
288 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
289 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
290 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
291 return UnableToLegalize;
292 LegalizeResult Status = conversionLibcall(
293 MI, MIRBuilder,
294 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
295 Type::getInt32Ty(Ctx));
296 if (Status != Legalized)
297 return Status;
298 break;
299 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000300 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000301
302 MI.eraseFromParent();
303 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000304}
305
Tim Northover69fa84a2016-10-14 22:18:18 +0000306LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
307 unsigned TypeIdx,
308 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000309 MIRBuilder.setInstr(MI);
310
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000311 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
312 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000313
Tim Northover9656f142016-08-04 20:54:13 +0000314 switch (MI.getOpcode()) {
315 default:
316 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000317 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000318 // FIXME: add support for when SizeOp0 isn't an exact multiple of
319 // NarrowSize.
320 if (SizeOp0 % NarrowSize != 0)
321 return UnableToLegalize;
322 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000323
324 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000325 for (int i = 0; i < NumParts; ++i)
326 DstRegs.push_back(
327 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000328
329 unsigned DstReg = MI.getOperand(0).getReg();
330 if(MRI.getType(DstReg).isVector())
331 MIRBuilder.buildBuildVector(DstReg, DstRegs);
332 else
333 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000334 MI.eraseFromParent();
335 return Legalized;
336 }
Tim Northover9656f142016-08-04 20:54:13 +0000337 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000338 // FIXME: add support for when SizeOp0 isn't an exact multiple of
339 // NarrowSize.
340 if (SizeOp0 % NarrowSize != 0)
341 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000342 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000343 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000344
Tim Northoverb18ea162016-09-20 15:20:36 +0000345 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000346 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
347 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
348
Tim Northover0f140c72016-09-09 11:46:34 +0000349 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
350 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000351
352 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000353 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
354 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000355
Tim Northover0f140c72016-09-09 11:46:34 +0000356 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000357 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000358
359 DstRegs.push_back(DstReg);
360 CarryIn = CarryOut;
361 }
Tim Northover0f140c72016-09-09 11:46:34 +0000362 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000363 if(MRI.getType(DstReg).isVector())
364 MIRBuilder.buildBuildVector(DstReg, DstRegs);
365 else
366 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000367 MI.eraseFromParent();
368 return Legalized;
369 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000370 case TargetOpcode::G_SUB: {
371 // FIXME: add support for when SizeOp0 isn't an exact multiple of
372 // NarrowSize.
373 if (SizeOp0 % NarrowSize != 0)
374 return UnableToLegalize;
375
376 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
377
378 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
379 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
380 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
381
382 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
383 unsigned BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
384 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
385 {Src1Regs[0], Src2Regs[0]});
386 DstRegs.push_back(DstReg);
387 unsigned BorrowIn = BorrowOut;
388 for (int i = 1; i < NumParts; ++i) {
389 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
390 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
391
392 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
393 {Src1Regs[i], Src2Regs[i], BorrowIn});
394
395 DstRegs.push_back(DstReg);
396 BorrowIn = BorrowOut;
397 }
398 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
399 MI.eraseFromParent();
400 return Legalized;
401 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000402 case TargetOpcode::G_MUL:
403 return narrowScalarMul(MI, TypeIdx, NarrowTy);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000404 case TargetOpcode::G_EXTRACT: {
405 if (TypeIdx != 1)
406 return UnableToLegalize;
407
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000408 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
409 // FIXME: add support for when SizeOp1 isn't an exact multiple of
410 // NarrowSize.
411 if (SizeOp1 % NarrowSize != 0)
412 return UnableToLegalize;
413 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000414
415 SmallVector<unsigned, 2> SrcRegs, DstRegs;
416 SmallVector<uint64_t, 2> Indexes;
417 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
418
419 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000420 uint64_t OpStart = MI.getOperand(2).getImm();
421 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000422 for (int i = 0; i < NumParts; ++i) {
423 unsigned SrcStart = i * NarrowSize;
424
425 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
426 // No part of the extract uses this subregister, ignore it.
427 continue;
428 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
429 // The entire subregister is extracted, forward the value.
430 DstRegs.push_back(SrcRegs[i]);
431 continue;
432 }
433
434 // OpSegStart is where this destination segment would start in OpReg if it
435 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000436 int64_t ExtractOffset;
437 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000438 if (OpStart < SrcStart) {
439 ExtractOffset = 0;
440 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
441 } else {
442 ExtractOffset = OpStart - SrcStart;
443 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
444 }
445
446 unsigned SegReg = SrcRegs[i];
447 if (ExtractOffset != 0 || SegSize != NarrowSize) {
448 // A genuine extract is needed.
449 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
450 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
451 }
452
453 DstRegs.push_back(SegReg);
454 }
455
Amara Emerson5ec14602018-12-10 18:44:58 +0000456 unsigned DstReg = MI.getOperand(0).getReg();
457 if(MRI.getType(DstReg).isVector())
458 MIRBuilder.buildBuildVector(DstReg, DstRegs);
459 else
460 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000461 MI.eraseFromParent();
462 return Legalized;
463 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000464 case TargetOpcode::G_INSERT: {
Matt Arsenault30989e42019-01-22 21:42:11 +0000465 // FIXME: Don't know how to handle secondary types yet.
466 if (TypeIdx != 0)
467 return UnableToLegalize;
468
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000469 // FIXME: add support for when SizeOp0 isn't an exact multiple of
470 // NarrowSize.
471 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000472 return UnableToLegalize;
473
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000474 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000475
476 SmallVector<unsigned, 2> SrcRegs, DstRegs;
477 SmallVector<uint64_t, 2> Indexes;
478 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
479
Tim Northover75e0b912017-03-06 18:23:04 +0000480 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000481 uint64_t OpStart = MI.getOperand(3).getImm();
482 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000483 for (int i = 0; i < NumParts; ++i) {
484 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000485
Tim Northover75e0b912017-03-06 18:23:04 +0000486 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000487 // No part of the insert affects this subregister, forward the original.
488 DstRegs.push_back(SrcRegs[i]);
489 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000490 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000491 // The entire subregister is defined by this insert, forward the new
492 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000493 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000494 continue;
495 }
496
Tim Northover2eb18d32017-03-07 21:24:33 +0000497 // OpSegStart is where this destination segment would start in OpReg if it
498 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000499 int64_t ExtractOffset, InsertOffset;
500 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000501 if (OpStart < DstStart) {
502 InsertOffset = 0;
503 ExtractOffset = DstStart - OpStart;
504 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
505 } else {
506 InsertOffset = OpStart - DstStart;
507 ExtractOffset = 0;
508 SegSize =
509 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
510 }
511
512 unsigned SegReg = OpReg;
513 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000514 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000515 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
516 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000517 }
518
Tim Northover75e0b912017-03-06 18:23:04 +0000519 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000520 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000521 DstRegs.push_back(DstReg);
522 }
523
524 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000525 unsigned DstReg = MI.getOperand(0).getReg();
526 if(MRI.getType(DstReg).isVector())
527 MIRBuilder.buildBuildVector(DstReg, DstRegs);
528 else
529 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000530 MI.eraseFromParent();
531 return Legalized;
532 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000533 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000534 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000535 unsigned DstReg = MI.getOperand(0).getReg();
536 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000537 int NumParts = SizeOp0 / NarrowSize;
538 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
539 unsigned LeftoverBits = DstTy.getSizeInBits() - HandledSize;
540
541 if (DstTy.isVector() && LeftoverBits != 0)
542 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000543
544 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
545 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
546 auto &MMO = **MI.memoperands_begin();
547 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
548 MIRBuilder.buildAnyExt(DstReg, TmpReg);
549 MI.eraseFromParent();
550 return Legalized;
551 }
552
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000553 // 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
Daniel Sanders4e523662017-06-13 23:42:32 +0000559 LLT OffsetTy = LLT::scalar(
560 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000561
562 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000563 for (int i = 0; i < NumParts; ++i) {
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000564 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000565 unsigned SrcReg = 0;
566 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000567 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000568
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000569 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
570 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000571 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
572 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000573
Daniel Sanders4e523662017-06-13 23:42:32 +0000574 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
575 Adjustment);
576
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000577 MIRBuilder.buildLoad(PartDstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000578
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000579 DstRegs.push_back(PartDstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000580 }
Matt Arsenault18619af2019-01-29 18:13:02 +0000581
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000582 unsigned MergeResultReg = LeftoverBits == 0 ? DstReg :
583 MRI.createGenericVirtualRegister(LLT::scalar(HandledSize));
584
585 // For the leftover piece, still create the merge and insert it.
586 // TODO: Would it be better to directly insert the intermediate pieces?
Matt Arsenault18619af2019-01-29 18:13:02 +0000587 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000588 MIRBuilder.buildBuildVector(MergeResultReg, DstRegs);
Amara Emerson5ec14602018-12-10 18:44:58 +0000589 else
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000590 MIRBuilder.buildMerge(MergeResultReg, DstRegs);
591
592 if (LeftoverBits == 0) {
593 MI.eraseFromParent();
594 return Legalized;
595 }
596
597 unsigned ImpDefReg = MRI.createGenericVirtualRegister(DstTy);
598 unsigned Insert0Reg = MRI.createGenericVirtualRegister(DstTy);
599 MIRBuilder.buildUndef(ImpDefReg);
600 MIRBuilder.buildInsert(Insert0Reg, ImpDefReg, MergeResultReg, 0);
601
602 unsigned PartDstReg
603 = MRI.createGenericVirtualRegister(LLT::scalar(LeftoverBits));
604 unsigned Offset = HandledSize / 8;
605
606 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
607 &MMO, Offset, LeftoverBits / 8);
608
609 unsigned SrcReg = 0;
610 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
611 Offset);
612 MIRBuilder.buildLoad(PartDstReg, SrcReg, *SplitMMO);
613 MIRBuilder.buildInsert(DstReg, Insert0Reg, PartDstReg, HandledSize);
614
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000615 MI.eraseFromParent();
616 return Legalized;
617 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000618 case TargetOpcode::G_ZEXTLOAD:
619 case TargetOpcode::G_SEXTLOAD: {
620 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
621 unsigned DstReg = MI.getOperand(0).getReg();
622 unsigned PtrReg = MI.getOperand(1).getReg();
623
624 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
625 auto &MMO = **MI.memoperands_begin();
626 if (MMO.getSize() * 8 == NarrowSize) {
627 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
628 } else {
629 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
630 : TargetOpcode::G_SEXTLOAD;
631 MIRBuilder.buildInstr(ExtLoad)
632 .addDef(TmpReg)
633 .addUse(PtrReg)
634 .addMemOperand(&MMO);
635 }
636
637 if (ZExt)
638 MIRBuilder.buildZExt(DstReg, TmpReg);
639 else
640 MIRBuilder.buildSExt(DstReg, TmpReg);
641
642 MI.eraseFromParent();
643 return Legalized;
644 }
Justin Bognerfde01042017-01-18 17:29:54 +0000645 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000646 // FIXME: add support for when SizeOp0 isn't an exact multiple of
647 // NarrowSize.
648 if (SizeOp0 % NarrowSize != 0)
649 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000650
651 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000652
653 unsigned SrcReg = MI.getOperand(0).getReg();
654 LLT SrcTy = MRI.getType(SrcReg);
655
656 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
657 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
658 auto &MMO = **MI.memoperands_begin();
659 MIRBuilder.buildTrunc(TmpReg, SrcReg);
660 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
661 MI.eraseFromParent();
662 return Legalized;
663 }
664
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000665 // This implementation doesn't work for atomics. Give up instead of doing
666 // something invalid.
667 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
668 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
669 return UnableToLegalize;
670
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000671 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000672 LLT OffsetTy = LLT::scalar(
673 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000674
675 SmallVector<unsigned, 2> SrcRegs;
676 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
677
678 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000679 unsigned DstReg = 0;
680 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000681 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Daniel Sanders4e523662017-06-13 23:42:32 +0000682
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000683 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
684 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000685 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
686 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000687
Daniel Sanders4e523662017-06-13 23:42:32 +0000688 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
689 Adjustment);
690
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000691 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000692 }
693 MI.eraseFromParent();
694 return Legalized;
695 }
Igor Breger29537882017-04-07 14:41:59 +0000696 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000697 // FIXME: add support for when SizeOp0 isn't an exact multiple of
698 // NarrowSize.
699 if (SizeOp0 % NarrowSize != 0)
700 return UnableToLegalize;
701 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000702 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000703 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000704
705 SmallVector<unsigned, 2> DstRegs;
706 for (int i = 0; i < NumParts; ++i) {
707 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
708 ConstantInt *CI =
709 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
710 MIRBuilder.buildConstant(DstReg, *CI);
711 DstRegs.push_back(DstReg);
712 }
713 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000714 if(MRI.getType(DstReg).isVector())
715 MIRBuilder.buildBuildVector(DstReg, DstRegs);
716 else
717 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000718 MI.eraseFromParent();
719 return Legalized;
720 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000721 case TargetOpcode::G_AND:
722 case TargetOpcode::G_OR:
723 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000724 // Legalize bitwise operation:
725 // A = BinOp<Ty> B, C
726 // into:
727 // B1, ..., BN = G_UNMERGE_VALUES B
728 // C1, ..., CN = G_UNMERGE_VALUES C
729 // A1 = BinOp<Ty/N> B1, C2
730 // ...
731 // AN = BinOp<Ty/N> BN, CN
732 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000733
734 // FIXME: add support for when SizeOp0 isn't an exact multiple of
735 // NarrowSize.
736 if (SizeOp0 % NarrowSize != 0)
737 return UnableToLegalize;
738 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000739
740 // List the registers where the destination will be scattered.
741 SmallVector<unsigned, 2> DstRegs;
742 // List the registers where the first argument will be split.
743 SmallVector<unsigned, 2> SrcsReg1;
744 // List the registers where the second argument will be split.
745 SmallVector<unsigned, 2> SrcsReg2;
746 // Create all the temporary registers.
747 for (int i = 0; i < NumParts; ++i) {
748 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
749 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
750 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
751
752 DstRegs.push_back(DstReg);
753 SrcsReg1.push_back(SrcReg1);
754 SrcsReg2.push_back(SrcReg2);
755 }
756 // Explode the big arguments into smaller chunks.
757 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
758 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
759
760 // Do the operation on each small part.
761 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000762 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
763 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000764
765 // Gather the destination registers into the final destination.
766 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000767 if(MRI.getType(DstReg).isVector())
768 MIRBuilder.buildBuildVector(DstReg, DstRegs);
769 else
770 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000771 MI.eraseFromParent();
772 return Legalized;
773 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000774 case TargetOpcode::G_SHL:
775 case TargetOpcode::G_LSHR:
776 case TargetOpcode::G_ASHR: {
777 if (TypeIdx != 1)
778 return UnableToLegalize; // TODO
779 narrowScalarSrc(MI, NarrowTy, 2);
780 return Legalized;
781 }
Tim Northover9656f142016-08-04 20:54:13 +0000782 }
Tim Northover33b07d62016-07-22 20:03:43 +0000783}
784
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000785void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
786 unsigned OpIdx, unsigned ExtOpcode) {
787 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000788 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000789 MO.setReg(ExtB->getOperand(0).getReg());
790}
791
Matt Arsenault30989e42019-01-22 21:42:11 +0000792void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
793 unsigned OpIdx) {
794 MachineOperand &MO = MI.getOperand(OpIdx);
795 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
796 {MO.getReg()});
797 MO.setReg(ExtB->getOperand(0).getReg());
798}
799
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000800void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
801 unsigned OpIdx, unsigned TruncOpcode) {
802 MachineOperand &MO = MI.getOperand(OpIdx);
803 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
804 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000805 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000806 MO.setReg(DstExt);
807}
808
Tim Northover69fa84a2016-10-14 22:18:18 +0000809LegalizerHelper::LegalizeResult
810LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000811 MIRBuilder.setInstr(MI);
812
Tim Northover32335812016-08-04 18:35:11 +0000813 switch (MI.getOpcode()) {
814 default:
815 return UnableToLegalize;
Matt Arsenaultd8d193d2019-01-29 23:17:35 +0000816 case TargetOpcode::G_MERGE_VALUES: {
817 if (TypeIdx != 1)
818 return UnableToLegalize;
819
820 unsigned DstReg = MI.getOperand(0).getReg();
821 LLT DstTy = MRI.getType(DstReg);
822 if (!DstTy.isScalar())
823 return UnableToLegalize;
824
825 unsigned NumSrc = MI.getNumOperands() - 1;
826 unsigned EltSize = DstTy.getSizeInBits() / NumSrc;
Matt Arsenaultd8d193d2019-01-29 23:17:35 +0000827
828 unsigned ResultReg = MRI.createGenericVirtualRegister(DstTy);
829 unsigned Offset = 0;
830 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I,
831 Offset += EltSize) {
Matt Arsenault3de9a962019-01-29 23:38:42 +0000832 assert(MRI.getType(MI.getOperand(I).getReg()) == LLT::scalar(EltSize));
Matt Arsenaultd8d193d2019-01-29 23:17:35 +0000833
834 unsigned ShiftAmt = MRI.createGenericVirtualRegister(DstTy);
835 unsigned Shl = MRI.createGenericVirtualRegister(DstTy);
836 unsigned ZextInput = MRI.createGenericVirtualRegister(DstTy);
837 MIRBuilder.buildZExt(ZextInput, MI.getOperand(I).getReg());
838
839 if (Offset != 0) {
840 unsigned NextResult = I + 1 == E ? DstReg :
841 MRI.createGenericVirtualRegister(DstTy);
842
843 MIRBuilder.buildConstant(ShiftAmt, Offset);
844 MIRBuilder.buildShl(Shl, ZextInput, ShiftAmt);
845 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
846 ResultReg = NextResult;
847 } else {
848 ResultReg = ZextInput;
849 }
850 }
851
852 MI.eraseFromParent();
853 return Legalized;
854 }
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000855 case TargetOpcode::G_UADDO:
856 case TargetOpcode::G_USUBO: {
857 if (TypeIdx == 1)
858 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000859 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
860 {MI.getOperand(2).getReg()});
861 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
862 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000863 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
864 ? TargetOpcode::G_ADD
865 : TargetOpcode::G_SUB;
866 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000867 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000868 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
869 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
870 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000871 TargetOpcode::G_AND, {WideTy},
872 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000873 // There is no overflow if the AndOp is the same as NewOp.
874 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
875 AndOp);
876 // Now trunc the NewOp to the original result.
877 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
878 MI.eraseFromParent();
879 return Legalized;
880 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000881 case TargetOpcode::G_CTTZ:
882 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
883 case TargetOpcode::G_CTLZ:
884 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
885 case TargetOpcode::G_CTPOP: {
886 // First ZEXT the input.
887 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
888 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
889 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
890 // The count is the same in the larger type except if the original
891 // value was zero. This can be handled by setting the bit just off
892 // the top of the original type.
893 auto TopBit =
894 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
895 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000896 TargetOpcode::G_OR, {WideTy},
897 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000898 }
899 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000900 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000901 // This is already the correct result for CTPOP and CTTZs
902 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
903 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
904 // The correct result is NewOp - (Difference in widety and current ty).
905 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000906 MIBNewOp = MIRBuilder.buildInstr(
907 TargetOpcode::G_SUB, {WideTy},
908 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000909 }
910 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +0000911 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000912 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000913 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
914 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000915 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000916 return Legalized;
917 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000918
Tim Northover61c16142016-08-04 21:39:49 +0000919 case TargetOpcode::G_ADD:
920 case TargetOpcode::G_AND:
921 case TargetOpcode::G_MUL:
922 case TargetOpcode::G_OR:
923 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000924 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000925 // Perform operation at larger width (any extension is fine here, high bits
926 // don't affect the result) and then truncate the result back to the
927 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000928 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000929 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
930 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
931 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000932 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000933 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000934
Roman Tereshin6d266382018-05-09 21:43:30 +0000935 case TargetOpcode::G_SHL:
Matt Arsenault30989e42019-01-22 21:42:11 +0000936 Observer.changingInstr(MI);
937
938 if (TypeIdx == 0) {
939 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
940 widenScalarDst(MI, WideTy);
941 } else {
942 assert(TypeIdx == 1);
943 // The "number of bits to shift" operand must preserve its value as an
944 // unsigned integer:
945 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
946 }
947
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000948 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000949 return Legalized;
950
Tim Northover7a753d92016-08-26 17:46:06 +0000951 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000952 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000953 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000954 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
955 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
956 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000957 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000958 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000959
Roman Tereshin6d266382018-05-09 21:43:30 +0000960 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +0000961 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000962 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +0000963
964 if (TypeIdx == 0) {
965 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
966 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
967
968 widenScalarSrc(MI, WideTy, 1, CvtOp);
969 widenScalarDst(MI, WideTy);
970 } else {
971 assert(TypeIdx == 1);
972 // The "number of bits to shift" operand must preserve its value as an
973 // unsigned integer:
974 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
975 }
976
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000977 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000978 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000979 case TargetOpcode::G_UDIV:
980 case TargetOpcode::G_UREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000981 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000982 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
983 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
984 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000985 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000986 return Legalized;
987
988 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000989 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +0000990 if (TypeIdx == 0) {
991 // Perform operation at larger width (any extension is fine here, high
992 // bits don't affect the result) and then truncate the result back to the
993 // original type.
994 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
995 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
996 widenScalarDst(MI, WideTy);
997 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +0000998 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +0000999 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001000 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001001 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001002 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001003 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001004
Ahmed Bougachab6137062017-01-23 21:10:14 +00001005 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001006 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001007 if (TypeIdx != 0)
1008 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001009 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001010 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001011 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001012 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001013
Ahmed Bougachad2948232017-01-20 01:37:24 +00001014 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001015 if (TypeIdx != 1)
1016 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001017 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001018 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001019 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001020 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001021
1022 case TargetOpcode::G_UITOFP:
1023 if (TypeIdx != 1)
1024 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001025 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001026 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001027 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001028 return Legalized;
1029
1030 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +00001031 if (TypeIdx != 0)
1032 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001033 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001034 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1035 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001036 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001037 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001038
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001039 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +00001040 // For some types like i24, we might try to widen to i32. To properly handle
1041 // this we should be using a dedicated extending load, until then avoid
1042 // trying to legalize.
1043 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
1044 WideTy.getSizeInBits())
1045 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001046 LLVM_FALLTHROUGH;
1047 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001048 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001049 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001050 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001051 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001052 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001053
Tim Northover3c73e362016-08-23 18:20:09 +00001054 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001055 if (TypeIdx != 0)
1056 return UnableToLegalize;
1057
1058 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1059 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001060 return UnableToLegalize;
1061
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001062 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001063
1064 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1065 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1066 widenScalarSrc(MI, WideTy, 0, ExtType);
1067
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001068 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001069 return Legalized;
1070 }
Tim Northoverea904f92016-08-19 22:40:00 +00001071 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001072 MachineOperand &SrcMO = MI.getOperand(1);
1073 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1074 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001075 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001076 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1077
1078 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001079 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001080 return Legalized;
1081 }
Tim Northovera11be042016-08-19 22:40:08 +00001082 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001083 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001084 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001085 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001086 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001087 switch (WideTy.getSizeInBits()) {
1088 case 32:
1089 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
1090 break;
1091 case 64:
1092 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
1093 break;
1094 default:
1095 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +00001096 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001097 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001098 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1099
1100 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001101 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001102 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001103 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001104 case TargetOpcode::G_IMPLICIT_DEF: {
1105 Observer.changingInstr(MI);
1106 widenScalarDst(MI, WideTy);
1107 Observer.changedInstr(MI);
1108 return Legalized;
1109 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001110 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001111 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001112 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001113 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001114 return Legalized;
1115
1116 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001117 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001118 if (TypeIdx == 0)
1119 widenScalarDst(MI, WideTy);
1120 else {
1121 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1122 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001123 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001124 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001125 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001126
1127 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001128 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001129 if (TypeIdx == 0)
1130 widenScalarDst(MI, WideTy);
1131 else {
1132 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1133 MI.getOperand(1).getPredicate()))
1134 ? TargetOpcode::G_SEXT
1135 : TargetOpcode::G_ZEXT;
1136 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1137 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1138 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001139 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001140 return Legalized;
1141
1142 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001143 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001144 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001145 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001146 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001147 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001148
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001149 case TargetOpcode::G_PHI: {
1150 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001151
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001152 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001153 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1154 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1155 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1156 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001157 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001158
1159 MachineBasicBlock &MBB = *MI.getParent();
1160 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1161 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001162 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001163 return Legalized;
1164 }
Matt Arsenault63786292019-01-22 20:38:15 +00001165 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1166 if (TypeIdx == 0) {
1167 unsigned VecReg = MI.getOperand(1).getReg();
1168 LLT VecTy = MRI.getType(VecReg);
1169 Observer.changingInstr(MI);
1170
1171 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1172 WideTy.getSizeInBits()),
1173 1, TargetOpcode::G_SEXT);
1174
1175 widenScalarDst(MI, WideTy, 0);
1176 Observer.changedInstr(MI);
1177 return Legalized;
1178 }
1179
Amara Emersoncbd86d82018-10-25 14:04:54 +00001180 if (TypeIdx != 2)
1181 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001182 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001183 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001184 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001185 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001186 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001187 case TargetOpcode::G_FADD:
1188 case TargetOpcode::G_FMUL:
1189 case TargetOpcode::G_FSUB:
1190 case TargetOpcode::G_FMA:
1191 case TargetOpcode::G_FNEG:
1192 case TargetOpcode::G_FABS:
1193 case TargetOpcode::G_FDIV:
1194 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001195 case TargetOpcode::G_FCEIL:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001196 case TargetOpcode::G_FCOS:
1197 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001198 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001199 case TargetOpcode::G_FLOG:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001200 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001201 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001202
1203 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1204 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1205
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001206 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1207 Observer.changedInstr(MI);
1208 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001209 }
Tim Northover33b07d62016-07-22 20:03:43 +00001210}
1211
Tim Northover69fa84a2016-10-14 22:18:18 +00001212LegalizerHelper::LegalizeResult
1213LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001214 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001215 MIRBuilder.setInstr(MI);
1216
1217 switch(MI.getOpcode()) {
1218 default:
1219 return UnableToLegalize;
1220 case TargetOpcode::G_SREM:
1221 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001222 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1223 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001224 .addDef(QuotReg)
1225 .addUse(MI.getOperand(1).getReg())
1226 .addUse(MI.getOperand(2).getReg());
1227
Tim Northover0f140c72016-09-09 11:46:34 +00001228 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1229 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1230 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1231 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001232 MI.eraseFromParent();
1233 return Legalized;
1234 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001235 case TargetOpcode::G_SMULO:
1236 case TargetOpcode::G_UMULO: {
1237 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1238 // result.
1239 unsigned Res = MI.getOperand(0).getReg();
1240 unsigned Overflow = MI.getOperand(1).getReg();
1241 unsigned LHS = MI.getOperand(2).getReg();
1242 unsigned RHS = MI.getOperand(3).getReg();
1243
1244 MIRBuilder.buildMul(Res, LHS, RHS);
1245
1246 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1247 ? TargetOpcode::G_SMULH
1248 : TargetOpcode::G_UMULH;
1249
1250 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1251 MIRBuilder.buildInstr(Opcode)
1252 .addDef(HiPart)
1253 .addUse(LHS)
1254 .addUse(RHS);
1255
1256 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1257 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001258
1259 // For *signed* multiply, overflow is detected by checking:
1260 // (hi != (lo >> bitwidth-1))
1261 if (Opcode == TargetOpcode::G_SMULH) {
1262 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1263 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1264 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1265 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1266 .addDef(Shifted)
1267 .addUse(Res)
1268 .addUse(ShiftAmt);
1269 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1270 } else {
1271 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1272 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001273 MI.eraseFromParent();
1274 return Legalized;
1275 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001276 case TargetOpcode::G_FNEG: {
1277 // TODO: Handle vector types once we are able to
1278 // represent them.
1279 if (Ty.isVector())
1280 return UnableToLegalize;
1281 unsigned Res = MI.getOperand(0).getReg();
1282 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001283 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001284 switch (Ty.getSizeInBits()) {
1285 case 16:
1286 ZeroTy = Type::getHalfTy(Ctx);
1287 break;
1288 case 32:
1289 ZeroTy = Type::getFloatTy(Ctx);
1290 break;
1291 case 64:
1292 ZeroTy = Type::getDoubleTy(Ctx);
1293 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001294 case 128:
1295 ZeroTy = Type::getFP128Ty(Ctx);
1296 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001297 default:
1298 llvm_unreachable("unexpected floating-point type");
1299 }
1300 ConstantFP &ZeroForNegation =
1301 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001302 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001303 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1304 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001305 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001306 .addUse(MI.getOperand(1).getReg());
1307 MI.eraseFromParent();
1308 return Legalized;
1309 }
Volkan Keles225921a2017-03-10 21:25:09 +00001310 case TargetOpcode::G_FSUB: {
1311 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1312 // First, check if G_FNEG is marked as Lower. If so, we may
1313 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001314 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001315 return UnableToLegalize;
1316 unsigned Res = MI.getOperand(0).getReg();
1317 unsigned LHS = MI.getOperand(1).getReg();
1318 unsigned RHS = MI.getOperand(2).getReg();
1319 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1320 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1321 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1322 .addDef(Res)
1323 .addUse(LHS)
1324 .addUse(Neg);
1325 MI.eraseFromParent();
1326 return Legalized;
1327 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001328 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1329 unsigned OldValRes = MI.getOperand(0).getReg();
1330 unsigned SuccessRes = MI.getOperand(1).getReg();
1331 unsigned Addr = MI.getOperand(2).getReg();
1332 unsigned CmpVal = MI.getOperand(3).getReg();
1333 unsigned NewVal = MI.getOperand(4).getReg();
1334 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1335 **MI.memoperands_begin());
1336 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1337 MI.eraseFromParent();
1338 return Legalized;
1339 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001340 case TargetOpcode::G_LOAD:
1341 case TargetOpcode::G_SEXTLOAD:
1342 case TargetOpcode::G_ZEXTLOAD: {
1343 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1344 unsigned DstReg = MI.getOperand(0).getReg();
1345 unsigned PtrReg = MI.getOperand(1).getReg();
1346 LLT DstTy = MRI.getType(DstReg);
1347 auto &MMO = **MI.memoperands_begin();
1348
1349 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001350 // In the case of G_LOAD, this was a non-extending load already and we're
1351 // about to lower to the same instruction.
1352 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1353 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001354 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1355 MI.eraseFromParent();
1356 return Legalized;
1357 }
1358
1359 if (DstTy.isScalar()) {
1360 unsigned TmpReg = MRI.createGenericVirtualRegister(
1361 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1362 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1363 switch (MI.getOpcode()) {
1364 default:
1365 llvm_unreachable("Unexpected opcode");
1366 case TargetOpcode::G_LOAD:
1367 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1368 break;
1369 case TargetOpcode::G_SEXTLOAD:
1370 MIRBuilder.buildSExt(DstReg, TmpReg);
1371 break;
1372 case TargetOpcode::G_ZEXTLOAD:
1373 MIRBuilder.buildZExt(DstReg, TmpReg);
1374 break;
1375 }
1376 MI.eraseFromParent();
1377 return Legalized;
1378 }
1379
1380 return UnableToLegalize;
1381 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001382 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1383 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1384 case TargetOpcode::G_CTLZ:
1385 case TargetOpcode::G_CTTZ:
1386 case TargetOpcode::G_CTPOP:
1387 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001388 case G_UADDE: {
1389 unsigned Res = MI.getOperand(0).getReg();
1390 unsigned CarryOut = MI.getOperand(1).getReg();
1391 unsigned LHS = MI.getOperand(2).getReg();
1392 unsigned RHS = MI.getOperand(3).getReg();
1393 unsigned CarryIn = MI.getOperand(4).getReg();
1394
1395 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1396 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1397
1398 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1399 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1400 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1401 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1402
1403 MI.eraseFromParent();
1404 return Legalized;
1405 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001406 case G_USUBO: {
1407 unsigned Res = MI.getOperand(0).getReg();
1408 unsigned BorrowOut = MI.getOperand(1).getReg();
1409 unsigned LHS = MI.getOperand(2).getReg();
1410 unsigned RHS = MI.getOperand(3).getReg();
1411
1412 MIRBuilder.buildSub(Res, LHS, RHS);
1413 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1414
1415 MI.eraseFromParent();
1416 return Legalized;
1417 }
1418 case G_USUBE: {
1419 unsigned Res = MI.getOperand(0).getReg();
1420 unsigned BorrowOut = MI.getOperand(1).getReg();
1421 unsigned LHS = MI.getOperand(2).getReg();
1422 unsigned RHS = MI.getOperand(3).getReg();
1423 unsigned BorrowIn = MI.getOperand(4).getReg();
1424
1425 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1426 unsigned ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1427 unsigned LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1428 unsigned LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1429
1430 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1431 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1432 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1433 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1434 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1435 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1436
1437 MI.eraseFromParent();
1438 return Legalized;
1439 }
Tim Northovercecee562016-08-26 17:46:13 +00001440 }
1441}
1442
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001443LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1444 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
1445 SmallVector<unsigned, 2> DstRegs;
1446
1447 unsigned NarrowSize = NarrowTy.getSizeInBits();
1448 unsigned DstReg = MI.getOperand(0).getReg();
1449 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1450 int NumParts = Size / NarrowSize;
1451 // FIXME: Don't know how to handle the situation where the small vectors
1452 // aren't all the same size yet.
1453 if (Size % NarrowSize != 0)
1454 return UnableToLegalize;
1455
1456 for (int i = 0; i < NumParts; ++i) {
1457 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1458 MIRBuilder.buildUndef(TmpReg);
1459 DstRegs.push_back(TmpReg);
1460 }
1461
1462 if (NarrowTy.isVector())
1463 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1464 else
1465 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1466
1467 MI.eraseFromParent();
1468 return Legalized;
1469}
1470
1471LegalizerHelper::LegalizeResult
1472LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
1473 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001474 const unsigned Opc = MI.getOpcode();
1475 const unsigned NumOps = MI.getNumOperands() - 1;
1476 const unsigned NarrowSize = NarrowTy.getSizeInBits();
1477 const unsigned DstReg = MI.getOperand(0).getReg();
1478 const unsigned Flags = MI.getFlags();
1479 const LLT DstTy = MRI.getType(DstReg);
1480 const unsigned Size = DstTy.getSizeInBits();
1481 const int NumParts = Size / NarrowSize;
1482 const LLT EltTy = DstTy.getElementType();
1483 const unsigned EltSize = EltTy.getSizeInBits();
1484 const unsigned BitsForNumParts = NarrowSize * NumParts;
1485
1486 // Check if we have any leftovers. If we do, then only handle the case where
1487 // the leftover is one element.
1488 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001489 return UnableToLegalize;
1490
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001491 if (BitsForNumParts != Size) {
1492 unsigned AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
1493 MIRBuilder.buildUndef(AccumDstReg);
1494
1495 // Handle the pieces which evenly divide into the requested type with
1496 // extract/op/insert sequence.
1497 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
1498 SmallVector<SrcOp, 4> SrcOps;
1499 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1500 unsigned PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
1501 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
1502 SrcOps.push_back(PartOpReg);
1503 }
1504
1505 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
1506 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1507
1508 unsigned PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
1509 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
1510 AccumDstReg = PartInsertReg;
1511 Offset += NarrowSize;
1512 }
1513
1514 // Handle the remaining element sized leftover piece.
1515 SmallVector<SrcOp, 4> SrcOps;
1516 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1517 unsigned PartOpReg = MRI.createGenericVirtualRegister(EltTy);
1518 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
1519 BitsForNumParts);
1520 SrcOps.push_back(PartOpReg);
1521 }
1522
1523 unsigned PartDstReg = MRI.createGenericVirtualRegister(EltTy);
1524 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1525 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
1526 MI.eraseFromParent();
1527
1528 return Legalized;
1529 }
1530
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001531 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1532
1533 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1534
1535 if (NumOps >= 2)
1536 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1537
1538 if (NumOps >= 3)
1539 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
1540
1541 for (int i = 0; i < NumParts; ++i) {
1542 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1543
1544 if (NumOps == 1)
1545 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1546 else if (NumOps == 2) {
1547 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1548 } else if (NumOps == 3) {
1549 MIRBuilder.buildInstr(Opc, {DstReg},
1550 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1551 }
1552
1553 DstRegs.push_back(DstReg);
1554 }
1555
1556 if (NarrowTy.isVector())
1557 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1558 else
1559 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1560
1561 MI.eraseFromParent();
1562 return Legalized;
1563}
1564
Tim Northover69fa84a2016-10-14 22:18:18 +00001565LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001566LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1567 LLT NarrowTy) {
1568 if (TypeIdx != 0)
1569 return UnableToLegalize;
1570
1571 unsigned DstReg = MI.getOperand(0).getReg();
1572 unsigned SrcReg = MI.getOperand(1).getReg();
1573 LLT DstTy = MRI.getType(DstReg);
1574 LLT SrcTy = MRI.getType(SrcReg);
1575
1576 LLT NarrowTy0 = NarrowTy;
1577 LLT NarrowTy1;
1578 unsigned NumParts;
1579
1580 if (NarrowTy.isScalar()) {
1581 NumParts = DstTy.getNumElements();
1582 NarrowTy1 = SrcTy.getElementType();
1583 } else {
1584 // Uneven breakdown not handled.
1585 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1586 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1587 return UnableToLegalize;
1588
1589 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
1590 }
1591
1592 SmallVector<unsigned, 4> SrcRegs, DstRegs;
1593 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1594
1595 for (unsigned I = 0; I < NumParts; ++I) {
1596 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1597 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1598 .addDef(DstReg)
1599 .addUse(SrcRegs[I]);
1600
1601 NewInst->setFlags(MI.getFlags());
1602 DstRegs.push_back(DstReg);
1603 }
1604
1605 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001606 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001607 else
1608 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1609
1610 MI.eraseFromParent();
1611 return Legalized;
1612}
1613
1614LegalizerHelper::LegalizeResult
1615LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1616 LLT NarrowTy) {
1617 unsigned DstReg = MI.getOperand(0).getReg();
1618 unsigned Src0Reg = MI.getOperand(2).getReg();
1619 LLT DstTy = MRI.getType(DstReg);
1620 LLT SrcTy = MRI.getType(Src0Reg);
1621
1622 unsigned NumParts;
1623 LLT NarrowTy0, NarrowTy1;
1624
1625 if (TypeIdx == 0) {
1626 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1627 unsigned OldElts = DstTy.getNumElements();
1628
1629 NarrowTy0 = NarrowTy;
1630 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
1631 NarrowTy1 = NarrowTy.isVector() ?
1632 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
1633 SrcTy.getElementType();
1634
1635 } else {
1636 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1637 unsigned OldElts = SrcTy.getNumElements();
1638
1639 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
1640 NarrowTy.getNumElements();
1641 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
1642 DstTy.getScalarSizeInBits());
1643 NarrowTy1 = NarrowTy;
1644 }
1645
1646 // FIXME: Don't know how to handle the situation where the small vectors
1647 // aren't all the same size yet.
1648 if (NarrowTy1.isVector() &&
1649 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
1650 return UnableToLegalize;
1651
1652 CmpInst::Predicate Pred
1653 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
1654
1655 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1656 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
1657 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
1658
1659 for (unsigned I = 0; I < NumParts; ++I) {
1660 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1661 DstRegs.push_back(DstReg);
1662
1663 if (MI.getOpcode() == TargetOpcode::G_ICMP)
1664 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1665 else {
1666 MachineInstr *NewCmp
1667 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1668 NewCmp->setFlags(MI.getFlags());
1669 }
1670 }
1671
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001672 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00001673 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1674 else
1675 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1676
1677 MI.eraseFromParent();
1678 return Legalized;
1679}
1680
1681LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00001682LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
1683 LLT NarrowTy) {
1684 unsigned DstReg = MI.getOperand(0).getReg();
1685 unsigned CondReg = MI.getOperand(1).getReg();
1686
1687 unsigned NumParts = 0;
1688 LLT NarrowTy0, NarrowTy1;
1689
1690 LLT DstTy = MRI.getType(DstReg);
1691 LLT CondTy = MRI.getType(CondReg);
1692 unsigned Size = DstTy.getSizeInBits();
1693
1694 assert(TypeIdx == 0 || CondTy.isVector());
1695
1696 if (TypeIdx == 0) {
1697 NarrowTy0 = NarrowTy;
1698 NarrowTy1 = CondTy;
1699
1700 unsigned NarrowSize = NarrowTy0.getSizeInBits();
1701 // FIXME: Don't know how to handle the situation where the small vectors
1702 // aren't all the same size yet.
1703 if (Size % NarrowSize != 0)
1704 return UnableToLegalize;
1705
1706 NumParts = Size / NarrowSize;
1707
1708 // Need to break down the condition type
1709 if (CondTy.isVector()) {
1710 if (CondTy.getNumElements() == NumParts)
1711 NarrowTy1 = CondTy.getElementType();
1712 else
1713 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
1714 CondTy.getScalarSizeInBits());
1715 }
1716 } else {
1717 NumParts = CondTy.getNumElements();
1718 if (NarrowTy.isVector()) {
1719 // TODO: Handle uneven breakdown.
1720 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
1721 return UnableToLegalize;
1722
1723 return UnableToLegalize;
1724 } else {
1725 NarrowTy0 = DstTy.getElementType();
1726 NarrowTy1 = NarrowTy;
1727 }
1728 }
1729
1730 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1731 if (CondTy.isVector())
1732 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
1733
1734 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
1735 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
1736
1737 for (unsigned i = 0; i < NumParts; ++i) {
1738 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1739 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
1740 Src1Regs[i], Src2Regs[i]);
1741 DstRegs.push_back(DstReg);
1742 }
1743
1744 if (NarrowTy0.isVector())
1745 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1746 else
1747 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1748
1749 MI.eraseFromParent();
1750 return Legalized;
1751}
1752
1753LegalizerHelper::LegalizeResult
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001754LegalizerHelper::fewerElementsVectorLoadStore(MachineInstr &MI, unsigned TypeIdx,
1755 LLT NarrowTy) {
1756 // FIXME: Don't know how to handle secondary types yet.
1757 if (TypeIdx != 0)
1758 return UnableToLegalize;
1759
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00001760 MachineMemOperand *MMO = *MI.memoperands_begin();
1761
1762 // This implementation doesn't work for atomics. Give up instead of doing
1763 // something invalid.
1764 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
1765 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
1766 return UnableToLegalize;
1767
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001768 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1769 unsigned ValReg = MI.getOperand(0).getReg();
1770 unsigned AddrReg = MI.getOperand(1).getReg();
1771 unsigned NarrowSize = NarrowTy.getSizeInBits();
1772 unsigned Size = MRI.getType(ValReg).getSizeInBits();
1773 unsigned NumParts = Size / NarrowSize;
1774
1775 SmallVector<unsigned, 8> NarrowRegs;
1776 if (!IsLoad)
1777 extractParts(ValReg, NarrowTy, NumParts, NarrowRegs);
1778
1779 const LLT OffsetTy =
1780 LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1781 MachineFunction &MF = *MI.getMF();
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00001782
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001783 for (unsigned Idx = 0; Idx < NumParts; ++Idx) {
1784 unsigned Adjustment = Idx * NarrowTy.getSizeInBits() / 8;
1785 unsigned Alignment = MinAlign(MMO->getAlignment(), Adjustment);
1786 unsigned NewAddrReg = 0;
1787 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, Adjustment);
1788 MachineMemOperand &NewMMO = *MF.getMachineMemOperand(
1789 MMO->getPointerInfo().getWithOffset(Adjustment), MMO->getFlags(),
1790 NarrowTy.getSizeInBits() / 8, Alignment);
1791 if (IsLoad) {
1792 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
1793 NarrowRegs.push_back(Dst);
1794 MIRBuilder.buildLoad(Dst, NewAddrReg, NewMMO);
1795 } else {
1796 MIRBuilder.buildStore(NarrowRegs[Idx], NewAddrReg, NewMMO);
1797 }
1798 }
1799 if (IsLoad) {
1800 if (NarrowTy.isVector())
1801 MIRBuilder.buildConcatVectors(ValReg, NarrowRegs);
1802 else
1803 MIRBuilder.buildBuildVector(ValReg, NarrowRegs);
1804 }
1805 MI.eraseFromParent();
1806 return Legalized;
1807}
1808
1809LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001810LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1811 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001812 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00001813
1814 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001815 switch (MI.getOpcode()) {
1816 case G_IMPLICIT_DEF:
1817 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
1818 case G_AND:
1819 case G_OR:
1820 case G_XOR:
1821 case G_ADD:
1822 case G_SUB:
1823 case G_MUL:
1824 case G_SMULH:
1825 case G_UMULH:
1826 case G_FADD:
1827 case G_FMUL:
1828 case G_FSUB:
1829 case G_FNEG:
1830 case G_FABS:
1831 case G_FDIV:
1832 case G_FREM:
1833 case G_FMA:
1834 case G_FPOW:
1835 case G_FEXP:
1836 case G_FEXP2:
1837 case G_FLOG:
1838 case G_FLOG2:
1839 case G_FLOG10:
1840 case G_FCEIL:
1841 case G_INTRINSIC_ROUND:
1842 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001843 case G_FCOS:
1844 case G_FSIN:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001845 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
1846 case G_ZEXT:
1847 case G_SEXT:
1848 case G_ANYEXT:
1849 case G_FPEXT:
1850 case G_FPTRUNC:
1851 case G_SITOFP:
1852 case G_UITOFP:
1853 case G_FPTOSI:
1854 case G_FPTOUI:
1855 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
1856 case G_ICMP:
1857 case G_FCMP:
1858 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00001859 case G_SELECT:
1860 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001861 case G_LOAD:
1862 case G_STORE:
1863 return fewerElementsVectorLoadStore(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00001864 default:
1865 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001866 }
1867}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001868
1869LegalizerHelper::LegalizeResult
Matt Arsenault211e89d2019-01-27 00:52:51 +00001870LegalizerHelper::narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT NewTy) {
1871 unsigned DstReg = MI.getOperand(0).getReg();
1872 unsigned Src0 = MI.getOperand(1).getReg();
1873 unsigned Src1 = MI.getOperand(2).getReg();
1874 LLT Ty = MRI.getType(DstReg);
1875 if (Ty.isVector())
1876 return UnableToLegalize;
1877
1878 unsigned Size = Ty.getSizeInBits();
1879 unsigned NewSize = Size / 2;
1880 if (Size != 2 * NewSize)
1881 return UnableToLegalize;
1882
1883 LLT HalfTy = LLT::scalar(NewSize);
1884 // TODO: if HalfTy != NewTy, handle the breakdown all at once?
1885
1886 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1887 unsigned Lo = MRI.createGenericVirtualRegister(HalfTy);
1888 unsigned Hi = MRI.createGenericVirtualRegister(HalfTy);
1889 unsigned ExtLo = MRI.createGenericVirtualRegister(Ty);
1890 unsigned ExtHi = MRI.createGenericVirtualRegister(Ty);
1891 unsigned ShiftedHi = MRI.createGenericVirtualRegister(Ty);
1892
1893 SmallVector<unsigned, 2> Src0Parts;
1894 SmallVector<unsigned, 2> Src1Parts;
1895
1896 extractParts(Src0, HalfTy, 2, Src0Parts);
1897 extractParts(Src1, HalfTy, 2, Src1Parts);
1898
1899 MIRBuilder.buildMul(Lo, Src0Parts[0], Src1Parts[0]);
1900
1901 // TODO: Use smulh or umulh depending on what the target has.
1902 MIRBuilder.buildUMulH(Hi, Src0Parts[1], Src1Parts[1]);
1903
1904 MIRBuilder.buildConstant(ShiftAmt, NewSize);
1905 MIRBuilder.buildAnyExt(ExtHi, Hi);
1906 MIRBuilder.buildShl(ShiftedHi, ExtHi, ShiftAmt);
1907
1908 MIRBuilder.buildZExt(ExtLo, Lo);
1909 MIRBuilder.buildOr(DstReg, ExtLo, ShiftedHi);
1910 MI.eraseFromParent();
1911 return Legalized;
1912}
1913
1914LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001915LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1916 unsigned Opc = MI.getOpcode();
1917 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00001918 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001919 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00001920 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001921 };
1922 switch (Opc) {
1923 default:
1924 return UnableToLegalize;
1925 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1926 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001927 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001928 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001929 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001930 return Legalized;
1931 }
1932 case TargetOpcode::G_CTLZ: {
1933 unsigned SrcReg = MI.getOperand(1).getReg();
1934 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001935 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1936 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001937 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
1938 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001939 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1940 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1941 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1942 SrcReg, MIBZero);
1943 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1944 MIBCtlzZU);
1945 MI.eraseFromParent();
1946 return Legalized;
1947 }
1948 // for now, we do this:
1949 // NewLen = NextPowerOf2(Len);
1950 // x = x | (x >> 1);
1951 // x = x | (x >> 2);
1952 // ...
1953 // x = x | (x >>16);
1954 // x = x | (x >>32); // for 64-bit input
1955 // Upto NewLen/2
1956 // return Len - popcount(x);
1957 //
1958 // Ref: "Hacker's Delight" by Henry Warren
1959 unsigned Op = SrcReg;
1960 unsigned NewLen = PowerOf2Ceil(Len);
1961 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1962 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1963 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001964 TargetOpcode::G_OR, {Ty},
1965 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
1966 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001967 Op = MIBOp->getOperand(0).getReg();
1968 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001969 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
1970 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1971 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001972 MI.eraseFromParent();
1973 return Legalized;
1974 }
1975 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1976 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001977 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001978 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001979 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001980 return Legalized;
1981 }
1982 case TargetOpcode::G_CTTZ: {
1983 unsigned SrcReg = MI.getOperand(1).getReg();
1984 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001985 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001986 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1987 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001988 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
1989 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001990 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1991 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1992 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1993 SrcReg, MIBZero);
1994 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1995 MIBCttzZU);
1996 MI.eraseFromParent();
1997 return Legalized;
1998 }
1999 // for now, we use: { return popcount(~x & (x - 1)); }
2000 // unless the target has ctlz but not ctpop, in which case we use:
2001 // { return 32 - nlz(~x & (x-1)); }
2002 // Ref: "Hacker's Delight" by Henry Warren
2003 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
2004 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002005 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002006 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002007 TargetOpcode::G_AND, {Ty},
2008 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
2009 {SrcReg, MIBCstNeg1})});
Diana Picus0528e2c2018-11-26 11:07:02 +00002010 if (!isSupported({TargetOpcode::G_CTPOP, {Ty}}) &&
2011 isSupported({TargetOpcode::G_CTLZ, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002012 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
2013 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002014 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2015 {MIBCstLen,
2016 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002017 MI.eraseFromParent();
2018 return Legalized;
2019 }
2020 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
2021 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
2022 return Legalized;
2023 }
2024 }
2025}