blob: a3b43c92a7fce6626467d280b782269648f22947 [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
Volkan Keles685fbda2017-03-10 18:34:57 +000039 auto Action = LI.getAction(MI, MRI);
Tim Northovera01bece2016-08-23 19:30:42 +000040 switch (std::get<0>(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");
Tim Northovera01bece2016-08-23 19:30:42 +000049 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000050 case LegalizerInfo::WidenScalar:
Daniel Sanders5377fb32017-04-20 15:46:12 +000051 DEBUG(dbgs() << ".. Widen scalar\n");
Tim Northovera01bece2016-08-23 19:30:42 +000052 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
Tim Northover69fa84a2016-10-14 22:18:18 +000053 case LegalizerInfo::Lower:
Daniel Sanders5377fb32017-04-20 15:46:12 +000054 DEBUG(dbgs() << ".. Lower\n");
Tim Northovercecee562016-08-26 17:46:13 +000055 return lower(MI, std::get<1>(Action), std::get<2>(Action));
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");
Tim Northovera01bece2016-08-23 19:30:42 +000058 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
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;
106 }
107 llvm_unreachable("Unknown libcall function");
108}
109
Diana Picusfc1675e2017-07-05 12:57:24 +0000110LegalizerHelper::LegalizeResult
111llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
112 const CallLowering::ArgInfo &Result,
113 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000114 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
115 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000116 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000117
Diana Picuse97822e2017-04-24 07:22:31 +0000118 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000119 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
120 MachineOperand::CreateES(Name), Result, Args))
121 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000122
Diana Picuse97822e2017-04-24 07:22:31 +0000123 return LegalizerHelper::Legalized;
124}
125
Diana Picus02e11012017-06-15 10:53:31 +0000126static LegalizerHelper::LegalizeResult
127simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
128 Type *OpType) {
129 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000130 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
131 {{MI.getOperand(1).getReg(), OpType},
132 {MI.getOperand(2).getReg(), OpType}});
Diana Picus02e11012017-06-15 10:53:31 +0000133}
134
Tim Northover69fa84a2016-10-14 22:18:18 +0000135LegalizerHelper::LegalizeResult
136LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000137 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
138 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000139 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000140
Diana Picusfc1675e2017-07-05 12:57:24 +0000141 MIRBuilder.setInstr(MI);
142
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000143 switch (MI.getOpcode()) {
144 default:
145 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000146 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000147 case TargetOpcode::G_UDIV:
148 case TargetOpcode::G_SREM:
149 case TargetOpcode::G_UREM: {
150 Type *HLTy = Type::getInt32Ty(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000151 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
152 if (Status != Legalized)
153 return Status;
154 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000155 }
Diana Picus1314a282017-04-11 10:52:34 +0000156 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000157 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000158 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000159 case TargetOpcode::G_FDIV:
Tim Northovere0418412017-02-08 23:23:39 +0000160 case TargetOpcode::G_FPOW:
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000161 case TargetOpcode::G_FREM: {
Diana Picus02e11012017-06-15 10:53:31 +0000162 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000163 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
164 if (Status != Legalized)
165 return Status;
166 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000167 }
168 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000169
170 MI.eraseFromParent();
171 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000172}
173
Tim Northover69fa84a2016-10-14 22:18:18 +0000174LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
175 unsigned TypeIdx,
176 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000177 // FIXME: Don't know how to handle secondary types yet.
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000178 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000179 return UnableToLegalize;
Justin Bognerfde01042017-01-18 17:29:54 +0000180
181 MIRBuilder.setInstr(MI);
182
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000183 int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
184 int64_t NarrowSize = NarrowTy.getSizeInBits();
185
Tim Northover9656f142016-08-04 20:54:13 +0000186 switch (MI.getOpcode()) {
187 default:
188 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000189 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000190 // FIXME: add support for when SizeOp0 isn't an exact multiple of
191 // NarrowSize.
192 if (SizeOp0 % NarrowSize != 0)
193 return UnableToLegalize;
194 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000195
196 SmallVector<unsigned, 2> DstRegs;
197 for (int i = 0; i < NumParts; ++i) {
198 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
199 MIRBuilder.buildUndef(Dst);
200 DstRegs.push_back(Dst);
201 }
202 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
203 MI.eraseFromParent();
204 return Legalized;
205 }
Tim Northover9656f142016-08-04 20:54:13 +0000206 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000207 // FIXME: add support for when SizeOp0 isn't an exact multiple of
208 // NarrowSize.
209 if (SizeOp0 % NarrowSize != 0)
210 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000211 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000212 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000213
Tim Northoverb18ea162016-09-20 15:20:36 +0000214 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000215 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
216 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
217
Tim Northover0f140c72016-09-09 11:46:34 +0000218 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
219 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000220
221 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000222 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
223 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000224
Tim Northover0f140c72016-09-09 11:46:34 +0000225 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000226 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000227
228 DstRegs.push_back(DstReg);
229 CarryIn = CarryOut;
230 }
Tim Northover0f140c72016-09-09 11:46:34 +0000231 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000232 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000233 MI.eraseFromParent();
234 return Legalized;
235 }
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000236 case TargetOpcode::G_EXTRACT: {
237 if (TypeIdx != 1)
238 return UnableToLegalize;
239
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000240 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
241 // FIXME: add support for when SizeOp1 isn't an exact multiple of
242 // NarrowSize.
243 if (SizeOp1 % NarrowSize != 0)
244 return UnableToLegalize;
245 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000246
247 SmallVector<unsigned, 2> SrcRegs, DstRegs;
248 SmallVector<uint64_t, 2> Indexes;
249 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
250
251 unsigned OpReg = MI.getOperand(0).getReg();
252 int64_t OpStart = MI.getOperand(2).getImm();
253 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
254 for (int i = 0; i < NumParts; ++i) {
255 unsigned SrcStart = i * NarrowSize;
256
257 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
258 // No part of the extract uses this subregister, ignore it.
259 continue;
260 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
261 // The entire subregister is extracted, forward the value.
262 DstRegs.push_back(SrcRegs[i]);
263 continue;
264 }
265
266 // OpSegStart is where this destination segment would start in OpReg if it
267 // extended infinitely in both directions.
268 int64_t ExtractOffset, SegSize;
269 if (OpStart < SrcStart) {
270 ExtractOffset = 0;
271 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
272 } else {
273 ExtractOffset = OpStart - SrcStart;
274 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
275 }
276
277 unsigned SegReg = SrcRegs[i];
278 if (ExtractOffset != 0 || SegSize != NarrowSize) {
279 // A genuine extract is needed.
280 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
281 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
282 }
283
284 DstRegs.push_back(SegReg);
285 }
286
287 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
288 MI.eraseFromParent();
289 return Legalized;
290 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000291 case TargetOpcode::G_INSERT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000292 // FIXME: add support for when SizeOp0 isn't an exact multiple of
293 // NarrowSize.
294 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000295 return UnableToLegalize;
296
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000297 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000298
299 SmallVector<unsigned, 2> SrcRegs, DstRegs;
300 SmallVector<uint64_t, 2> Indexes;
301 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
302
Tim Northover75e0b912017-03-06 18:23:04 +0000303 unsigned OpReg = MI.getOperand(2).getReg();
304 int64_t OpStart = MI.getOperand(3).getImm();
305 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000306 for (int i = 0; i < NumParts; ++i) {
307 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000308
Tim Northover75e0b912017-03-06 18:23:04 +0000309 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000310 // No part of the insert affects this subregister, forward the original.
311 DstRegs.push_back(SrcRegs[i]);
312 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000313 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000314 // The entire subregister is defined by this insert, forward the new
315 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000316 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000317 continue;
318 }
319
Tim Northover2eb18d32017-03-07 21:24:33 +0000320 // OpSegStart is where this destination segment would start in OpReg if it
321 // extended infinitely in both directions.
322 int64_t ExtractOffset, InsertOffset, SegSize;
323 if (OpStart < DstStart) {
324 InsertOffset = 0;
325 ExtractOffset = DstStart - OpStart;
326 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
327 } else {
328 InsertOffset = OpStart - DstStart;
329 ExtractOffset = 0;
330 SegSize =
331 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
332 }
333
334 unsigned SegReg = OpReg;
335 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000336 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000337 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
338 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000339 }
340
Tim Northover75e0b912017-03-06 18:23:04 +0000341 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000342 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000343 DstRegs.push_back(DstReg);
344 }
345
346 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Tim Northoverbf017292017-03-03 22:46:09 +0000347 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000348 MI.eraseFromParent();
349 return Legalized;
350 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000351 case TargetOpcode::G_LOAD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000352 // FIXME: add support for when SizeOp0 isn't an exact multiple of
353 // NarrowSize.
354 if (SizeOp0 % NarrowSize != 0)
355 return UnableToLegalize;
356 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000357 LLT OffsetTy = LLT::scalar(
358 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000359
360 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000361 for (int i = 0; i < NumParts; ++i) {
362 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000363 unsigned SrcReg = 0;
364 unsigned Adjustment = i * NarrowSize / 8;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000365
Daniel Sanders4e523662017-06-13 23:42:32 +0000366 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
367 Adjustment);
368
Justin Bognere094cc42017-01-20 00:30:17 +0000369 // TODO: This is conservatively correct, but we probably want to split the
370 // memory operands in the future.
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000371 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
372
373 DstRegs.push_back(DstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000374 }
375 unsigned DstReg = MI.getOperand(0).getReg();
Tim Northoverbf017292017-03-03 22:46:09 +0000376 MIRBuilder.buildMerge(DstReg, DstRegs);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000377 MI.eraseFromParent();
378 return Legalized;
379 }
Justin Bognerfde01042017-01-18 17:29:54 +0000380 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000381 // FIXME: add support for when SizeOp0 isn't an exact multiple of
382 // NarrowSize.
383 if (SizeOp0 % NarrowSize != 0)
384 return UnableToLegalize;
385 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000386 LLT OffsetTy = LLT::scalar(
387 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000388
389 SmallVector<unsigned, 2> SrcRegs;
390 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
391
392 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000393 unsigned DstReg = 0;
394 unsigned Adjustment = i * NarrowSize / 8;
395
396 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
397 Adjustment);
398
Justin Bognere094cc42017-01-20 00:30:17 +0000399 // TODO: This is conservatively correct, but we probably want to split the
400 // memory operands in the future.
Justin Bognerfde01042017-01-18 17:29:54 +0000401 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
402 }
403 MI.eraseFromParent();
404 return Legalized;
405 }
Igor Breger29537882017-04-07 14:41:59 +0000406 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000407 // FIXME: add support for when SizeOp0 isn't an exact multiple of
408 // NarrowSize.
409 if (SizeOp0 % NarrowSize != 0)
410 return UnableToLegalize;
411 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000412 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000413 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000414
415 SmallVector<unsigned, 2> DstRegs;
416 for (int i = 0; i < NumParts; ++i) {
417 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
418 ConstantInt *CI =
419 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
420 MIRBuilder.buildConstant(DstReg, *CI);
421 DstRegs.push_back(DstReg);
422 }
423 unsigned DstReg = MI.getOperand(0).getReg();
424 MIRBuilder.buildMerge(DstReg, DstRegs);
425 MI.eraseFromParent();
426 return Legalized;
427 }
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000428 case TargetOpcode::G_OR: {
429 // Legalize bitwise operation:
430 // A = BinOp<Ty> B, C
431 // into:
432 // B1, ..., BN = G_UNMERGE_VALUES B
433 // C1, ..., CN = G_UNMERGE_VALUES C
434 // A1 = BinOp<Ty/N> B1, C2
435 // ...
436 // AN = BinOp<Ty/N> BN, CN
437 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000438
439 // FIXME: add support for when SizeOp0 isn't an exact multiple of
440 // NarrowSize.
441 if (SizeOp0 % NarrowSize != 0)
442 return UnableToLegalize;
443 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000444
445 // List the registers where the destination will be scattered.
446 SmallVector<unsigned, 2> DstRegs;
447 // List the registers where the first argument will be split.
448 SmallVector<unsigned, 2> SrcsReg1;
449 // List the registers where the second argument will be split.
450 SmallVector<unsigned, 2> SrcsReg2;
451 // Create all the temporary registers.
452 for (int i = 0; i < NumParts; ++i) {
453 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
454 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
455 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
456
457 DstRegs.push_back(DstReg);
458 SrcsReg1.push_back(SrcReg1);
459 SrcsReg2.push_back(SrcReg2);
460 }
461 // Explode the big arguments into smaller chunks.
462 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
463 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
464
465 // Do the operation on each small part.
466 for (int i = 0; i < NumParts; ++i)
467 MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
468
469 // Gather the destination registers into the final destination.
470 unsigned DstReg = MI.getOperand(0).getReg();
471 MIRBuilder.buildMerge(DstReg, DstRegs);
472 MI.eraseFromParent();
473 return Legalized;
474 }
Tim Northover9656f142016-08-04 20:54:13 +0000475 }
Tim Northover33b07d62016-07-22 20:03:43 +0000476}
477
Tim Northover69fa84a2016-10-14 22:18:18 +0000478LegalizerHelper::LegalizeResult
479LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000480 MIRBuilder.setInstr(MI);
481
Tim Northover32335812016-08-04 18:35:11 +0000482 switch (MI.getOpcode()) {
483 default:
484 return UnableToLegalize;
Tim Northover61c16142016-08-04 21:39:49 +0000485 case TargetOpcode::G_ADD:
486 case TargetOpcode::G_AND:
487 case TargetOpcode::G_MUL:
488 case TargetOpcode::G_OR:
489 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000490 case TargetOpcode::G_SUB:
491 case TargetOpcode::G_SHL: {
Tim Northover32335812016-08-04 18:35:11 +0000492 // Perform operation at larger width (any extension is fine here, high bits
493 // don't affect the result) and then truncate the result back to the
494 // original type.
Tim Northover0f140c72016-09-09 11:46:34 +0000495 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
496 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
497 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
498 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
Tim Northover32335812016-08-04 18:35:11 +0000499
Tim Northover0f140c72016-09-09 11:46:34 +0000500 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
501 MIRBuilder.buildInstr(MI.getOpcode())
502 .addDef(DstExt)
503 .addUse(Src1Ext)
504 .addUse(Src2Ext);
Tim Northover32335812016-08-04 18:35:11 +0000505
Tim Northover0f140c72016-09-09 11:46:34 +0000506 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover32335812016-08-04 18:35:11 +0000507 MI.eraseFromParent();
508 return Legalized;
509 }
Tim Northover7a753d92016-08-26 17:46:06 +0000510 case TargetOpcode::G_SDIV:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000511 case TargetOpcode::G_UDIV:
Diana Picusdf4100b2017-07-18 09:08:47 +0000512 case TargetOpcode::G_SREM:
513 case TargetOpcode::G_UREM:
Justin Bognerddb80ae2017-01-19 07:51:17 +0000514 case TargetOpcode::G_ASHR:
515 case TargetOpcode::G_LSHR: {
516 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
Diana Picusdf4100b2017-07-18 09:08:47 +0000517 MI.getOpcode() == TargetOpcode::G_SREM ||
Justin Bognerddb80ae2017-01-19 07:51:17 +0000518 MI.getOpcode() == TargetOpcode::G_ASHR
519 ? TargetOpcode::G_SEXT
520 : TargetOpcode::G_ZEXT;
Tim Northover7a753d92016-08-26 17:46:06 +0000521
Tim Northover0f140c72016-09-09 11:46:34 +0000522 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
523 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
524 MI.getOperand(1).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000525
Tim Northover0f140c72016-09-09 11:46:34 +0000526 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
527 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
528 MI.getOperand(2).getReg());
Tim Northover7a753d92016-08-26 17:46:06 +0000529
Tim Northover0f140c72016-09-09 11:46:34 +0000530 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
531 MIRBuilder.buildInstr(MI.getOpcode())
Tim Northover7a753d92016-08-26 17:46:06 +0000532 .addDef(ResExt)
533 .addUse(LHSExt)
534 .addUse(RHSExt);
535
Tim Northover0f140c72016-09-09 11:46:34 +0000536 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
Tim Northover7a753d92016-08-26 17:46:06 +0000537 MI.eraseFromParent();
538 return Legalized;
539 }
Tim Northover868332d2017-02-06 23:41:27 +0000540 case TargetOpcode::G_SELECT: {
541 if (TypeIdx != 0)
542 return UnableToLegalize;
543
544 // Perform operation at larger width (any extension is fine here, high bits
545 // don't affect the result) and then truncate the result back to the
546 // original type.
547 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
548 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
549 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
550 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
551
552 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
553 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
554 .addDef(DstExt)
555 .addReg(MI.getOperand(1).getReg())
556 .addUse(Src1Ext)
557 .addUse(Src2Ext);
558
559 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
560 MI.eraseFromParent();
561 return Legalized;
562 }
Ahmed Bougachab6137062017-01-23 21:10:14 +0000563 case TargetOpcode::G_FPTOSI:
564 case TargetOpcode::G_FPTOUI: {
565 if (TypeIdx != 0)
566 return UnableToLegalize;
567
568 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
569 MIRBuilder.buildInstr(MI.getOpcode())
570 .addDef(DstExt)
571 .addUse(MI.getOperand(1).getReg());
572
573 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
574 MI.eraseFromParent();
575 return Legalized;
576 }
Ahmed Bougachad2948232017-01-20 01:37:24 +0000577 case TargetOpcode::G_SITOFP:
578 case TargetOpcode::G_UITOFP: {
579 if (TypeIdx != 1)
580 return UnableToLegalize;
581
582 unsigned Src = MI.getOperand(1).getReg();
583 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
584
585 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
586 MIRBuilder.buildSExt(SrcExt, Src);
587 } else {
588 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
589 MIRBuilder.buildZExt(SrcExt, Src);
590 }
591
592 MIRBuilder.buildInstr(MI.getOpcode())
593 .addDef(MI.getOperand(0).getReg())
594 .addUse(SrcExt);
595
596 MI.eraseFromParent();
597 return Legalized;
598 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000599 case TargetOpcode::G_INSERT: {
600 if (TypeIdx != 0)
601 return UnableToLegalize;
602
603 unsigned Src = MI.getOperand(1).getReg();
604 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
605 MIRBuilder.buildAnyExt(SrcExt, Src);
606
607 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
608 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
609 MI.getOperand(3).getImm());
610 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
611 MIB.addReg(MI.getOperand(OpNum).getReg());
612 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
613 }
614
615 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
616 MI.eraseFromParent();
617 return Legalized;
618 }
Tim Northover3c73e362016-08-23 18:20:09 +0000619 case TargetOpcode::G_LOAD: {
Rui Ueyamaa5edf652016-09-09 18:37:08 +0000620 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
621 WideTy.getSizeInBits() &&
Tim Northover3c73e362016-08-23 18:20:09 +0000622 "illegal to increase number of bytes loaded");
623
Tim Northover0f140c72016-09-09 11:46:34 +0000624 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
625 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
626 **MI.memoperands_begin());
627 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northover3c73e362016-08-23 18:20:09 +0000628 MI.eraseFromParent();
629 return Legalized;
630 }
631 case TargetOpcode::G_STORE: {
Tim Northover548feee2017-03-21 22:22:05 +0000632 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
633 WideTy != LLT::scalar(8))
634 return UnableToLegalize;
635
636 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
637 auto Content = TLI.getBooleanContents(false, false);
638
639 unsigned ExtOp = TargetOpcode::G_ANYEXT;
640 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
641 ExtOp = TargetOpcode::G_ZEXT;
642 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
643 ExtOp = TargetOpcode::G_SEXT;
644 else
645 ExtOp = TargetOpcode::G_ANYEXT;
Tim Northover3c73e362016-08-23 18:20:09 +0000646
Tim Northover0f140c72016-09-09 11:46:34 +0000647 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover548feee2017-03-21 22:22:05 +0000648 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
649 MI.getOperand(0).getReg());
Tim Northover0f140c72016-09-09 11:46:34 +0000650 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
651 **MI.memoperands_begin());
Tim Northover3c73e362016-08-23 18:20:09 +0000652 MI.eraseFromParent();
653 return Legalized;
654 }
Tim Northoverea904f92016-08-19 22:40:00 +0000655 case TargetOpcode::G_CONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000656 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
Tim Northover9267ac52016-12-05 21:47:07 +0000657 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
Tim Northover0f140c72016-09-09 11:46:34 +0000658 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northoverea904f92016-08-19 22:40:00 +0000659 MI.eraseFromParent();
660 return Legalized;
661 }
Tim Northovera11be042016-08-19 22:40:08 +0000662 case TargetOpcode::G_FCONSTANT: {
Tim Northover0f140c72016-09-09 11:46:34 +0000663 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
664 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
665 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
Tim Northovera11be042016-08-19 22:40:08 +0000666 MI.eraseFromParent();
667 return Legalized;
668 }
Tim Northoverb3a0be42016-08-23 21:01:20 +0000669 case TargetOpcode::G_BRCOND: {
Tim Northover0f140c72016-09-09 11:46:34 +0000670 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
671 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
672 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
Tim Northoverb3a0be42016-08-23 21:01:20 +0000673 MI.eraseFromParent();
674 return Legalized;
675 }
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000676 case TargetOpcode::G_FCMP: {
677 unsigned Op0Ext, Op1Ext, DstReg;
678 unsigned Cmp1 = MI.getOperand(2).getReg();
679 unsigned Cmp2 = MI.getOperand(3).getReg();
680 if (TypeIdx == 0) {
681 Op0Ext = Cmp1;
682 Op1Ext = Cmp2;
683 DstReg = MRI.createGenericVirtualRegister(WideTy);
684 } else {
685 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
686 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
687 DstReg = MI.getOperand(0).getReg();
688 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1);
689 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2);
690 }
691 MIRBuilder.buildFCmp(
692 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
693 DstReg, Op0Ext, Op1Ext);
694 if (TypeIdx == 0)
695 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
696 DstReg);
697 MI.eraseFromParent();
698 return Legalized;
699 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000700 case TargetOpcode::G_ICMP: {
Tim Northover051b8ad2016-08-26 17:46:17 +0000701 bool IsSigned = CmpInst::isSigned(
702 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000703 unsigned Cmp1 = MI.getOperand(2).getReg();
704 unsigned Cmp2 = MI.getOperand(3).getReg();
705 unsigned Op0Ext, Op1Ext, DstReg;
706 if (TypeIdx == 0) {
707 Op0Ext = Cmp1;
708 Op1Ext = Cmp2;
709 DstReg = MRI.createGenericVirtualRegister(WideTy);
Tim Northover6cd4b232016-08-23 21:01:26 +0000710 } else {
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000711 Op0Ext = MRI.createGenericVirtualRegister(WideTy);
712 Op1Ext = MRI.createGenericVirtualRegister(WideTy);
713 DstReg = MI.getOperand(0).getReg();
714 if (IsSigned) {
715 MIRBuilder.buildSExt(Op0Ext, Cmp1);
716 MIRBuilder.buildSExt(Op1Ext, Cmp2);
717 } else {
718 MIRBuilder.buildZExt(Op0Ext, Cmp1);
719 MIRBuilder.buildZExt(Op1Ext, Cmp2);
720 }
Tim Northover6cd4b232016-08-23 21:01:26 +0000721 }
Tim Northover051b8ad2016-08-26 17:46:17 +0000722 MIRBuilder.buildICmp(
Tim Northover051b8ad2016-08-26 17:46:17 +0000723 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
Aditya Nandakumar02c602e2017-07-31 17:00:16 +0000724 DstReg, Op0Ext, Op1Ext);
725 if (TypeIdx == 0)
726 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
727 DstReg);
Tim Northover051b8ad2016-08-26 17:46:17 +0000728 MI.eraseFromParent();
729 return Legalized;
Tim Northover6cd4b232016-08-23 21:01:26 +0000730 }
Tim Northover22d82cf2016-09-15 11:02:19 +0000731 case TargetOpcode::G_GEP: {
732 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
733 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
734 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
735 MI.getOperand(2).setReg(OffsetExt);
736 return Legalized;
737 }
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000738 case TargetOpcode::G_PHI: {
739 assert(TypeIdx == 0 && "Expecting only Idx 0");
David Blaikie196f53b22017-08-25 16:46:07 +0000740 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) {
Aditya Nandakumar892979e2017-08-25 04:57:27 +0000741 auto FirstTermIt = MBB.getFirstTerminator();
742 MIRBuilder.setInsertPt(MBB, FirstTermIt);
743 MachineInstr *DefMI = MRI.getVRegDef(Reg);
744 MachineInstrBuilder MIB;
745 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC)
746 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy,
747 DefMI->getOperand(1).getReg());
748 else
749 MIB = MIRBuilder.buildAnyExt(WideTy, Reg);
750 return MIB->getOperand(0).getReg();
751 };
752 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy);
753 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end();
754 OpIt != OpE;) {
755 unsigned Reg = OpIt++->getReg();
756 MachineBasicBlock *OpMBB = OpIt++->getMBB();
757 MIB.addReg(getExtendedReg(Reg, *OpMBB));
758 MIB.addMBB(OpMBB);
759 }
760 auto *MBB = MI.getParent();
761 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
762 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(),
763 MIB->getOperand(0).getReg());
764 MI.eraseFromParent();
765 return Legalized;
766 }
Tim Northover32335812016-08-04 18:35:11 +0000767 }
Tim Northover33b07d62016-07-22 20:03:43 +0000768}
769
Tim Northover69fa84a2016-10-14 22:18:18 +0000770LegalizerHelper::LegalizeResult
771LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +0000772 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +0000773 MIRBuilder.setInstr(MI);
774
775 switch(MI.getOpcode()) {
776 default:
777 return UnableToLegalize;
778 case TargetOpcode::G_SREM:
779 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +0000780 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
781 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +0000782 .addDef(QuotReg)
783 .addUse(MI.getOperand(1).getReg())
784 .addUse(MI.getOperand(2).getReg());
785
Tim Northover0f140c72016-09-09 11:46:34 +0000786 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
787 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
788 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
789 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +0000790 MI.eraseFromParent();
791 return Legalized;
792 }
Tim Northover0a9b2792017-02-08 21:22:15 +0000793 case TargetOpcode::G_SMULO:
794 case TargetOpcode::G_UMULO: {
795 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
796 // result.
797 unsigned Res = MI.getOperand(0).getReg();
798 unsigned Overflow = MI.getOperand(1).getReg();
799 unsigned LHS = MI.getOperand(2).getReg();
800 unsigned RHS = MI.getOperand(3).getReg();
801
802 MIRBuilder.buildMul(Res, LHS, RHS);
803
804 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
805 ? TargetOpcode::G_SMULH
806 : TargetOpcode::G_UMULH;
807
808 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
809 MIRBuilder.buildInstr(Opcode)
810 .addDef(HiPart)
811 .addUse(LHS)
812 .addUse(RHS);
813
814 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
815 MIRBuilder.buildConstant(Zero, 0);
816 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
817 MI.eraseFromParent();
818 return Legalized;
819 }
Volkan Keles5698b2a2017-03-08 18:09:14 +0000820 case TargetOpcode::G_FNEG: {
821 // TODO: Handle vector types once we are able to
822 // represent them.
823 if (Ty.isVector())
824 return UnableToLegalize;
825 unsigned Res = MI.getOperand(0).getReg();
826 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +0000827 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +0000828 switch (Ty.getSizeInBits()) {
829 case 16:
830 ZeroTy = Type::getHalfTy(Ctx);
831 break;
832 case 32:
833 ZeroTy = Type::getFloatTy(Ctx);
834 break;
835 case 64:
836 ZeroTy = Type::getDoubleTy(Ctx);
837 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +0000838 case 128:
839 ZeroTy = Type::getFP128Ty(Ctx);
840 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +0000841 default:
842 llvm_unreachable("unexpected floating-point type");
843 }
844 ConstantFP &ZeroForNegation =
845 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
846 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
847 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
848 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
849 .addDef(Res)
850 .addUse(Zero)
851 .addUse(MI.getOperand(1).getReg());
852 MI.eraseFromParent();
853 return Legalized;
854 }
Volkan Keles225921a2017-03-10 21:25:09 +0000855 case TargetOpcode::G_FSUB: {
856 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
857 // First, check if G_FNEG is marked as Lower. If so, we may
858 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
859 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
860 return UnableToLegalize;
861 unsigned Res = MI.getOperand(0).getReg();
862 unsigned LHS = MI.getOperand(1).getReg();
863 unsigned RHS = MI.getOperand(2).getReg();
864 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
865 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
866 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
867 .addDef(Res)
868 .addUse(LHS)
869 .addUse(Neg);
870 MI.eraseFromParent();
871 return Legalized;
872 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +0000873 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
874 unsigned OldValRes = MI.getOperand(0).getReg();
875 unsigned SuccessRes = MI.getOperand(1).getReg();
876 unsigned Addr = MI.getOperand(2).getReg();
877 unsigned CmpVal = MI.getOperand(3).getReg();
878 unsigned NewVal = MI.getOperand(4).getReg();
879 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
880 **MI.memoperands_begin());
881 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
882 MI.eraseFromParent();
883 return Legalized;
884 }
Tim Northovercecee562016-08-26 17:46:13 +0000885 }
886}
887
Tim Northover69fa84a2016-10-14 22:18:18 +0000888LegalizerHelper::LegalizeResult
889LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
890 LLT NarrowTy) {
Quentin Colombet5e60bcd2016-08-27 02:38:21 +0000891 // FIXME: Don't know how to handle secondary types yet.
892 if (TypeIdx != 0)
893 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000894 switch (MI.getOpcode()) {
895 default:
896 return UnableToLegalize;
897 case TargetOpcode::G_ADD: {
898 unsigned NarrowSize = NarrowTy.getSizeInBits();
Tim Northover0f140c72016-09-09 11:46:34 +0000899 unsigned DstReg = MI.getOperand(0).getReg();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000900 unsigned Size = MRI.getType(DstReg).getSizeInBits();
901 int NumParts = Size / NarrowSize;
902 // FIXME: Don't know how to handle the situation where the small vectors
903 // aren't all the same size yet.
904 if (Size % NarrowSize != 0)
905 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000906
907 MIRBuilder.setInstr(MI);
908
Tim Northoverb18ea162016-09-20 15:20:36 +0000909 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover33b07d62016-07-22 20:03:43 +0000910 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
911 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
912
913 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000914 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
915 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
Tim Northover33b07d62016-07-22 20:03:43 +0000916 DstRegs.push_back(DstReg);
917 }
918
Tim Northoverbf017292017-03-03 22:46:09 +0000919 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover33b07d62016-07-22 20:03:43 +0000920 MI.eraseFromParent();
921 return Legalized;
922 }
923 }
924}