blob: d8dc936eef2e83092bf078ee81e5c9a07af06787 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Tim Northover69fa84a2016-10-14 22:18:18 +000010/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000011/// individual instructions and the LegalizeMachineIR wrapper pass for the
12/// primary legalization.
13//
14//===----------------------------------------------------------------------===//
15
Tim Northover69fa84a2016-10-14 22:18:18 +000016#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000017#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000018#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000020#include "llvm/CodeGen/TargetLowering.h"
21#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000022#include "llvm/Support/Debug.h"
23#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000024
Tim Northover33b07d62016-07-22 20:03:43 +000025
Daniel Sanders5377fb32017-04-20 15:46:12 +000026#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000027
28using namespace llvm;
29
Tim Northover69fa84a2016-10-14 22:18:18 +000030LegalizerHelper::LegalizerHelper(MachineFunction &MF)
Volkan Keles685fbda2017-03-10 18:34:57 +000031 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
Tim Northover33b07d62016-07-22 20:03:43 +000032 MIRBuilder.setMF(MF);
33}
34
Tim Northover69fa84a2016-10-14 22:18:18 +000035LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000036LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Daniel Sanders5377fb32017-04-20 15:46:12 +000037 DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
38
Daniel Sanders262ed0e2018-01-24 17:17:46 +000039 auto Step = LI.getAction(MI, MRI);
40 switch (Step.Action) {
Tim Northover69fa84a2016-10-14 22:18:18 +000041 case LegalizerInfo::Legal:
Daniel Sanders5377fb32017-04-20 15:46:12 +000042 DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000043 return AlreadyLegal;
Tim Northover69fa84a2016-10-14 22:18:18 +000044 case LegalizerInfo::Libcall:
Daniel Sanders5377fb32017-04-20 15:46:12 +000045 DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000046 return libcall(MI);
Tim Northover69fa84a2016-10-14 22:18:18 +000047 case LegalizerInfo::NarrowScalar:
Daniel Sanders5377fb32017-04-20 15:46:12 +000048 DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000049 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Tim Northover69fa84a2016-10-14 22:18:18 +000050 case LegalizerInfo::WidenScalar:
Daniel Sanders5377fb32017-04-20 15:46:12 +000051 DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000052 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Tim Northover69fa84a2016-10-14 22:18:18 +000053 case LegalizerInfo::Lower:
Daniel Sanders5377fb32017-04-20 15:46:12 +000054 DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000055 return lower(MI, Step.TypeIdx, Step.NewType);
Tim Northover69fa84a2016-10-14 22:18:18 +000056 case LegalizerInfo::FewerElements:
Daniel Sanders5377fb32017-04-20 15:46:12 +000057 DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000058 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Tim Northover91366172017-02-15 23:22:50 +000059 case LegalizerInfo::Custom:
Daniel Sanders5377fb32017-04-20 15:46:12 +000060 DEBUG(dbgs() << ".. Custom legalization\n");
Volkan Keles685fbda2017-03-10 18:34:57 +000061 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
62 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000063 default:
Daniel Sanders5377fb32017-04-20 15:46:12 +000064 DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000065 return UnableToLegalize;
66 }
67}
68
Tim Northover69fa84a2016-10-14 22:18:18 +000069void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
70 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000071 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000072 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000073 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000074}
75
Tim Northovere0418412017-02-08 23:23:39 +000076static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
77 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +000078 case TargetOpcode::G_SDIV:
79 assert(Size == 32 && "Unsupported size");
80 return RTLIB::SDIV_I32;
81 case TargetOpcode::G_UDIV:
82 assert(Size == 32 && "Unsupported size");
83 return RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +000084 case TargetOpcode::G_SREM:
85 assert(Size == 32 && "Unsupported size");
86 return RTLIB::SREM_I32;
87 case TargetOpcode::G_UREM:
88 assert(Size == 32 && "Unsupported size");
89 return RTLIB::UREM_I32;
Diana Picus1314a282017-04-11 10:52:34 +000090 case TargetOpcode::G_FADD:
91 assert((Size == 32 || Size == 64) && "Unsupported size");
92 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +000093 case TargetOpcode::G_FSUB:
94 assert((Size == 32 || Size == 64) && "Unsupported size");
95 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +000096 case TargetOpcode::G_FMUL:
97 assert((Size == 32 || Size == 64) && "Unsupported size");
98 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +000099 case TargetOpcode::G_FDIV:
100 assert((Size == 32 || Size == 64) && "Unsupported size");
101 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000102 case TargetOpcode::G_FREM:
103 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
104 case TargetOpcode::G_FPOW:
105 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000106 case TargetOpcode::G_FMA:
107 assert((Size == 32 || Size == 64) && "Unsupported size");
108 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000109 }
110 llvm_unreachable("Unknown libcall function");
111}
112
Diana Picusfc1675e2017-07-05 12:57:24 +0000113LegalizerHelper::LegalizeResult
114llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
115 const CallLowering::ArgInfo &Result,
116 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000117 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
118 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000119 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000120
Diana Picuse97822e2017-04-24 07:22:31 +0000121 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000122 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
123 MachineOperand::CreateES(Name), Result, Args))
124 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000125
Diana Picuse97822e2017-04-24 07:22:31 +0000126 return LegalizerHelper::Legalized;
127}
128
Diana Picus65ed3642018-01-17 13:34:10 +0000129// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000130static LegalizerHelper::LegalizeResult
131simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
132 Type *OpType) {
133 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000134
135 SmallVector<CallLowering::ArgInfo, 3> Args;
136 for (unsigned i = 1; i < MI.getNumOperands(); i++)
137 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000138 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000139 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000140}
141
Diana Picus65ed3642018-01-17 13:34:10 +0000142static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
143 Type *FromType) {
144 auto ToMVT = MVT::getVT(ToType);
145 auto FromMVT = MVT::getVT(FromType);
146
147 switch (Opcode) {
148 case TargetOpcode::G_FPEXT:
149 return RTLIB::getFPEXT(FromMVT, ToMVT);
150 case TargetOpcode::G_FPTRUNC:
151 return RTLIB::getFPROUND(FromMVT, ToMVT);
152 }
153 llvm_unreachable("Unsupported libcall function");
154}
155
156static LegalizerHelper::LegalizeResult
157conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
158 Type *FromType) {
159 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
160 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
161 {{MI.getOperand(1).getReg(), FromType}});
162}
163
Tim Northover69fa84a2016-10-14 22:18:18 +0000164LegalizerHelper::LegalizeResult
165LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000166 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
167 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000168 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000169
Diana Picusfc1675e2017-07-05 12:57:24 +0000170 MIRBuilder.setInstr(MI);
171
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000172 switch (MI.getOpcode()) {
173 default:
174 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000175 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000176 case TargetOpcode::G_UDIV:
177 case TargetOpcode::G_SREM:
178 case TargetOpcode::G_UREM: {
179 Type *HLTy = Type::getInt32Ty(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000180 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
181 if (Status != Legalized)
182 return Status;
183 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000184 }
Diana Picus1314a282017-04-11 10:52:34 +0000185 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000186 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000187 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000188 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000189 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000190 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000191 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000192 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000193 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
194 if (Status != Legalized)
195 return Status;
196 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000197 }
Diana Picus65ed3642018-01-17 13:34:10 +0000198 case TargetOpcode::G_FPEXT: {
199 // FIXME: Support other floating point types (half, fp128 etc)
200 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
201 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
202 if (ToSize != 64 || FromSize != 32)
203 return UnableToLegalize;
204 LegalizeResult Status = conversionLibcall(
205 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
206 if (Status != Legalized)
207 return Status;
208 break;
209 }
210 case TargetOpcode::G_FPTRUNC: {
211 // FIXME: Support other floating point types (half, fp128 etc)
212 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
213 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
214 if (ToSize != 32 || FromSize != 64)
215 return UnableToLegalize;
216 LegalizeResult Status = conversionLibcall(
217 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
218 if (Status != Legalized)
219 return Status;
220 break;
221 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000222 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000223
224 MI.eraseFromParent();
225 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000226}
227
Tim Northover69fa84a2016-10-14 22:18:18 +0000228LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
229 unsigned TypeIdx,
230 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000231 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000232 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000233 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000234
235 MIRBuilder.setInstr(MI);
236
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000237 int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
238 int64_t NarrowSize = NarrowTy.getSizeInBits();
239
Tim Northover9656f142016-08-04 20:54:13 +0000240 switch (MI.getOpcode()) {
241 default:
242 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000243 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000244 // FIXME: add support for when SizeOp0 isn't an exact multiple of
245 // NarrowSize.
246 if (SizeOp0 % NarrowSize != 0)
247 return UnableToLegalize;
248 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000249
250 SmallVector<unsigned, 2> DstRegs;
251 for (int i = 0; i < NumParts; ++i) {
252 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
253 MIRBuilder.buildUndef(Dst);
254 DstRegs.push_back(Dst);
255 }
256 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
257 MI.eraseFromParent();
258 return Legalized;
259 }
Tim Northover9656f142016-08-04 20:54:13 +0000260 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000261 // FIXME: add support for when SizeOp0 isn't an exact multiple of
262 // NarrowSize.
263 if (SizeOp0 % NarrowSize != 0)
264 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000265 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000266 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000267
Tim Northoverb18ea162016-09-20 15:20:36 +0000268 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000269 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
270 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
271
Tim Northover0f140c72016-09-09 11:46:34 +0000272 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
273 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000274
275 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000276 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
277 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000278
Tim Northover0f140c72016-09-09 11:46:34 +0000279 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000280 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000281
282 DstRegs.push_back(DstReg);
283 CarryIn = CarryOut;
284 }
Tim Northover0f140c72016-09-09 11:46:34 +0000285 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000286 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000287 MI.eraseFromParent();
288 return Legalized;
289 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000290 case TargetOpcode::G_EXTRACT: {
291 if (TypeIdx != 1)
292 return UnableToLegalize;
293
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000294 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
295 // FIXME: add support for when SizeOp1 isn't an exact multiple of
296 // NarrowSize.
297 if (SizeOp1 % NarrowSize != 0)
298 return UnableToLegalize;
299 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000300
301 SmallVector<unsigned, 2> SrcRegs, DstRegs;
302 SmallVector<uint64_t, 2> Indexes;
303 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
304
305 unsigned OpReg = MI.getOperand(0).getReg();
306 int64_t OpStart = MI.getOperand(2).getImm();
307 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
308 for (int i = 0; i < NumParts; ++i) {
309 unsigned SrcStart = i * NarrowSize;
310
311 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
312 // No part of the extract uses this subregister, ignore it.
313 continue;
314 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
315 // The entire subregister is extracted, forward the value.
316 DstRegs.push_back(SrcRegs[i]);
317 continue;
318 }
319
320 // OpSegStart is where this destination segment would start in OpReg if it
321 // extended infinitely in both directions.
322 int64_t ExtractOffset, SegSize;
323 if (OpStart < SrcStart) {
324 ExtractOffset = 0;
325 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
326 } else {
327 ExtractOffset = OpStart - SrcStart;
328 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
329 }
330
331 unsigned SegReg = SrcRegs[i];
332 if (ExtractOffset != 0 || SegSize != NarrowSize) {
333 // A genuine extract is needed.
334 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
335 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
336 }
337
338 DstRegs.push_back(SegReg);
339 }
340
341 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
342 MI.eraseFromParent();
343 return Legalized;
344 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000345 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000346 // FIXME: add support for when SizeOp0 isn't an exact multiple of
347 // NarrowSize.
348 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000349 return UnableToLegalize;
350
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000351 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000352
353 SmallVector<unsigned, 2> SrcRegs, DstRegs;
354 SmallVector<uint64_t, 2> Indexes;
355 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
356
Tim Northover75e0b912017-03-06 18:23:04 +0000357 unsigned OpReg = MI.getOperand(2).getReg();
358 int64_t OpStart = MI.getOperand(3).getImm();
359 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000360 for (int i = 0; i < NumParts; ++i) {
361 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000362
Tim Northover75e0b912017-03-06 18:23:04 +0000363 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000364 // No part of the insert affects this subregister, forward the original.
365 DstRegs.push_back(SrcRegs[i]);
366 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000367 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000368 // The entire subregister is defined by this insert, forward the new
369 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000370 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000371 continue;
372 }
373
Tim Northover2eb18d32017-03-07 21:24:33 +0000374 // OpSegStart is where this destination segment would start in OpReg if it
375 // extended infinitely in both directions.
376 int64_t ExtractOffset, InsertOffset, SegSize;
377 if (OpStart < DstStart) {
378 InsertOffset = 0;
379 ExtractOffset = DstStart - OpStart;
380 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
381 } else {
382 InsertOffset = OpStart - DstStart;
383 ExtractOffset = 0;
384 SegSize =
385 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
386 }
387
388 unsigned SegReg = OpReg;
389 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000390 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000391 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
392 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000393 }
394
Tim Northover75e0b912017-03-06 18:23:04 +0000395 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000396 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000397 DstRegs.push_back(DstReg);
398 }
399
400 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000401 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000402 MI.eraseFromParent();
403 return Legalized;
404 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000405 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000406 // FIXME: add support for when SizeOp0 isn't an exact multiple of
407 // NarrowSize.
408 if (SizeOp0 % NarrowSize != 0)
409 return UnableToLegalize;
410 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000411 LLT OffsetTy = LLT::scalar(
412 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000413
414 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000415 for (int i = 0; i < NumParts; ++i) {
416 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000417 unsigned SrcReg = 0;
418 unsigned Adjustment = i * NarrowSize / 8;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000419
Daniel Sanders4e523662017-06-13 23:42:32 +0000420 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
421 Adjustment);
422
Justin Bognere094cc42017-01-20 00:30:17 +0000423 // TODO: This is conservatively correct, but we probably want to split the
424 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000425 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
426
427 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000428 }
429 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000430 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000431 MI.eraseFromParent();
432 return Legalized;
433 }
Justin Bognerfde01042017-01-18 17:29:54 +0000434 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000435 // FIXME: add support for when SizeOp0 isn't an exact multiple of
436 // NarrowSize.
437 if (SizeOp0 % NarrowSize != 0)
438 return UnableToLegalize;
439 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000440 LLT OffsetTy = LLT::scalar(
441 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000442
443 SmallVector<unsigned, 2> SrcRegs;
444 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
445
446 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000447 unsigned DstReg = 0;
448 unsigned Adjustment = i * NarrowSize / 8;
449
450 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
451 Adjustment);
452
Justin Bognere094cc42017-01-20 00:30:17 +0000453 // TODO: This is conservatively correct, but we probably want to split the
454 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000455 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
456 }
457 MI.eraseFromParent();
458 return Legalized;
459 }
Igor Breger29537882017-04-07 14:41:59 +0000460 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000461 // FIXME: add support for when SizeOp0 isn't an exact multiple of
462 // NarrowSize.
463 if (SizeOp0 % NarrowSize != 0)
464 return UnableToLegalize;
465 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000466 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000467 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000468
469 SmallVector<unsigned, 2> DstRegs;
470 for (int i = 0; i < NumParts; ++i) {
471 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
472 ConstantInt *CI =
473 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
474 MIRBuilder.buildConstant(DstReg, *CI);
475 DstRegs.push_back(DstReg);
476 }
477 unsigned DstReg = MI.getOperand(0).getReg();
478 MIRBuilder.buildMerge(DstReg, DstRegs);
479 MI.eraseFromParent();
480 return Legalized;
481 }
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000482 case TargetOpcode::G_OR: {
483 // Legalize bitwise operation:
484 // A = BinOp<Ty> B, C
485 // into:
486 // B1, ..., BN = G_UNMERGE_VALUES B
487 // C1, ..., CN = G_UNMERGE_VALUES C
488 // A1 = BinOp<Ty/N> B1, C2
489 // ...
490 // AN = BinOp<Ty/N> BN, CN
491 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000492
493 // FIXME: add support for when SizeOp0 isn't an exact multiple of
494 // NarrowSize.
495 if (SizeOp0 % NarrowSize != 0)
496 return UnableToLegalize;
497 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000498
499 // List the registers where the destination will be scattered.
500 SmallVector<unsigned, 2> DstRegs;
501 // List the registers where the first argument will be split.
502 SmallVector<unsigned, 2> SrcsReg1;
503 // List the registers where the second argument will be split.
504 SmallVector<unsigned, 2> SrcsReg2;
505 // Create all the temporary registers.
506 for (int i = 0; i < NumParts; ++i) {
507 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
508 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
509 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
510
511 DstRegs.push_back(DstReg);
512 SrcsReg1.push_back(SrcReg1);
513 SrcsReg2.push_back(SrcReg2);
514 }
515 // Explode the big arguments into smaller chunks.
516 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
517 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
518
519 // Do the operation on each small part.
520 for (int i = 0; i < NumParts; ++i)
521 MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
522
523 // Gather the destination registers into the final destination.
524 unsigned DstReg = MI.getOperand(0).getReg();
525 MIRBuilder.buildMerge(DstReg, DstRegs);
526 MI.eraseFromParent();
527 return Legalized;
528 }
Tim Northover9656f142016-08-04 20:54:13 +0000529 }
Tim Northover33b07d62016-07-22 20:03:43 +0000530}
531
Tim Northover69fa84a2016-10-14 22:18:18 +0000532LegalizerHelper::LegalizeResult
533LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000534 MIRBuilder.setInstr(MI);
535
Tim Northover32335812016-08-04 18:35:11 +0000536 switch (MI.getOpcode()) {
537 default:
538 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000539 case TargetOpcode::G_ADD:
540 case TargetOpcode::G_AND:
541 case TargetOpcode::G_MUL:
542 case TargetOpcode::G_OR:
543 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000544 case TargetOpcode::G_SUB:
545 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000546 // Perform operation at larger width (any extension is fine here, high bits
547 // don't affect the result) and then truncate the result back to the
548 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000549 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
550 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
551 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
552 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000553
Tim Northover0f140c72016-09-09 11:46:34 +0000554 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
555 MIRBuilder.buildInstr(MI.getOpcode())
556 .addDef(DstExt)
557 .addUse(Src1Ext)
558 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000559
Tim Northover0f140c72016-09-09 11:46:34 +0000560 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000561 MI.eraseFromParent();
562 return Legalized;
563 }
Tim Northover7a753d92016-08-26 17:46:06 +0000564 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000565 case TargetOpcode::G_UDIV:
Diana Picusdf4100b2017-07-18 09:08:47 +0000566 case TargetOpcode::G_SREM:
567 case TargetOpcode::G_UREM:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000568 case TargetOpcode::G_ASHR:
569 case TargetOpcode::G_LSHR: {
570 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
Diana Picusdf4100b2017-07-18 09:08:47 +0000571 MI.getOpcode() == TargetOpcode::G_SREM ||
Justin Bognerddb80ae2017-01-19 07:51:17 +0000572 MI.getOpcode() == TargetOpcode::G_ASHR
573 ? TargetOpcode::G_SEXT
574 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000575
Tim Northover0f140c72016-09-09 11:46:34 +0000576 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
577 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
578 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000579
Tim Northover0f140c72016-09-09 11:46:34 +0000580 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
581 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
582 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000583
Tim Northover0f140c72016-09-09 11:46:34 +0000584 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
585 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000586 .addDef(ResExt)
587 .addUse(LHSExt)
588 .addUse(RHSExt);
589
Tim Northover0f140c72016-09-09 11:46:34 +0000590 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000591 MI.eraseFromParent();
592 return Legalized;
593 }
Tim Northover868332d2017-02-06 23:41:27 +0000594 case TargetOpcode::G_SELECT: {
595 if (TypeIdx != 0)
596 return UnableToLegalize;
597
598 // Perform operation at larger width (any extension is fine here, high bits
599 // don't affect the result) and then truncate the result back to the
600 // original type.
601 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
602 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
603 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
604 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
605
606 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
607 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
608 .addDef(DstExt)
609 .addReg(MI.getOperand(1).getReg())
610 .addUse(Src1Ext)
611 .addUse(Src2Ext);
612
613 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
614 MI.eraseFromParent();
615 return Legalized;
616 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000617 case TargetOpcode::G_FPTOSI:
618 case TargetOpcode::G_FPTOUI: {
619 if (TypeIdx != 0)
620 return UnableToLegalize;
621
622 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
623 MIRBuilder.buildInstr(MI.getOpcode())
624 .addDef(DstExt)
625 .addUse(MI.getOperand(1).getReg());
626
627 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
628 MI.eraseFromParent();
629 return Legalized;
630 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000631 case TargetOpcode::G_SITOFP:
632 case TargetOpcode::G_UITOFP: {
633 if (TypeIdx != 1)
634 return UnableToLegalize;
635
636 unsigned Src = MI.getOperand(1).getReg();
637 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
638
639 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
640 MIRBuilder.buildSExt(SrcExt, Src);
641 } else {
642 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
643 MIRBuilder.buildZExt(SrcExt, Src);
644 }
645
646 MIRBuilder.buildInstr(MI.getOpcode())
647 .addDef(MI.getOperand(0).getReg())
648 .addUse(SrcExt);
649
650 MI.eraseFromParent();
651 return Legalized;
652 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000653 case TargetOpcode::G_INSERT: {
654 if (TypeIdx != 0)
655 return UnableToLegalize;
656
657 unsigned Src = MI.getOperand(1).getReg();
658 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
659 MIRBuilder.buildAnyExt(SrcExt, Src);
660
661 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
662 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
663 MI.getOperand(3).getImm());
664 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
665 MIB.addReg(MI.getOperand(OpNum).getReg());
666 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
667 }
668
669 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
670 MI.eraseFromParent();
671 return Legalized;
672 }
Tim Northover3c73e362016-08-23 18:20:09 +0000673 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000674 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
675 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000676 "illegal to increase number of bytes loaded");
677
Tim Northover0f140c72016-09-09 11:46:34 +0000678 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
679 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
680 **MI.memoperands_begin());
681 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000682 MI.eraseFromParent();
683 return Legalized;
684 }
685 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000686 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
687 WideTy != LLT::scalar(8))
688 return UnableToLegalize;
689
690 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
691 auto Content = TLI.getBooleanContents(false, false);
692
693 unsigned ExtOp = TargetOpcode::G_ANYEXT;
694 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
695 ExtOp = TargetOpcode::G_ZEXT;
696 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
697 ExtOp = TargetOpcode::G_SEXT;
698 else
699 ExtOp = TargetOpcode::G_ANYEXT;
Tim Northover3c73e362016-08-23 18:20:09 +0000700
Tim Northover0f140c72016-09-09 11:46:34 +0000701 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover548feee2017-03-21 22:22:05 +0000702 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
703 MI.getOperand(0).getReg());
Tim Northover0f140c72016-09-09 11:46:34 +0000704 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
705 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000706 MI.eraseFromParent();
707 return Legalized;
708 }
Tim Northoverea904f92016-08-19 22:40:00 +0000709 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000710 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000711 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000712 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000713 MI.eraseFromParent();
714 return Legalized;
715 }
Tim Northovera11be042016-08-19 22:40:08 +0000716 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000717 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
718 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
719 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000720 MI.eraseFromParent();
721 return Legalized;
722 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000723 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000724 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
725 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
726 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000727 MI.eraseFromParent();
728 return Legalized;
729 }
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000730 case TargetOpcode::G_FCMP: {
731 unsigned Op0Ext, Op1Ext, DstReg;
732 unsigned Cmp1 = MI.getOperand(2).getReg();
733 unsigned Cmp2 = MI.getOperand(3).getReg();
734 if (TypeIdx == 0) {
735 Op0Ext = Cmp1;
736 Op1Ext = Cmp2;
737 DstReg = MRI.createGenericVirtualRegister(WideTy);
738 } else {
739 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
740 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
741 DstReg = MI.getOperand(0).getReg();
742 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1);
743 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2);
744 }
745 MIRBuilder.buildFCmp(
746 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
747 DstReg, Op0Ext, Op1Ext);
748 if (TypeIdx == 0)
749 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
750 DstReg);
751 MI.eraseFromParent();
752 return Legalized;
753 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000754 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000755 bool IsSigned = CmpInst::isSigned(
756 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000757 unsigned Cmp1 = MI.getOperand(2).getReg();
758 unsigned Cmp2 = MI.getOperand(3).getReg();
759 unsigned Op0Ext, Op1Ext, DstReg;
760 if (TypeIdx == 0) {
761 Op0Ext = Cmp1;
762 Op1Ext = Cmp2;
763 DstReg = MRI.createGenericVirtualRegister(WideTy);
Tim Northover6cd4b232016-08-23 21:01:26 +0000764 } else {
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000765 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
766 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
767 DstReg = MI.getOperand(0).getReg();
768 if (IsSigned) {
769 MIRBuilder.buildSExt(Op0Ext, Cmp1);
770 MIRBuilder.buildSExt(Op1Ext, Cmp2);
771 } else {
772 MIRBuilder.buildZExt(Op0Ext, Cmp1);
773 MIRBuilder.buildZExt(Op1Ext, Cmp2);
774 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000775 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000776 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000777 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000778 DstReg, Op0Ext, Op1Ext);
779 if (TypeIdx == 0)
780 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
781 DstReg);
Tim Northover051b8ad2016-08-26 17:46:17 +0000782 MI.eraseFromParent();
783 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000784 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000785 case TargetOpcode::G_GEP: {
786 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
787 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
788 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
789 MI.getOperand(2).setReg(OffsetExt);
790 return Legalized;
791 }
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000792 case TargetOpcode::G_PHI: {
793 assert(TypeIdx == 0 && "Expecting only Idx 0");
David Blaikie196f53b22017-08-25 16:46:07 +0000794 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) {
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000795 auto FirstTermIt = MBB.getFirstTerminator();
796 MIRBuilder.setInsertPt(MBB, FirstTermIt);
797 MachineInstr *DefMI = MRI.getVRegDef(Reg);
798 MachineInstrBuilder MIB;
799 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC)
800 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy,
801 DefMI->getOperand(1).getReg());
802 else
803 MIB = MIRBuilder.buildAnyExt(WideTy, Reg);
804 return MIB->getOperand(0).getReg();
805 };
806 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy);
807 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end();
808 OpIt != OpE;) {
809 unsigned Reg = OpIt++->getReg();
810 MachineBasicBlock *OpMBB = OpIt++->getMBB();
811 MIB.addReg(getExtendedReg(Reg, *OpMBB));
812 MIB.addMBB(OpMBB);
813 }
814 auto *MBB = MI.getParent();
815 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
816 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(),
817 MIB->getOperand(0).getReg());
818 MI.eraseFromParent();
819 return Legalized;
820 }
Tim Northover32335812016-08-04 18:35:11 +0000821 }
Tim Northover33b07d62016-07-22 20:03:43 +0000822}
823
Tim Northover69fa84a2016-10-14 22:18:18 +0000824LegalizerHelper::LegalizeResult
825LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000826 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000827 MIRBuilder.setInstr(MI);
828
829 switch(MI.getOpcode()) {
830 default:
831 return UnableToLegalize;
832 case TargetOpcode::G_SREM:
833 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000834 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
835 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000836 .addDef(QuotReg)
837 .addUse(MI.getOperand(1).getReg())
838 .addUse(MI.getOperand(2).getReg());
839
Tim Northover0f140c72016-09-09 11:46:34 +0000840 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
841 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
842 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
843 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000844 MI.eraseFromParent();
845 return Legalized;
846 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000847 case TargetOpcode::G_SMULO:
848 case TargetOpcode::G_UMULO: {
849 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
850 // result.
851 unsigned Res = MI.getOperand(0).getReg();
852 unsigned Overflow = MI.getOperand(1).getReg();
853 unsigned LHS = MI.getOperand(2).getReg();
854 unsigned RHS = MI.getOperand(3).getReg();
855
856 MIRBuilder.buildMul(Res, LHS, RHS);
857
858 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
859 ? TargetOpcode::G_SMULH
860 : TargetOpcode::G_UMULH;
861
862 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
863 MIRBuilder.buildInstr(Opcode)
864 .addDef(HiPart)
865 .addUse(LHS)
866 .addUse(RHS);
867
868 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
869 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +0000870
871 // For *signed* multiply, overflow is detected by checking:
872 // (hi != (lo >> bitwidth-1))
873 if (Opcode == TargetOpcode::G_SMULH) {
874 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
875 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
876 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
877 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
878 .addDef(Shifted)
879 .addUse(Res)
880 .addUse(ShiftAmt);
881 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
882 } else {
883 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
884 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000885 MI.eraseFromParent();
886 return Legalized;
887 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000888 case TargetOpcode::G_FNEG: {
889 // TODO: Handle vector types once we are able to
890 // represent them.
891 if (Ty.isVector())
892 return UnableToLegalize;
893 unsigned Res = MI.getOperand(0).getReg();
894 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +0000895 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +0000896 switch (Ty.getSizeInBits()) {
897 case 16:
898 ZeroTy = Type::getHalfTy(Ctx);
899 break;
900 case 32:
901 ZeroTy = Type::getFloatTy(Ctx);
902 break;
903 case 64:
904 ZeroTy = Type::getDoubleTy(Ctx);
905 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +0000906 case 128:
907 ZeroTy = Type::getFP128Ty(Ctx);
908 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +0000909 default:
910 llvm_unreachable("unexpected floating-point type");
911 }
912 ConstantFP &ZeroForNegation =
913 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
914 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
915 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
916 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
917 .addDef(Res)
918 .addUse(Zero)
919 .addUse(MI.getOperand(1).getReg());
920 MI.eraseFromParent();
921 return Legalized;
922 }
Volkan Keles225921a2017-03-10 21:25:09 +0000923 case TargetOpcode::G_FSUB: {
924 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
925 // First, check if G_FNEG is marked as Lower. If so, we may
926 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000927 if (LI.getAction({G_FNEG, {Ty}}).Action == LegalizerInfo::Lower)
Volkan Keles225921a2017-03-10 21:25:09 +0000928 return UnableToLegalize;
929 unsigned Res = MI.getOperand(0).getReg();
930 unsigned LHS = MI.getOperand(1).getReg();
931 unsigned RHS = MI.getOperand(2).getReg();
932 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
933 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
934 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
935 .addDef(Res)
936 .addUse(LHS)
937 .addUse(Neg);
938 MI.eraseFromParent();
939 return Legalized;
940 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +0000941 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
942 unsigned OldValRes = MI.getOperand(0).getReg();
943 unsigned SuccessRes = MI.getOperand(1).getReg();
944 unsigned Addr = MI.getOperand(2).getReg();
945 unsigned CmpVal = MI.getOperand(3).getReg();
946 unsigned NewVal = MI.getOperand(4).getReg();
947 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
948 **MI.memoperands_begin());
949 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
950 MI.eraseFromParent();
951 return Legalized;
952 }
Tim Northovercecee562016-08-26 17:46:13 +0000953 }
954}
955
Tim Northover69fa84a2016-10-14 22:18:18 +0000956LegalizerHelper::LegalizeResult
957LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
958 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000959 // FIXME: Don't know how to handle secondary types yet.
960 if (TypeIdx != 0)
961 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000962 switch (MI.getOpcode()) {
963 default:
964 return UnableToLegalize;
965 case TargetOpcode::G_ADD: {
966 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000967 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000968 unsigned Size = MRI.getType(DstReg).getSizeInBits();
969 int NumParts = Size / NarrowSize;
970 // FIXME: Don't know how to handle the situation where the small vectors
971 // aren't all the same size yet.
972 if (Size % NarrowSize != 0)
973 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000974
975 MIRBuilder.setInstr(MI);
976
Tim Northoverb18ea162016-09-20 15:20:36 +0000977 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000978 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
979 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
980
981 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000982 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
983 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000984 DstRegs.push_back(DstReg);
985 }
986
Tim Northoverbf017292017-03-03 22:46:09 +0000987 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000988 MI.eraseFromParent();
989 return Legalized;
990 }
991 }
992}