blob: c6e5f3e61242e523091c72cb8058a81e768b3cc7 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Tim Northover69fa84a2016-10-14 22:18:18 +000010/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000011/// individual instructions and the LegalizeMachineIR wrapper pass for the
12/// primary legalization.
13//
14//===----------------------------------------------------------------------===//
15
Tim Northover69fa84a2016-10-14 22:18:18 +000016#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000017#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000018#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000019#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000020#include "llvm/CodeGen/MachineRegisterInfo.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000021#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000022#include "llvm/CodeGen/TargetLowering.h"
23#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000024#include "llvm/Support/Debug.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000025#include "llvm/Support/MathExtras.h"
Tim Northover33b07d62016-07-22 20:03:43 +000026#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000027
Daniel Sanders5377fb32017-04-20 15:46:12 +000028#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000029
30using namespace llvm;
Daniel Sanders9ade5592018-01-29 17:37:29 +000031using namespace LegalizeActions;
Tim Northover33b07d62016-07-22 20:03:43 +000032
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000033LegalizerHelper::LegalizerHelper(MachineFunction &MF,
34 GISelChangeObserver &Observer)
35 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()),
36 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,
42 GISelChangeObserver &Observer)
43 : MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000044 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000045 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000046}
Tim Northover69fa84a2016-10-14 22:18:18 +000047LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000048LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000049 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000050
Daniel Sanders262ed0e2018-01-24 17:17:46 +000051 auto Step = LI.getAction(MI, MRI);
52 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000053 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000054 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000055 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000056 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000057 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000058 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000059 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000060 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000061 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000062 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000063 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000064 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000065 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000066 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000067 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000068 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000069 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000070 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000071 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000072 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000073 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
74 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000075 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000076 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000077 return UnableToLegalize;
78 }
79}
80
Tim Northover69fa84a2016-10-14 22:18:18 +000081void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
82 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000083 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000084 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000085 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000086}
87
Tim Northovere0418412017-02-08 23:23:39 +000088static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
89 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000090 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000091 assert((Size == 32 || Size == 64) && "Unsupported size");
92 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +000093 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000094 assert((Size == 32 || Size == 64) && "Unsupported size");
95 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000096 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000097 assert((Size == 32 || Size == 64) && "Unsupported size");
98 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +000099 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000100 assert((Size == 32 || Size == 64) && "Unsupported size");
101 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000102 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
103 assert(Size == 32 && "Unsupported size");
104 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000105 case TargetOpcode::G_FADD:
106 assert((Size == 32 || Size == 64) && "Unsupported size");
107 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000108 case TargetOpcode::G_FSUB:
109 assert((Size == 32 || Size == 64) && "Unsupported size");
110 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000111 case TargetOpcode::G_FMUL:
112 assert((Size == 32 || Size == 64) && "Unsupported size");
113 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000114 case TargetOpcode::G_FDIV:
115 assert((Size == 32 || Size == 64) && "Unsupported size");
116 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000117 case TargetOpcode::G_FREM:
118 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
119 case TargetOpcode::G_FPOW:
120 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000121 case TargetOpcode::G_FMA:
122 assert((Size == 32 || Size == 64) && "Unsupported size");
123 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000124 }
125 llvm_unreachable("Unknown libcall function");
126}
127
Diana Picusfc1675e2017-07-05 12:57:24 +0000128LegalizerHelper::LegalizeResult
129llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
130 const CallLowering::ArgInfo &Result,
131 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000132 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
133 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000134 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000135
Diana Picuse97822e2017-04-24 07:22:31 +0000136 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000137 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
138 MachineOperand::CreateES(Name), Result, Args))
139 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000140
Diana Picuse97822e2017-04-24 07:22:31 +0000141 return LegalizerHelper::Legalized;
142}
143
Diana Picus65ed3642018-01-17 13:34:10 +0000144// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000145static LegalizerHelper::LegalizeResult
146simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
147 Type *OpType) {
148 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000149
150 SmallVector<CallLowering::ArgInfo, 3> Args;
151 for (unsigned i = 1; i < MI.getNumOperands(); i++)
152 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000153 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000154 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000155}
156
Diana Picus65ed3642018-01-17 13:34:10 +0000157static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
158 Type *FromType) {
159 auto ToMVT = MVT::getVT(ToType);
160 auto FromMVT = MVT::getVT(FromType);
161
162 switch (Opcode) {
163 case TargetOpcode::G_FPEXT:
164 return RTLIB::getFPEXT(FromMVT, ToMVT);
165 case TargetOpcode::G_FPTRUNC:
166 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000167 case TargetOpcode::G_FPTOSI:
168 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
169 case TargetOpcode::G_FPTOUI:
170 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000171 case TargetOpcode::G_SITOFP:
172 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
173 case TargetOpcode::G_UITOFP:
174 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000175 }
176 llvm_unreachable("Unsupported libcall function");
177}
178
179static LegalizerHelper::LegalizeResult
180conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
181 Type *FromType) {
182 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
183 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
184 {{MI.getOperand(1).getReg(), FromType}});
185}
186
Tim Northover69fa84a2016-10-14 22:18:18 +0000187LegalizerHelper::LegalizeResult
188LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000189 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
190 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000191 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000192
Diana Picusfc1675e2017-07-05 12:57:24 +0000193 MIRBuilder.setInstr(MI);
194
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000195 switch (MI.getOpcode()) {
196 default:
197 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000198 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000199 case TargetOpcode::G_UDIV:
200 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000201 case TargetOpcode::G_UREM:
202 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000203 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000204 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
205 if (Status != Legalized)
206 return Status;
207 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000208 }
Diana Picus1314a282017-04-11 10:52:34 +0000209 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000210 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000211 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000212 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000213 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000214 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000215 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000216 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000217 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
218 if (Status != Legalized)
219 return Status;
220 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000221 }
Diana Picus65ed3642018-01-17 13:34:10 +0000222 case TargetOpcode::G_FPEXT: {
223 // FIXME: Support other floating point types (half, fp128 etc)
224 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
225 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
226 if (ToSize != 64 || FromSize != 32)
227 return UnableToLegalize;
228 LegalizeResult Status = conversionLibcall(
229 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
230 if (Status != Legalized)
231 return Status;
232 break;
233 }
234 case TargetOpcode::G_FPTRUNC: {
235 // FIXME: Support other floating point types (half, fp128 etc)
236 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
237 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
238 if (ToSize != 32 || FromSize != 64)
239 return UnableToLegalize;
240 LegalizeResult Status = conversionLibcall(
241 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
242 if (Status != Legalized)
243 return Status;
244 break;
245 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000246 case TargetOpcode::G_FPTOSI:
247 case TargetOpcode::G_FPTOUI: {
248 // FIXME: Support other types
249 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
250 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
251 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
252 return UnableToLegalize;
253 LegalizeResult Status = conversionLibcall(
254 MI, MIRBuilder, Type::getInt32Ty(Ctx),
255 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
256 if (Status != Legalized)
257 return Status;
258 break;
259 }
Diana Picus517531e2018-01-30 09:15:17 +0000260 case TargetOpcode::G_SITOFP:
261 case TargetOpcode::G_UITOFP: {
262 // FIXME: Support other types
263 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
264 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
265 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
266 return UnableToLegalize;
267 LegalizeResult Status = conversionLibcall(
268 MI, MIRBuilder,
269 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
270 Type::getInt32Ty(Ctx));
271 if (Status != Legalized)
272 return Status;
273 break;
274 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000275 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000276
277 MI.eraseFromParent();
278 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000279}
280
Tim Northover69fa84a2016-10-14 22:18:18 +0000281LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
282 unsigned TypeIdx,
283 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000284 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000285 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000286 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000287
288 MIRBuilder.setInstr(MI);
289
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000290 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
291 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000292
Tim Northover9656f142016-08-04 20:54:13 +0000293 switch (MI.getOpcode()) {
294 default:
295 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000296 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000297 // FIXME: add support for when SizeOp0 isn't an exact multiple of
298 // NarrowSize.
299 if (SizeOp0 % NarrowSize != 0)
300 return UnableToLegalize;
301 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000302
303 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000304 for (int i = 0; i < NumParts; ++i)
305 DstRegs.push_back(
306 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000307
308 unsigned DstReg = MI.getOperand(0).getReg();
309 if(MRI.getType(DstReg).isVector())
310 MIRBuilder.buildBuildVector(DstReg, DstRegs);
311 else
312 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000313 MI.eraseFromParent();
314 return Legalized;
315 }
Tim Northover9656f142016-08-04 20:54:13 +0000316 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000317 // FIXME: add support for when SizeOp0 isn't an exact multiple of
318 // NarrowSize.
319 if (SizeOp0 % NarrowSize != 0)
320 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000321 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000322 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000323
Tim Northoverb18ea162016-09-20 15:20:36 +0000324 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000325 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
326 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
327
Tim Northover0f140c72016-09-09 11:46:34 +0000328 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
329 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000330
331 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000332 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
333 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000334
Tim Northover0f140c72016-09-09 11:46:34 +0000335 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000336 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000337
338 DstRegs.push_back(DstReg);
339 CarryIn = CarryOut;
340 }
Tim Northover0f140c72016-09-09 11:46:34 +0000341 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000342 if(MRI.getType(DstReg).isVector())
343 MIRBuilder.buildBuildVector(DstReg, DstRegs);
344 else
345 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000346 MI.eraseFromParent();
347 return Legalized;
348 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000349 case TargetOpcode::G_EXTRACT: {
350 if (TypeIdx != 1)
351 return UnableToLegalize;
352
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000353 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
354 // FIXME: add support for when SizeOp1 isn't an exact multiple of
355 // NarrowSize.
356 if (SizeOp1 % NarrowSize != 0)
357 return UnableToLegalize;
358 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000359
360 SmallVector<unsigned, 2> SrcRegs, DstRegs;
361 SmallVector<uint64_t, 2> Indexes;
362 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
363
364 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000365 uint64_t OpStart = MI.getOperand(2).getImm();
366 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000367 for (int i = 0; i < NumParts; ++i) {
368 unsigned SrcStart = i * NarrowSize;
369
370 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
371 // No part of the extract uses this subregister, ignore it.
372 continue;
373 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
374 // The entire subregister is extracted, forward the value.
375 DstRegs.push_back(SrcRegs[i]);
376 continue;
377 }
378
379 // OpSegStart is where this destination segment would start in OpReg if it
380 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000381 int64_t ExtractOffset;
382 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000383 if (OpStart < SrcStart) {
384 ExtractOffset = 0;
385 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
386 } else {
387 ExtractOffset = OpStart - SrcStart;
388 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
389 }
390
391 unsigned SegReg = SrcRegs[i];
392 if (ExtractOffset != 0 || SegSize != NarrowSize) {
393 // A genuine extract is needed.
394 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
395 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
396 }
397
398 DstRegs.push_back(SegReg);
399 }
400
Amara Emerson5ec14602018-12-10 18:44:58 +0000401 unsigned DstReg = MI.getOperand(0).getReg();
402 if(MRI.getType(DstReg).isVector())
403 MIRBuilder.buildBuildVector(DstReg, DstRegs);
404 else
405 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000406 MI.eraseFromParent();
407 return Legalized;
408 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000409 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000410 // FIXME: add support for when SizeOp0 isn't an exact multiple of
411 // NarrowSize.
412 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000413 return UnableToLegalize;
414
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000415 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000416
417 SmallVector<unsigned, 2> SrcRegs, DstRegs;
418 SmallVector<uint64_t, 2> Indexes;
419 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
420
Tim Northover75e0b912017-03-06 18:23:04 +0000421 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000422 uint64_t OpStart = MI.getOperand(3).getImm();
423 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000424 for (int i = 0; i < NumParts; ++i) {
425 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000426
Tim Northover75e0b912017-03-06 18:23:04 +0000427 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000428 // No part of the insert affects this subregister, forward the original.
429 DstRegs.push_back(SrcRegs[i]);
430 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000431 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000432 // The entire subregister is defined by this insert, forward the new
433 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000434 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000435 continue;
436 }
437
Tim Northover2eb18d32017-03-07 21:24:33 +0000438 // OpSegStart is where this destination segment would start in OpReg if it
439 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000440 int64_t ExtractOffset, InsertOffset;
441 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000442 if (OpStart < DstStart) {
443 InsertOffset = 0;
444 ExtractOffset = DstStart - OpStart;
445 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
446 } else {
447 InsertOffset = OpStart - DstStart;
448 ExtractOffset = 0;
449 SegSize =
450 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
451 }
452
453 unsigned SegReg = OpReg;
454 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000455 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000456 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
457 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000458 }
459
Tim Northover75e0b912017-03-06 18:23:04 +0000460 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000461 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000462 DstRegs.push_back(DstReg);
463 }
464
465 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000466 unsigned DstReg = MI.getOperand(0).getReg();
467 if(MRI.getType(DstReg).isVector())
468 MIRBuilder.buildBuildVector(DstReg, DstRegs);
469 else
470 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000471 MI.eraseFromParent();
472 return Legalized;
473 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000474 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000475 // FIXME: add support for when SizeOp0 isn't an exact multiple of
476 // NarrowSize.
477 if (SizeOp0 % NarrowSize != 0)
478 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000479
480 const auto &MMO = **MI.memoperands_begin();
481 // This implementation doesn't work for atomics. Give up instead of doing
482 // something invalid.
483 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
484 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
485 return UnableToLegalize;
486
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000487 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000488 LLT OffsetTy = LLT::scalar(
489 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000490
491 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000492 for (int i = 0; i < NumParts; ++i) {
493 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000494 unsigned SrcReg = 0;
495 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000496 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000497
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000498 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
499 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000500 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
501 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000502
Daniel Sanders4e523662017-06-13 23:42:32 +0000503 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
504 Adjustment);
505
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000506 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000507
508 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000509 }
510 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000511 if(MRI.getType(DstReg).isVector())
512 MIRBuilder.buildBuildVector(DstReg, DstRegs);
513 else
514 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000515 MI.eraseFromParent();
516 return Legalized;
517 }
Justin Bognerfde01042017-01-18 17:29:54 +0000518 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000519 // FIXME: add support for when SizeOp0 isn't an exact multiple of
520 // NarrowSize.
521 if (SizeOp0 % NarrowSize != 0)
522 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000523
524 const auto &MMO = **MI.memoperands_begin();
525 // This implementation doesn't work for atomics. Give up instead of doing
526 // something invalid.
527 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
528 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
529 return UnableToLegalize;
530
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000531 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000532 LLT OffsetTy = LLT::scalar(
533 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000534
535 SmallVector<unsigned, 2> SrcRegs;
536 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
537
538 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000539 unsigned DstReg = 0;
540 unsigned Adjustment = i * NarrowSize / 8;
Volkan Keles60c6aff2018-10-25 17:52:19 +0000541 unsigned Alignment = MinAlign(MMO.getAlignment(), Adjustment);
Daniel Sanders4e523662017-06-13 23:42:32 +0000542
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000543 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
544 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(),
Volkan Keles60c6aff2018-10-25 17:52:19 +0000545 NarrowSize / 8, Alignment, MMO.getAAInfo(), MMO.getRanges(),
546 MMO.getSyncScopeID(), MMO.getOrdering(), MMO.getFailureOrdering());
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000547
Daniel Sanders4e523662017-06-13 23:42:32 +0000548 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
549 Adjustment);
550
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000551 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000552 }
553 MI.eraseFromParent();
554 return Legalized;
555 }
Igor Breger29537882017-04-07 14:41:59 +0000556 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000557 // FIXME: add support for when SizeOp0 isn't an exact multiple of
558 // NarrowSize.
559 if (SizeOp0 % NarrowSize != 0)
560 return UnableToLegalize;
561 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000562 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000563 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000564
565 SmallVector<unsigned, 2> DstRegs;
566 for (int i = 0; i < NumParts; ++i) {
567 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
568 ConstantInt *CI =
569 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
570 MIRBuilder.buildConstant(DstReg, *CI);
571 DstRegs.push_back(DstReg);
572 }
573 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000574 if(MRI.getType(DstReg).isVector())
575 MIRBuilder.buildBuildVector(DstReg, DstRegs);
576 else
577 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000578 MI.eraseFromParent();
579 return Legalized;
580 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000581 case TargetOpcode::G_AND:
582 case TargetOpcode::G_OR:
583 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000584 // Legalize bitwise operation:
585 // A = BinOp<Ty> B, C
586 // into:
587 // B1, ..., BN = G_UNMERGE_VALUES B
588 // C1, ..., CN = G_UNMERGE_VALUES C
589 // A1 = BinOp<Ty/N> B1, C2
590 // ...
591 // AN = BinOp<Ty/N> BN, CN
592 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000593
594 // FIXME: add support for when SizeOp0 isn't an exact multiple of
595 // NarrowSize.
596 if (SizeOp0 % NarrowSize != 0)
597 return UnableToLegalize;
598 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000599
600 // List the registers where the destination will be scattered.
601 SmallVector<unsigned, 2> DstRegs;
602 // List the registers where the first argument will be split.
603 SmallVector<unsigned, 2> SrcsReg1;
604 // List the registers where the second argument will be split.
605 SmallVector<unsigned, 2> SrcsReg2;
606 // Create all the temporary registers.
607 for (int i = 0; i < NumParts; ++i) {
608 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
609 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
610 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
611
612 DstRegs.push_back(DstReg);
613 SrcsReg1.push_back(SrcReg1);
614 SrcsReg2.push_back(SrcReg2);
615 }
616 // Explode the big arguments into smaller chunks.
617 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
618 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
619
620 // Do the operation on each small part.
621 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000622 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
623 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000624
625 // Gather the destination registers into the final destination.
626 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000627 if(MRI.getType(DstReg).isVector())
628 MIRBuilder.buildBuildVector(DstReg, DstRegs);
629 else
630 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000631 MI.eraseFromParent();
632 return Legalized;
633 }
Tim Northover9656f142016-08-04 20:54:13 +0000634 }
Tim Northover33b07d62016-07-22 20:03:43 +0000635}
636
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000637void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
638 unsigned OpIdx, unsigned ExtOpcode) {
639 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000640 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000641 MO.setReg(ExtB->getOperand(0).getReg());
642}
643
644void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
645 unsigned OpIdx, unsigned TruncOpcode) {
646 MachineOperand &MO = MI.getOperand(OpIdx);
647 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
648 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000649 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000650 MO.setReg(DstExt);
651}
652
Tim Northover69fa84a2016-10-14 22:18:18 +0000653LegalizerHelper::LegalizeResult
654LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000655 MIRBuilder.setInstr(MI);
656
Tim Northover32335812016-08-04 18:35:11 +0000657 switch (MI.getOpcode()) {
658 default:
659 return UnableToLegalize;
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000660 case TargetOpcode::G_UADDO:
661 case TargetOpcode::G_USUBO: {
662 if (TypeIdx == 1)
663 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000664 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
665 {MI.getOperand(2).getReg()});
666 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
667 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000668 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
669 ? TargetOpcode::G_ADD
670 : TargetOpcode::G_SUB;
671 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000672 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000673 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
674 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
675 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000676 TargetOpcode::G_AND, {WideTy},
677 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000678 // There is no overflow if the AndOp is the same as NewOp.
679 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
680 AndOp);
681 // Now trunc the NewOp to the original result.
682 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
683 MI.eraseFromParent();
684 return Legalized;
685 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000686 case TargetOpcode::G_CTTZ:
687 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
688 case TargetOpcode::G_CTLZ:
689 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
690 case TargetOpcode::G_CTPOP: {
691 // First ZEXT the input.
692 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
693 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
694 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
695 // The count is the same in the larger type except if the original
696 // value was zero. This can be handled by setting the bit just off
697 // the top of the original type.
698 auto TopBit =
699 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
700 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000701 TargetOpcode::G_OR, {WideTy},
702 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000703 }
704 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000705 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000706 // This is already the correct result for CTPOP and CTTZs
707 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
708 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
709 // The correct result is NewOp - (Difference in widety and current ty).
710 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000711 MIBNewOp = MIRBuilder.buildInstr(
712 TargetOpcode::G_SUB, {WideTy},
713 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000714 }
715 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +0000716 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000717 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000718 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
719 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000720 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +0000721 return Legalized;
722 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000723
Tim Northover61c16142016-08-04 21:39:49 +0000724 case TargetOpcode::G_ADD:
725 case TargetOpcode::G_AND:
726 case TargetOpcode::G_MUL:
727 case TargetOpcode::G_OR:
728 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000729 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +0000730 // Perform operation at larger width (any extension is fine here, high bits
731 // don't affect the result) and then truncate the result back to the
732 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000733 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000734 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
735 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
736 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000737 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000738 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000739
Roman Tereshin6d266382018-05-09 21:43:30 +0000740 case TargetOpcode::G_SHL:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000741 Observer.changingInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000742 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
743 // The "number of bits to shift" operand must preserve its value as an
744 // unsigned integer:
745 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
746 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000747 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000748 return Legalized;
749
Tim Northover7a753d92016-08-26 17:46:06 +0000750 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +0000751 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000752 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000753 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
754 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
755 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000756 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000757 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000758
Roman Tereshin6d266382018-05-09 21:43:30 +0000759 case TargetOpcode::G_ASHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000760 Observer.changingInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000761 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
762 // The "number of bits to shift" operand must preserve its value as an
763 // unsigned integer:
764 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
765 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000766 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +0000767 return Legalized;
768
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000769 case TargetOpcode::G_UDIV:
770 case TargetOpcode::G_UREM:
771 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000772 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000773 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
774 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
775 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000776 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000777 return Legalized;
778
779 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000780 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +0000781 if (TypeIdx == 0) {
782 // Perform operation at larger width (any extension is fine here, high
783 // bits don't affect the result) and then truncate the result back to the
784 // original type.
785 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
786 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
787 widenScalarDst(MI, WideTy);
788 } else {
789 // Explicit extension is required here since high bits affect the result.
790 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
791 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000792 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000793 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000794
Ahmed Bougachab6137062017-01-23 21:10:14 +0000795 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000796 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +0000797 if (TypeIdx != 0)
798 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000799 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000800 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000801 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000802 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000803
Ahmed Bougachad2948232017-01-20 01:37:24 +0000804 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +0000805 if (TypeIdx != 1)
806 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000807 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000808 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000809 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000810 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000811
812 case TargetOpcode::G_UITOFP:
813 if (TypeIdx != 1)
814 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000815 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000816 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000817 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000818 return Legalized;
819
820 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +0000821 if (TypeIdx != 0)
822 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000823 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000824 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
825 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000826 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000827 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000828
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000829 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +0000830 // For some types like i24, we might try to widen to i32. To properly handle
831 // this we should be using a dedicated extending load, until then avoid
832 // trying to legalize.
833 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
834 WideTy.getSizeInBits())
835 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +0000836 LLVM_FALLTHROUGH;
837 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000838 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000839 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000840 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000841 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000842 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000843
Tim Northover3c73e362016-08-23 18:20:09 +0000844 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000845 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
846 WideTy != LLT::scalar(8))
847 return UnableToLegalize;
848
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000849 Observer.changingInstr(MI);
Amara Emerson5a3bb682018-06-01 13:20:32 +0000850 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000851 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +0000852 return Legalized;
853 }
Tim Northoverea904f92016-08-19 22:40:00 +0000854 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000855 MachineOperand &SrcMO = MI.getOperand(1);
856 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
857 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000858 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000859 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
860
861 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000862 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +0000863 return Legalized;
864 }
Tim Northovera11be042016-08-19 22:40:08 +0000865 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000866 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +0000867 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000868 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +0000869 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000870 switch (WideTy.getSizeInBits()) {
871 case 32:
872 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
873 break;
874 case 64:
875 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
876 break;
877 default:
878 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +0000879 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000880 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000881 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
882
883 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000884 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +0000885 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +0000886 }
Matt Arsenaultbefee402019-01-09 07:34:14 +0000887 case TargetOpcode::G_IMPLICIT_DEF: {
888 Observer.changingInstr(MI);
889 widenScalarDst(MI, WideTy);
890 Observer.changedInstr(MI);
891 return Legalized;
892 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000893 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000894 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000895 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000896 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000897 return Legalized;
898
899 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000900 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000901 if (TypeIdx == 0)
902 widenScalarDst(MI, WideTy);
903 else {
904 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
905 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +0000906 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000907 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +0000908 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000909
910 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000911 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000912 if (TypeIdx == 0)
913 widenScalarDst(MI, WideTy);
914 else {
915 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
916 MI.getOperand(1).getPredicate()))
917 ? TargetOpcode::G_SEXT
918 : TargetOpcode::G_ZEXT;
919 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
920 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
921 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000922 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000923 return Legalized;
924
925 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +0000926 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000927 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000928 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000929 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +0000930 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000931
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000932 case TargetOpcode::G_PHI: {
933 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000934
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000935 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000936 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
937 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
938 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
939 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000940 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000941
942 MachineBasicBlock &MBB = *MI.getParent();
943 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
944 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000945 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000946 return Legalized;
947 }
Amara Emersoncbd86d82018-10-25 14:04:54 +0000948 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
949 if (TypeIdx != 2)
950 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +0000951 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +0000952 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000953 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +0000954 return Legalized;
Jessica Paquette453ab1d2018-12-21 17:05:26 +0000955
956 case TargetOpcode::G_FCEIL:
957 if (TypeIdx != 0)
958 return UnableToLegalize;
959 Observer.changingInstr(MI);
960 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_FPEXT);
961 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
962 Observer.changedInstr(MI);
963 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +0000964 }
Tim Northover33b07d62016-07-22 20:03:43 +0000965}
966
Tim Northover69fa84a2016-10-14 22:18:18 +0000967LegalizerHelper::LegalizeResult
968LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000969 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000970 MIRBuilder.setInstr(MI);
971
972 switch(MI.getOpcode()) {
973 default:
974 return UnableToLegalize;
975 case TargetOpcode::G_SREM:
976 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000977 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
978 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000979 .addDef(QuotReg)
980 .addUse(MI.getOperand(1).getReg())
981 .addUse(MI.getOperand(2).getReg());
982
Tim Northover0f140c72016-09-09 11:46:34 +0000983 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
984 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
985 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
986 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000987 MI.eraseFromParent();
988 return Legalized;
989 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000990 case TargetOpcode::G_SMULO:
991 case TargetOpcode::G_UMULO: {
992 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
993 // result.
994 unsigned Res = MI.getOperand(0).getReg();
995 unsigned Overflow = MI.getOperand(1).getReg();
996 unsigned LHS = MI.getOperand(2).getReg();
997 unsigned RHS = MI.getOperand(3).getReg();
998
999 MIRBuilder.buildMul(Res, LHS, RHS);
1000
1001 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1002 ? TargetOpcode::G_SMULH
1003 : TargetOpcode::G_UMULH;
1004
1005 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1006 MIRBuilder.buildInstr(Opcode)
1007 .addDef(HiPart)
1008 .addUse(LHS)
1009 .addUse(RHS);
1010
1011 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1012 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001013
1014 // For *signed* multiply, overflow is detected by checking:
1015 // (hi != (lo >> bitwidth-1))
1016 if (Opcode == TargetOpcode::G_SMULH) {
1017 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1018 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1019 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1020 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1021 .addDef(Shifted)
1022 .addUse(Res)
1023 .addUse(ShiftAmt);
1024 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1025 } else {
1026 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1027 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001028 MI.eraseFromParent();
1029 return Legalized;
1030 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001031 case TargetOpcode::G_FNEG: {
1032 // TODO: Handle vector types once we are able to
1033 // represent them.
1034 if (Ty.isVector())
1035 return UnableToLegalize;
1036 unsigned Res = MI.getOperand(0).getReg();
1037 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001038 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001039 switch (Ty.getSizeInBits()) {
1040 case 16:
1041 ZeroTy = Type::getHalfTy(Ctx);
1042 break;
1043 case 32:
1044 ZeroTy = Type::getFloatTy(Ctx);
1045 break;
1046 case 64:
1047 ZeroTy = Type::getDoubleTy(Ctx);
1048 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001049 case 128:
1050 ZeroTy = Type::getFP128Ty(Ctx);
1051 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001052 default:
1053 llvm_unreachable("unexpected floating-point type");
1054 }
1055 ConstantFP &ZeroForNegation =
1056 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001057 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001058 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1059 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001060 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001061 .addUse(MI.getOperand(1).getReg());
1062 MI.eraseFromParent();
1063 return Legalized;
1064 }
Volkan Keles225921a2017-03-10 21:25:09 +00001065 case TargetOpcode::G_FSUB: {
1066 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1067 // First, check if G_FNEG is marked as Lower. If so, we may
1068 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001069 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001070 return UnableToLegalize;
1071 unsigned Res = MI.getOperand(0).getReg();
1072 unsigned LHS = MI.getOperand(1).getReg();
1073 unsigned RHS = MI.getOperand(2).getReg();
1074 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1075 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1076 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1077 .addDef(Res)
1078 .addUse(LHS)
1079 .addUse(Neg);
1080 MI.eraseFromParent();
1081 return Legalized;
1082 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001083 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1084 unsigned OldValRes = MI.getOperand(0).getReg();
1085 unsigned SuccessRes = MI.getOperand(1).getReg();
1086 unsigned Addr = MI.getOperand(2).getReg();
1087 unsigned CmpVal = MI.getOperand(3).getReg();
1088 unsigned NewVal = MI.getOperand(4).getReg();
1089 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1090 **MI.memoperands_begin());
1091 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1092 MI.eraseFromParent();
1093 return Legalized;
1094 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001095 case TargetOpcode::G_LOAD:
1096 case TargetOpcode::G_SEXTLOAD:
1097 case TargetOpcode::G_ZEXTLOAD: {
1098 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1099 unsigned DstReg = MI.getOperand(0).getReg();
1100 unsigned PtrReg = MI.getOperand(1).getReg();
1101 LLT DstTy = MRI.getType(DstReg);
1102 auto &MMO = **MI.memoperands_begin();
1103
1104 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001105 // In the case of G_LOAD, this was a non-extending load already and we're
1106 // about to lower to the same instruction.
1107 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1108 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001109 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1110 MI.eraseFromParent();
1111 return Legalized;
1112 }
1113
1114 if (DstTy.isScalar()) {
1115 unsigned TmpReg = MRI.createGenericVirtualRegister(
1116 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1117 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1118 switch (MI.getOpcode()) {
1119 default:
1120 llvm_unreachable("Unexpected opcode");
1121 case TargetOpcode::G_LOAD:
1122 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1123 break;
1124 case TargetOpcode::G_SEXTLOAD:
1125 MIRBuilder.buildSExt(DstReg, TmpReg);
1126 break;
1127 case TargetOpcode::G_ZEXTLOAD:
1128 MIRBuilder.buildZExt(DstReg, TmpReg);
1129 break;
1130 }
1131 MI.eraseFromParent();
1132 return Legalized;
1133 }
1134
1135 return UnableToLegalize;
1136 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001137 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1138 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1139 case TargetOpcode::G_CTLZ:
1140 case TargetOpcode::G_CTTZ:
1141 case TargetOpcode::G_CTPOP:
1142 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001143 case G_UADDE: {
1144 unsigned Res = MI.getOperand(0).getReg();
1145 unsigned CarryOut = MI.getOperand(1).getReg();
1146 unsigned LHS = MI.getOperand(2).getReg();
1147 unsigned RHS = MI.getOperand(3).getReg();
1148 unsigned CarryIn = MI.getOperand(4).getReg();
1149
1150 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1151 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1152
1153 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1154 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1155 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1156 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1157
1158 MI.eraseFromParent();
1159 return Legalized;
1160 }
Tim Northovercecee562016-08-26 17:46:13 +00001161 }
1162}
1163
Tim Northover69fa84a2016-10-14 22:18:18 +00001164LegalizerHelper::LegalizeResult
1165LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1166 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +00001167 // FIXME: Don't know how to handle secondary types yet.
1168 if (TypeIdx != 0)
1169 return UnableToLegalize;
Volkan Keles574d7372018-12-14 22:11:20 +00001170
1171 MIRBuilder.setInstr(MI);
Tim Northover33b07d62016-07-22 20:03:43 +00001172 switch (MI.getOpcode()) {
1173 default:
1174 return UnableToLegalize;
1175 case TargetOpcode::G_ADD: {
1176 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +00001177 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +00001178 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1179 int NumParts = Size / NarrowSize;
1180 // FIXME: Don't know how to handle the situation where the small vectors
1181 // aren't all the same size yet.
1182 if (Size % NarrowSize != 0)
1183 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00001184
Tim Northoverb18ea162016-09-20 15:20:36 +00001185 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +00001186 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
1187 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
1188
1189 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +00001190 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1191 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +00001192 DstRegs.push_back(DstReg);
1193 }
1194
Amara Emerson5ec14602018-12-10 18:44:58 +00001195 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +00001196 MI.eraseFromParent();
1197 return Legalized;
1198 }
Volkan Keles574d7372018-12-14 22:11:20 +00001199 case TargetOpcode::G_LOAD:
1200 case TargetOpcode::G_STORE: {
1201 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1202 unsigned ValReg = MI.getOperand(0).getReg();
1203 unsigned AddrReg = MI.getOperand(1).getReg();
1204 unsigned NarrowSize = NarrowTy.getSizeInBits();
1205 unsigned Size = MRI.getType(ValReg).getSizeInBits();
1206 unsigned NumParts = Size / NarrowSize;
1207
1208 SmallVector<unsigned, 8> NarrowRegs;
1209 if (!IsLoad)
1210 extractParts(ValReg, NarrowTy, NumParts, NarrowRegs);
1211
1212 const LLT OffsetTy =
1213 LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1214 MachineFunction &MF = *MI.getMF();
1215 MachineMemOperand *MMO = *MI.memoperands_begin();
1216 for (unsigned Idx = 0; Idx < NumParts; ++Idx) {
1217 unsigned Adjustment = Idx * NarrowTy.getSizeInBits() / 8;
1218 unsigned Alignment = MinAlign(MMO->getAlignment(), Adjustment);
1219 unsigned NewAddrReg = 0;
1220 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, Adjustment);
1221 MachineMemOperand &NewMMO = *MF.getMachineMemOperand(
1222 MMO->getPointerInfo().getWithOffset(Adjustment), MMO->getFlags(),
1223 NarrowTy.getSizeInBits() / 8, Alignment);
1224 if (IsLoad) {
1225 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
1226 NarrowRegs.push_back(Dst);
1227 MIRBuilder.buildLoad(Dst, NewAddrReg, NewMMO);
1228 } else {
1229 MIRBuilder.buildStore(NarrowRegs[Idx], NewAddrReg, NewMMO);
1230 }
1231 }
1232 if (IsLoad) {
1233 if (NarrowTy.isVector())
1234 MIRBuilder.buildConcatVectors(ValReg, NarrowRegs);
1235 else
1236 MIRBuilder.buildBuildVector(ValReg, NarrowRegs);
1237 }
1238 MI.eraseFromParent();
1239 return Legalized;
1240 }
Tim Northover33b07d62016-07-22 20:03:43 +00001241 }
1242}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001243
1244LegalizerHelper::LegalizeResult
1245LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
1246 unsigned Opc = MI.getOpcode();
1247 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00001248 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001249 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00001250 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001251 };
1252 switch (Opc) {
1253 default:
1254 return UnableToLegalize;
1255 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1256 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001257 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001258 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001259 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001260 return Legalized;
1261 }
1262 case TargetOpcode::G_CTLZ: {
1263 unsigned SrcReg = MI.getOperand(1).getReg();
1264 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001265 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty}})) {
1266 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001267 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
1268 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001269 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1270 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1271 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1272 SrcReg, MIBZero);
1273 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1274 MIBCtlzZU);
1275 MI.eraseFromParent();
1276 return Legalized;
1277 }
1278 // for now, we do this:
1279 // NewLen = NextPowerOf2(Len);
1280 // x = x | (x >> 1);
1281 // x = x | (x >> 2);
1282 // ...
1283 // x = x | (x >>16);
1284 // x = x | (x >>32); // for 64-bit input
1285 // Upto NewLen/2
1286 // return Len - popcount(x);
1287 //
1288 // Ref: "Hacker's Delight" by Henry Warren
1289 unsigned Op = SrcReg;
1290 unsigned NewLen = PowerOf2Ceil(Len);
1291 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
1292 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
1293 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001294 TargetOpcode::G_OR, {Ty},
1295 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
1296 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001297 Op = MIBOp->getOperand(0).getReg();
1298 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001299 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
1300 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1301 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001302 MI.eraseFromParent();
1303 return Legalized;
1304 }
1305 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
1306 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001307 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001308 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001309 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001310 return Legalized;
1311 }
1312 case TargetOpcode::G_CTTZ: {
1313 unsigned SrcReg = MI.getOperand(1).getReg();
1314 unsigned Len = Ty.getSizeInBits();
Diana Picus0528e2c2018-11-26 11:07:02 +00001315 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001316 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
1317 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001318 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
1319 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001320 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
1321 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
1322 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
1323 SrcReg, MIBZero);
1324 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
1325 MIBCttzZU);
1326 MI.eraseFromParent();
1327 return Legalized;
1328 }
1329 // for now, we use: { return popcount(~x & (x - 1)); }
1330 // unless the target has ctlz but not ctpop, in which case we use:
1331 // { return 32 - nlz(~x & (x-1)); }
1332 // Ref: "Hacker's Delight" by Henry Warren
1333 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
1334 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001335 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001336 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001337 TargetOpcode::G_AND, {Ty},
1338 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
1339 {SrcReg, MIBCstNeg1})});
Diana Picus0528e2c2018-11-26 11:07:02 +00001340 if (!isSupported({TargetOpcode::G_CTPOP, {Ty}}) &&
1341 isSupported({TargetOpcode::G_CTLZ, {Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001342 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
1343 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001344 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
1345 {MIBCstLen,
1346 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001347 MI.eraseFromParent();
1348 return Legalized;
1349 }
1350 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
1351 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
1352 return Legalized;
1353 }
1354 }
1355}