blob: bd0ad3f8083f95cd0f894a5ebb1731bf1e9f04e8 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tim Northover33b07d62016-07-22 20:03:43 +00006//
7//===----------------------------------------------------------------------===//
8//
Tim Northover69fa84a2016-10-14 22:18:18 +00009/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000010/// individual instructions and the LegalizeMachineIR wrapper pass for the
11/// primary legalization.
12//
13//===----------------------------------------------------------------------===//
14
Tim Northover69fa84a2016-10-14 22:18:18 +000015#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000016#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000017#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000018#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000020#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000021#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000023#include "llvm/Support/Debug.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000024#include "llvm/Support/MathExtras.h"
Tim Northover33b07d62016-07-22 20:03:43 +000025#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000026
Daniel Sanders5377fb32017-04-20 15:46:12 +000027#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000028
29using namespace llvm;
Daniel Sanders9ade5592018-01-29 17:37:29 +000030using namespace LegalizeActions;
Tim Northover33b07d62016-07-22 20:03:43 +000031
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000032LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000033 GISelChangeObserver &Observer,
34 MachineIRBuilder &Builder)
35 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
36 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000037 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000038 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000039}
40
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000041LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000042 GISelChangeObserver &Observer,
43 MachineIRBuilder &B)
44 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000045 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000046 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000047}
Tim Northover69fa84a2016-10-14 22:18:18 +000048LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000049LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000050 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000051
Daniel Sanders262ed0e2018-01-24 17:17:46 +000052 auto Step = LI.getAction(MI, MRI);
53 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000054 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000055 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000056 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000057 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000058 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000059 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000060 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000061 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000062 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000063 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000064 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000065 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000066 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000067 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000068 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000069 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000070 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000071 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +000072 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000073 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000074 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
75 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +000076 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000077 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +000078 return UnableToLegalize;
79 }
80}
81
Tim Northover69fa84a2016-10-14 22:18:18 +000082void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
83 SmallVectorImpl<unsigned> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +000084 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +000085 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +000086 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +000087}
88
Matt Arsenaultc7bce732019-01-31 02:46:05 +000089bool LegalizerHelper::extractParts(unsigned Reg, LLT RegTy,
90 LLT MainTy, LLT &LeftoverTy,
91 SmallVectorImpl<unsigned> &VRegs,
92 SmallVectorImpl<unsigned> &LeftoverRegs) {
93 assert(!LeftoverTy.isValid() && "this is an out argument");
94
95 unsigned RegSize = RegTy.getSizeInBits();
96 unsigned MainSize = MainTy.getSizeInBits();
97 unsigned NumParts = RegSize / MainSize;
98 unsigned LeftoverSize = RegSize - NumParts * MainSize;
99
100 // Use an unmerge when possible.
101 if (LeftoverSize == 0) {
102 for (unsigned I = 0; I < NumParts; ++I)
103 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy));
104 MIRBuilder.buildUnmerge(VRegs, Reg);
105 return true;
106 }
107
108 if (MainTy.isVector()) {
109 unsigned EltSize = MainTy.getScalarSizeInBits();
110 if (LeftoverSize % EltSize != 0)
111 return false;
112 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
113 } else {
114 LeftoverTy = LLT::scalar(LeftoverSize);
115 }
116
117 // For irregular sizes, extract the individual parts.
118 for (unsigned I = 0; I != NumParts; ++I) {
119 unsigned NewReg = MRI.createGenericVirtualRegister(MainTy);
120 VRegs.push_back(NewReg);
121 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I);
122 }
123
124 for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
125 Offset += LeftoverSize) {
126 unsigned NewReg = MRI.createGenericVirtualRegister(LeftoverTy);
127 LeftoverRegs.push_back(NewReg);
128 MIRBuilder.buildExtract(NewReg, Reg, Offset);
129 }
130
131 return true;
132}
133
134void LegalizerHelper::insertParts(unsigned DstReg,
135 LLT ResultTy, LLT PartTy,
136 ArrayRef<unsigned> PartRegs,
137 LLT LeftoverTy,
138 ArrayRef<unsigned> LeftoverRegs) {
139 if (!LeftoverTy.isValid()) {
140 assert(LeftoverRegs.empty());
141
142 if (PartTy.isVector())
143 MIRBuilder.buildConcatVectors(DstReg, PartRegs);
144 else
145 MIRBuilder.buildBuildVector(DstReg, PartRegs);
146 return;
147 }
148
149 unsigned PartSize = PartTy.getSizeInBits();
150 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits();
151
152 unsigned CurResultReg = MRI.createGenericVirtualRegister(ResultTy);
153 MIRBuilder.buildUndef(CurResultReg);
154
155 unsigned Offset = 0;
156 for (unsigned PartReg : PartRegs) {
157 unsigned NewResultReg = MRI.createGenericVirtualRegister(ResultTy);
158 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset);
159 CurResultReg = NewResultReg;
160 Offset += PartSize;
161 }
162
163 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) {
164 // Use the original output register for the final insert to avoid a copy.
165 unsigned NewResultReg = (I + 1 == E) ?
166 DstReg : MRI.createGenericVirtualRegister(ResultTy);
167
168 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset);
169 CurResultReg = NewResultReg;
170 Offset += LeftoverPartSize;
171 }
172}
173
Tim Northovere0418412017-02-08 23:23:39 +0000174static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
175 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +0000176 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000177 assert((Size == 32 || Size == 64) && "Unsupported size");
178 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +0000179 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000180 assert((Size == 32 || Size == 64) && "Unsupported size");
181 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000182 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000183 assert((Size == 32 || Size == 64) && "Unsupported size");
184 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000185 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000186 assert((Size == 32 || Size == 64) && "Unsupported size");
187 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000188 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
189 assert(Size == 32 && "Unsupported size");
190 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000191 case TargetOpcode::G_FADD:
192 assert((Size == 32 || Size == 64) && "Unsupported size");
193 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000194 case TargetOpcode::G_FSUB:
195 assert((Size == 32 || Size == 64) && "Unsupported size");
196 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000197 case TargetOpcode::G_FMUL:
198 assert((Size == 32 || Size == 64) && "Unsupported size");
199 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000200 case TargetOpcode::G_FDIV:
201 assert((Size == 32 || Size == 64) && "Unsupported size");
202 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Jessica Paquette84bedac2019-01-30 23:46:15 +0000203 case TargetOpcode::G_FEXP:
204 assert((Size == 32 || Size == 64) && "Unsupported size");
205 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000206 case TargetOpcode::G_FREM:
207 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
208 case TargetOpcode::G_FPOW:
209 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000210 case TargetOpcode::G_FMA:
211 assert((Size == 32 || Size == 64) && "Unsupported size");
212 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Jessica Paquette7db82d72019-01-28 18:34:18 +0000213 case TargetOpcode::G_FSIN:
214 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
215 return Size == 128 ? RTLIB::SIN_F128
216 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32;
217 case TargetOpcode::G_FCOS:
218 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
219 return Size == 128 ? RTLIB::COS_F128
220 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32;
Jessica Paquettec49428a2019-01-28 19:53:14 +0000221 case TargetOpcode::G_FLOG10:
222 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
223 return Size == 128 ? RTLIB::LOG10_F128
224 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32;
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000225 case TargetOpcode::G_FLOG:
226 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
227 return Size == 128 ? RTLIB::LOG_F128
228 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32;
Jessica Paquette0154bd12019-01-30 21:16:04 +0000229 case TargetOpcode::G_FLOG2:
230 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
231 return Size == 128 ? RTLIB::LOG2_F128
232 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000233 }
234 llvm_unreachable("Unknown libcall function");
235}
236
Diana Picusfc1675e2017-07-05 12:57:24 +0000237LegalizerHelper::LegalizeResult
238llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
239 const CallLowering::ArgInfo &Result,
240 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000241 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
242 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000243 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000244
Diana Picuse97822e2017-04-24 07:22:31 +0000245 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000246 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
247 MachineOperand::CreateES(Name), Result, Args))
248 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000249
Diana Picuse97822e2017-04-24 07:22:31 +0000250 return LegalizerHelper::Legalized;
251}
252
Diana Picus65ed3642018-01-17 13:34:10 +0000253// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000254static LegalizerHelper::LegalizeResult
255simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
256 Type *OpType) {
257 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000258
259 SmallVector<CallLowering::ArgInfo, 3> Args;
260 for (unsigned i = 1; i < MI.getNumOperands(); i++)
261 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000262 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000263 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000264}
265
Diana Picus65ed3642018-01-17 13:34:10 +0000266static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
267 Type *FromType) {
268 auto ToMVT = MVT::getVT(ToType);
269 auto FromMVT = MVT::getVT(FromType);
270
271 switch (Opcode) {
272 case TargetOpcode::G_FPEXT:
273 return RTLIB::getFPEXT(FromMVT, ToMVT);
274 case TargetOpcode::G_FPTRUNC:
275 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000276 case TargetOpcode::G_FPTOSI:
277 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
278 case TargetOpcode::G_FPTOUI:
279 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000280 case TargetOpcode::G_SITOFP:
281 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
282 case TargetOpcode::G_UITOFP:
283 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000284 }
285 llvm_unreachable("Unsupported libcall function");
286}
287
288static LegalizerHelper::LegalizeResult
289conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
290 Type *FromType) {
291 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
292 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
293 {{MI.getOperand(1).getReg(), FromType}});
294}
295
Tim Northover69fa84a2016-10-14 22:18:18 +0000296LegalizerHelper::LegalizeResult
297LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000298 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
299 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000300 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000301
Diana Picusfc1675e2017-07-05 12:57:24 +0000302 MIRBuilder.setInstr(MI);
303
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000304 switch (MI.getOpcode()) {
305 default:
306 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000307 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000308 case TargetOpcode::G_UDIV:
309 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000310 case TargetOpcode::G_UREM:
311 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000312 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000313 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
314 if (Status != Legalized)
315 return Status;
316 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000317 }
Diana Picus1314a282017-04-11 10:52:34 +0000318 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000319 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000320 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000321 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000322 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000323 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000324 case TargetOpcode::G_FREM:
325 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000326 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000327 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000328 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000329 case TargetOpcode::G_FLOG2:
330 case TargetOpcode::G_FEXP: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000331 if (Size > 64) {
332 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
333 return UnableToLegalize;
334 }
Diana Picus02e11012017-06-15 10:53:31 +0000335 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000336 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
337 if (Status != Legalized)
338 return Status;
339 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000340 }
Diana Picus65ed3642018-01-17 13:34:10 +0000341 case TargetOpcode::G_FPEXT: {
342 // FIXME: Support other floating point types (half, fp128 etc)
343 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
344 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
345 if (ToSize != 64 || FromSize != 32)
346 return UnableToLegalize;
347 LegalizeResult Status = conversionLibcall(
348 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
349 if (Status != Legalized)
350 return Status;
351 break;
352 }
353 case TargetOpcode::G_FPTRUNC: {
354 // FIXME: Support other floating point types (half, fp128 etc)
355 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
356 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
357 if (ToSize != 32 || FromSize != 64)
358 return UnableToLegalize;
359 LegalizeResult Status = conversionLibcall(
360 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
361 if (Status != Legalized)
362 return Status;
363 break;
364 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000365 case TargetOpcode::G_FPTOSI:
366 case TargetOpcode::G_FPTOUI: {
367 // FIXME: Support other types
368 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
369 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
370 if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
371 return UnableToLegalize;
372 LegalizeResult Status = conversionLibcall(
373 MI, MIRBuilder, Type::getInt32Ty(Ctx),
374 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
375 if (Status != Legalized)
376 return Status;
377 break;
378 }
Diana Picus517531e2018-01-30 09:15:17 +0000379 case TargetOpcode::G_SITOFP:
380 case TargetOpcode::G_UITOFP: {
381 // FIXME: Support other types
382 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
383 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
384 if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
385 return UnableToLegalize;
386 LegalizeResult Status = conversionLibcall(
387 MI, MIRBuilder,
388 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
389 Type::getInt32Ty(Ctx));
390 if (Status != Legalized)
391 return Status;
392 break;
393 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000394 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000395
396 MI.eraseFromParent();
397 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000398}
399
Tim Northover69fa84a2016-10-14 22:18:18 +0000400LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
401 unsigned TypeIdx,
402 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000403 MIRBuilder.setInstr(MI);
404
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000405 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
406 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000407
Tim Northover9656f142016-08-04 20:54:13 +0000408 switch (MI.getOpcode()) {
409 default:
410 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000411 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000412 // FIXME: add support for when SizeOp0 isn't an exact multiple of
413 // NarrowSize.
414 if (SizeOp0 % NarrowSize != 0)
415 return UnableToLegalize;
416 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000417
418 SmallVector<unsigned, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000419 for (int i = 0; i < NumParts; ++i)
420 DstRegs.push_back(
421 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000422
423 unsigned DstReg = MI.getOperand(0).getReg();
424 if(MRI.getType(DstReg).isVector())
425 MIRBuilder.buildBuildVector(DstReg, DstRegs);
426 else
427 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000428 MI.eraseFromParent();
429 return Legalized;
430 }
Tim Northover9656f142016-08-04 20:54:13 +0000431 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000432 // FIXME: add support for when SizeOp0 isn't an exact multiple of
433 // NarrowSize.
434 if (SizeOp0 % NarrowSize != 0)
435 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000436 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000437 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000438
Tim Northoverb18ea162016-09-20 15:20:36 +0000439 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000440 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
441 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
442
Tim Northover0f140c72016-09-09 11:46:34 +0000443 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
444 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000445
446 for (int i = 0; i < NumParts; ++i) {
Tim Northover0f140c72016-09-09 11:46:34 +0000447 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
448 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000449
Tim Northover0f140c72016-09-09 11:46:34 +0000450 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000451 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000452
453 DstRegs.push_back(DstReg);
454 CarryIn = CarryOut;
455 }
Tim Northover0f140c72016-09-09 11:46:34 +0000456 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000457 if(MRI.getType(DstReg).isVector())
458 MIRBuilder.buildBuildVector(DstReg, DstRegs);
459 else
460 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000461 MI.eraseFromParent();
462 return Legalized;
463 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000464 case TargetOpcode::G_SUB: {
465 // FIXME: add support for when SizeOp0 isn't an exact multiple of
466 // NarrowSize.
467 if (SizeOp0 % NarrowSize != 0)
468 return UnableToLegalize;
469
470 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
471
472 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
473 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
474 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
475
476 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
477 unsigned BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
478 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
479 {Src1Regs[0], Src2Regs[0]});
480 DstRegs.push_back(DstReg);
481 unsigned BorrowIn = BorrowOut;
482 for (int i = 1; i < NumParts; ++i) {
483 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
484 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
485
486 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
487 {Src1Regs[i], Src2Regs[i], BorrowIn});
488
489 DstRegs.push_back(DstReg);
490 BorrowIn = BorrowOut;
491 }
492 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
493 MI.eraseFromParent();
494 return Legalized;
495 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000496 case TargetOpcode::G_MUL:
497 return narrowScalarMul(MI, TypeIdx, NarrowTy);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000498 case TargetOpcode::G_EXTRACT: {
499 if (TypeIdx != 1)
500 return UnableToLegalize;
501
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000502 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
503 // FIXME: add support for when SizeOp1 isn't an exact multiple of
504 // NarrowSize.
505 if (SizeOp1 % NarrowSize != 0)
506 return UnableToLegalize;
507 int NumParts = SizeOp1 / NarrowSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000508
509 SmallVector<unsigned, 2> SrcRegs, DstRegs;
510 SmallVector<uint64_t, 2> Indexes;
511 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
512
513 unsigned OpReg = MI.getOperand(0).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000514 uint64_t OpStart = MI.getOperand(2).getImm();
515 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000516 for (int i = 0; i < NumParts; ++i) {
517 unsigned SrcStart = i * NarrowSize;
518
519 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
520 // No part of the extract uses this subregister, ignore it.
521 continue;
522 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
523 // The entire subregister is extracted, forward the value.
524 DstRegs.push_back(SrcRegs[i]);
525 continue;
526 }
527
528 // OpSegStart is where this destination segment would start in OpReg if it
529 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000530 int64_t ExtractOffset;
531 uint64_t SegSize;
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000532 if (OpStart < SrcStart) {
533 ExtractOffset = 0;
534 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
535 } else {
536 ExtractOffset = OpStart - SrcStart;
537 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
538 }
539
540 unsigned SegReg = SrcRegs[i];
541 if (ExtractOffset != 0 || SegSize != NarrowSize) {
542 // A genuine extract is needed.
543 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
544 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
545 }
546
547 DstRegs.push_back(SegReg);
548 }
549
Amara Emerson5ec14602018-12-10 18:44:58 +0000550 unsigned DstReg = MI.getOperand(0).getReg();
551 if(MRI.getType(DstReg).isVector())
552 MIRBuilder.buildBuildVector(DstReg, DstRegs);
553 else
554 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverc2d5e6d2017-06-26 20:34:13 +0000555 MI.eraseFromParent();
556 return Legalized;
557 }
Tim Northover0e6afbd2017-02-06 21:56:47 +0000558 case TargetOpcode::G_INSERT: {
Matt Arsenault30989e42019-01-22 21:42:11 +0000559 // FIXME: Don't know how to handle secondary types yet.
560 if (TypeIdx != 0)
561 return UnableToLegalize;
562
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000563 // FIXME: add support for when SizeOp0 isn't an exact multiple of
564 // NarrowSize.
565 if (SizeOp0 % NarrowSize != 0)
Tim Northover0e6afbd2017-02-06 21:56:47 +0000566 return UnableToLegalize;
567
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000568 int NumParts = SizeOp0 / NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000569
570 SmallVector<unsigned, 2> SrcRegs, DstRegs;
571 SmallVector<uint64_t, 2> Indexes;
572 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
573
Tim Northover75e0b912017-03-06 18:23:04 +0000574 unsigned OpReg = MI.getOperand(2).getReg();
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000575 uint64_t OpStart = MI.getOperand(3).getImm();
576 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
Tim Northover0e6afbd2017-02-06 21:56:47 +0000577 for (int i = 0; i < NumParts; ++i) {
578 unsigned DstStart = i * NarrowSize;
Tim Northover0e6afbd2017-02-06 21:56:47 +0000579
Tim Northover75e0b912017-03-06 18:23:04 +0000580 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000581 // No part of the insert affects this subregister, forward the original.
582 DstRegs.push_back(SrcRegs[i]);
583 continue;
Tim Northover75e0b912017-03-06 18:23:04 +0000584 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
Tim Northover0e6afbd2017-02-06 21:56:47 +0000585 // The entire subregister is defined by this insert, forward the new
586 // value.
Tim Northover75e0b912017-03-06 18:23:04 +0000587 DstRegs.push_back(OpReg);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000588 continue;
589 }
590
Tim Northover2eb18d32017-03-07 21:24:33 +0000591 // OpSegStart is where this destination segment would start in OpReg if it
592 // extended infinitely in both directions.
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000593 int64_t ExtractOffset, InsertOffset;
594 uint64_t SegSize;
Tim Northover2eb18d32017-03-07 21:24:33 +0000595 if (OpStart < DstStart) {
596 InsertOffset = 0;
597 ExtractOffset = DstStart - OpStart;
598 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
599 } else {
600 InsertOffset = OpStart - DstStart;
601 ExtractOffset = 0;
602 SegSize =
603 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
604 }
605
606 unsigned SegReg = OpReg;
607 if (ExtractOffset != 0 || SegSize != OpSize) {
Tim Northover75e0b912017-03-06 18:23:04 +0000608 // A genuine extract is needed.
Tim Northover2eb18d32017-03-07 21:24:33 +0000609 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
610 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000611 }
612
Tim Northover75e0b912017-03-06 18:23:04 +0000613 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Tim Northover2eb18d32017-03-07 21:24:33 +0000614 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000615 DstRegs.push_back(DstReg);
616 }
617
618 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Amara Emerson5ec14602018-12-10 18:44:58 +0000619 unsigned DstReg = MI.getOperand(0).getReg();
620 if(MRI.getType(DstReg).isVector())
621 MIRBuilder.buildBuildVector(DstReg, DstRegs);
622 else
623 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover0e6afbd2017-02-06 21:56:47 +0000624 MI.eraseFromParent();
625 return Legalized;
626 }
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000627 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000628 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000629 unsigned DstReg = MI.getOperand(0).getReg();
630 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000631 int NumParts = SizeOp0 / NarrowSize;
632 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
633 unsigned LeftoverBits = DstTy.getSizeInBits() - HandledSize;
634
635 if (DstTy.isVector() && LeftoverBits != 0)
636 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000637
638 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
639 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
640 auto &MMO = **MI.memoperands_begin();
641 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
642 MIRBuilder.buildAnyExt(DstReg, TmpReg);
643 MI.eraseFromParent();
644 return Legalized;
645 }
646
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000647 // This implementation doesn't work for atomics. Give up instead of doing
648 // something invalid.
649 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
650 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
651 return UnableToLegalize;
652
Daniel Sanders4e523662017-06-13 23:42:32 +0000653 LLT OffsetTy = LLT::scalar(
654 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000655
Matt Arsenault8db20012019-01-31 01:49:58 +0000656 MachineFunction &MF = MIRBuilder.getMF();
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000657 SmallVector<unsigned, 2> DstRegs;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000658 for (int i = 0; i < NumParts; ++i) {
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000659 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Daniel Sanders4e523662017-06-13 23:42:32 +0000660 unsigned SrcReg = 0;
Matt Arsenault8db20012019-01-31 01:49:58 +0000661 unsigned Offset = i * NarrowSize / 8;
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000662
Matt Arsenault8db20012019-01-31 01:49:58 +0000663 MachineMemOperand *SplitMMO =
664 MF.getMachineMemOperand(&MMO, Offset, NarrowSize / 8);
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000665
Daniel Sanders4e523662017-06-13 23:42:32 +0000666 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
Matt Arsenault8db20012019-01-31 01:49:58 +0000667 Offset);
Daniel Sanders4e523662017-06-13 23:42:32 +0000668
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000669 MIRBuilder.buildLoad(PartDstReg, SrcReg, *SplitMMO);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000670
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000671 DstRegs.push_back(PartDstReg);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000672 }
Matt Arsenault18619af2019-01-29 18:13:02 +0000673
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000674 unsigned MergeResultReg = LeftoverBits == 0 ? DstReg :
675 MRI.createGenericVirtualRegister(LLT::scalar(HandledSize));
676
677 // For the leftover piece, still create the merge and insert it.
678 // TODO: Would it be better to directly insert the intermediate pieces?
Matt Arsenault18619af2019-01-29 18:13:02 +0000679 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000680 MIRBuilder.buildBuildVector(MergeResultReg, DstRegs);
Amara Emerson5ec14602018-12-10 18:44:58 +0000681 else
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000682 MIRBuilder.buildMerge(MergeResultReg, DstRegs);
683
684 if (LeftoverBits == 0) {
685 MI.eraseFromParent();
686 return Legalized;
687 }
688
689 unsigned ImpDefReg = MRI.createGenericVirtualRegister(DstTy);
690 unsigned Insert0Reg = MRI.createGenericVirtualRegister(DstTy);
691 MIRBuilder.buildUndef(ImpDefReg);
692 MIRBuilder.buildInsert(Insert0Reg, ImpDefReg, MergeResultReg, 0);
693
694 unsigned PartDstReg
695 = MRI.createGenericVirtualRegister(LLT::scalar(LeftoverBits));
696 unsigned Offset = HandledSize / 8;
697
698 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand(
699 &MMO, Offset, LeftoverBits / 8);
700
701 unsigned SrcReg = 0;
702 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
703 Offset);
704 MIRBuilder.buildLoad(PartDstReg, SrcReg, *SplitMMO);
705 MIRBuilder.buildInsert(DstReg, Insert0Reg, PartDstReg, HandledSize);
706
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000707 MI.eraseFromParent();
708 return Legalized;
709 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000710 case TargetOpcode::G_ZEXTLOAD:
711 case TargetOpcode::G_SEXTLOAD: {
712 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
713 unsigned DstReg = MI.getOperand(0).getReg();
714 unsigned PtrReg = MI.getOperand(1).getReg();
715
716 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
717 auto &MMO = **MI.memoperands_begin();
718 if (MMO.getSize() * 8 == NarrowSize) {
719 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
720 } else {
721 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
722 : TargetOpcode::G_SEXTLOAD;
723 MIRBuilder.buildInstr(ExtLoad)
724 .addDef(TmpReg)
725 .addUse(PtrReg)
726 .addMemOperand(&MMO);
727 }
728
729 if (ZExt)
730 MIRBuilder.buildZExt(DstReg, TmpReg);
731 else
732 MIRBuilder.buildSExt(DstReg, TmpReg);
733
734 MI.eraseFromParent();
735 return Legalized;
736 }
Justin Bognerfde01042017-01-18 17:29:54 +0000737 case TargetOpcode::G_STORE: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000738 // FIXME: add support for when SizeOp0 isn't an exact multiple of
739 // NarrowSize.
740 if (SizeOp0 % NarrowSize != 0)
741 return UnableToLegalize;
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000742
743 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000744
745 unsigned SrcReg = MI.getOperand(0).getReg();
746 LLT SrcTy = MRI.getType(SrcReg);
747
748 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
749 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
750 auto &MMO = **MI.memoperands_begin();
751 MIRBuilder.buildTrunc(TmpReg, SrcReg);
752 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
753 MI.eraseFromParent();
754 return Legalized;
755 }
756
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000757 // This implementation doesn't work for atomics. Give up instead of doing
758 // something invalid.
759 if (MMO.getOrdering() != AtomicOrdering::NotAtomic ||
760 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic)
761 return UnableToLegalize;
762
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000763 int NumParts = SizeOp0 / NarrowSize;
Daniel Sanders4e523662017-06-13 23:42:32 +0000764 LLT OffsetTy = LLT::scalar(
765 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
Justin Bognerfde01042017-01-18 17:29:54 +0000766
767 SmallVector<unsigned, 2> SrcRegs;
768 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
769
Matt Arsenault8db20012019-01-31 01:49:58 +0000770 MachineFunction &MF = MIRBuilder.getMF();
Justin Bognerfde01042017-01-18 17:29:54 +0000771 for (int i = 0; i < NumParts; ++i) {
Daniel Sanders4e523662017-06-13 23:42:32 +0000772 unsigned DstReg = 0;
Matt Arsenault8db20012019-01-31 01:49:58 +0000773 unsigned Offset = i * NarrowSize / 8;
Daniel Sanders4e523662017-06-13 23:42:32 +0000774
Matt Arsenault8db20012019-01-31 01:49:58 +0000775 MachineMemOperand *SplitMMO =
776 MF.getMachineMemOperand(&MMO, Offset, NarrowSize / 8);
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000777
Daniel Sanders4e523662017-06-13 23:42:32 +0000778 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
Matt Arsenault8db20012019-01-31 01:49:58 +0000779 Offset);
Daniel Sanders4e523662017-06-13 23:42:32 +0000780
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000781 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO);
Justin Bognerfde01042017-01-18 17:29:54 +0000782 }
783 MI.eraseFromParent();
784 return Legalized;
785 }
Igor Breger29537882017-04-07 14:41:59 +0000786 case TargetOpcode::G_CONSTANT: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000787 // FIXME: add support for when SizeOp0 isn't an exact multiple of
788 // NarrowSize.
789 if (SizeOp0 % NarrowSize != 0)
790 return UnableToLegalize;
791 int NumParts = SizeOp0 / NarrowSize;
Igor Breger29537882017-04-07 14:41:59 +0000792 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
Matthias Braunf1caa282017-12-15 22:22:58 +0000793 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Igor Breger29537882017-04-07 14:41:59 +0000794
795 SmallVector<unsigned, 2> DstRegs;
796 for (int i = 0; i < NumParts; ++i) {
797 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
798 ConstantInt *CI =
799 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
800 MIRBuilder.buildConstant(DstReg, *CI);
801 DstRegs.push_back(DstReg);
802 }
803 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000804 if(MRI.getType(DstReg).isVector())
805 MIRBuilder.buildBuildVector(DstReg, DstRegs);
806 else
807 MIRBuilder.buildMerge(DstReg, DstRegs);
Igor Breger29537882017-04-07 14:41:59 +0000808 MI.eraseFromParent();
809 return Legalized;
810 }
Petar Avramovic150fd432018-12-18 11:36:14 +0000811 case TargetOpcode::G_AND:
812 case TargetOpcode::G_OR:
813 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000814 // Legalize bitwise operation:
815 // A = BinOp<Ty> B, C
816 // into:
817 // B1, ..., BN = G_UNMERGE_VALUES B
818 // C1, ..., CN = G_UNMERGE_VALUES C
819 // A1 = BinOp<Ty/N> B1, C2
820 // ...
821 // AN = BinOp<Ty/N> BN, CN
822 // A = G_MERGE_VALUES A1, ..., AN
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000823
824 // FIXME: add support for when SizeOp0 isn't an exact multiple of
825 // NarrowSize.
826 if (SizeOp0 % NarrowSize != 0)
827 return UnableToLegalize;
828 int NumParts = SizeOp0 / NarrowSize;
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000829
830 // List the registers where the destination will be scattered.
831 SmallVector<unsigned, 2> DstRegs;
832 // List the registers where the first argument will be split.
833 SmallVector<unsigned, 2> SrcsReg1;
834 // List the registers where the second argument will be split.
835 SmallVector<unsigned, 2> SrcsReg2;
836 // Create all the temporary registers.
837 for (int i = 0; i < NumParts; ++i) {
838 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
839 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
840 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
841
842 DstRegs.push_back(DstReg);
843 SrcsReg1.push_back(SrcReg1);
844 SrcsReg2.push_back(SrcReg2);
845 }
846 // Explode the big arguments into smaller chunks.
847 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
848 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
849
850 // Do the operation on each small part.
851 for (int i = 0; i < NumParts; ++i)
Petar Avramovic150fd432018-12-18 11:36:14 +0000852 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]},
853 {SrcsReg1[i], SrcsReg2[i]});
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000854
855 // Gather the destination registers into the final destination.
856 unsigned DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000857 if(MRI.getType(DstReg).isVector())
858 MIRBuilder.buildBuildVector(DstReg, DstRegs);
859 else
860 MIRBuilder.buildMerge(DstReg, DstRegs);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000861 MI.eraseFromParent();
862 return Legalized;
863 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000864 case TargetOpcode::G_SHL:
865 case TargetOpcode::G_LSHR:
866 case TargetOpcode::G_ASHR: {
867 if (TypeIdx != 1)
868 return UnableToLegalize; // TODO
Matt Arsenaultcf4db732019-01-31 02:22:39 +0000869 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +0000870 narrowScalarSrc(MI, NarrowTy, 2);
Amara Emerson13311e52019-01-30 23:42:46 +0000871 Observer.changedInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +0000872 return Legalized;
873 }
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000874 case TargetOpcode::G_CTLZ:
875 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
876 case TargetOpcode::G_CTTZ:
877 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
878 case TargetOpcode::G_CTPOP:
879 if (TypeIdx != 0)
880 return UnableToLegalize; // TODO
881
882 Observer.changingInstr(MI);
883 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
884 Observer.changedInstr(MI);
885 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000886 case TargetOpcode::G_INTTOPTR:
887 if (TypeIdx != 1)
888 return UnableToLegalize;
889
890 Observer.changingInstr(MI);
891 narrowScalarSrc(MI, NarrowTy, 1);
892 Observer.changedInstr(MI);
893 return Legalized;
894 case TargetOpcode::G_PTRTOINT:
895 if (TypeIdx != 0)
896 return UnableToLegalize;
897
898 Observer.changingInstr(MI);
899 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
900 Observer.changedInstr(MI);
901 return Legalized;
Tim Northover9656f142016-08-04 20:54:13 +0000902 }
Tim Northover33b07d62016-07-22 20:03:43 +0000903}
904
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000905void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
906 unsigned OpIdx, unsigned ExtOpcode) {
907 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000908 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000909 MO.setReg(ExtB->getOperand(0).getReg());
910}
911
Matt Arsenault30989e42019-01-22 21:42:11 +0000912void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
913 unsigned OpIdx) {
914 MachineOperand &MO = MI.getOperand(OpIdx);
915 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
916 {MO.getReg()});
917 MO.setReg(ExtB->getOperand(0).getReg());
918}
919
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000920void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
921 unsigned OpIdx, unsigned TruncOpcode) {
922 MachineOperand &MO = MI.getOperand(OpIdx);
923 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
924 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000925 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000926 MO.setReg(DstExt);
927}
928
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000929void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
930 unsigned OpIdx, unsigned ExtOpcode) {
931 MachineOperand &MO = MI.getOperand(OpIdx);
932 unsigned DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
933 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
934 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
935 MO.setReg(DstTrunc);
936}
937
Tim Northover69fa84a2016-10-14 22:18:18 +0000938LegalizerHelper::LegalizeResult
939LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +0000940 MIRBuilder.setInstr(MI);
941
Tim Northover32335812016-08-04 18:35:11 +0000942 switch (MI.getOpcode()) {
943 default:
944 return UnableToLegalize;
Matt Arsenaultd8d193d2019-01-29 23:17:35 +0000945 case TargetOpcode::G_MERGE_VALUES: {
946 if (TypeIdx != 1)
947 return UnableToLegalize;
948
949 unsigned DstReg = MI.getOperand(0).getReg();
950 LLT DstTy = MRI.getType(DstReg);
951 if (!DstTy.isScalar())
952 return UnableToLegalize;
953
954 unsigned NumSrc = MI.getNumOperands() - 1;
955 unsigned EltSize = DstTy.getSizeInBits() / NumSrc;
Matt Arsenaultd8d193d2019-01-29 23:17:35 +0000956
957 unsigned ResultReg = MRI.createGenericVirtualRegister(DstTy);
958 unsigned Offset = 0;
959 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I,
960 Offset += EltSize) {
Matt Arsenault3de9a962019-01-29 23:38:42 +0000961 assert(MRI.getType(MI.getOperand(I).getReg()) == LLT::scalar(EltSize));
Matt Arsenaultd8d193d2019-01-29 23:17:35 +0000962
963 unsigned ShiftAmt = MRI.createGenericVirtualRegister(DstTy);
964 unsigned Shl = MRI.createGenericVirtualRegister(DstTy);
965 unsigned ZextInput = MRI.createGenericVirtualRegister(DstTy);
966 MIRBuilder.buildZExt(ZextInput, MI.getOperand(I).getReg());
967
968 if (Offset != 0) {
969 unsigned NextResult = I + 1 == E ? DstReg :
970 MRI.createGenericVirtualRegister(DstTy);
971
972 MIRBuilder.buildConstant(ShiftAmt, Offset);
973 MIRBuilder.buildShl(Shl, ZextInput, ShiftAmt);
974 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
975 ResultReg = NextResult;
976 } else {
977 ResultReg = ZextInput;
978 }
979 }
980
981 MI.eraseFromParent();
982 return Legalized;
983 }
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000984 case TargetOpcode::G_UADDO:
985 case TargetOpcode::G_USUBO: {
986 if (TypeIdx == 1)
987 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000988 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
989 {MI.getOperand(2).getReg()});
990 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
991 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000992 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
993 ? TargetOpcode::G_ADD
994 : TargetOpcode::G_SUB;
995 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000996 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +0000997 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
998 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
999 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001000 TargetOpcode::G_AND, {WideTy},
1001 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001002 // There is no overflow if the AndOp is the same as NewOp.
1003 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1004 AndOp);
1005 // Now trunc the NewOp to the original result.
1006 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1007 MI.eraseFromParent();
1008 return Legalized;
1009 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001010 case TargetOpcode::G_CTTZ:
1011 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1012 case TargetOpcode::G_CTLZ:
1013 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1014 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001015 if (TypeIdx == 0) {
1016 widenScalarDst(MI, WideTy, 0);
1017 return Legalized;
1018 }
1019
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001020 // First ZEXT the input.
1021 auto MIBSrc = MIRBuilder.buildZExt(WideTy, MI.getOperand(1).getReg());
1022 LLT CurTy = MRI.getType(MI.getOperand(0).getReg());
1023 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1024 // The count is the same in the larger type except if the original
1025 // value was zero. This can be handled by setting the bit just off
1026 // the top of the original type.
1027 auto TopBit =
1028 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
1029 MIBSrc = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001030 TargetOpcode::G_OR, {WideTy},
1031 {MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit.getSExtValue())});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001032 }
1033 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001034 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001035 // This is already the correct result for CTPOP and CTTZs
1036 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1037 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1038 // The correct result is NewOp - (Difference in widety and current ty).
1039 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001040 MIBNewOp = MIRBuilder.buildInstr(
1041 TargetOpcode::G_SUB, {WideTy},
1042 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001043 }
1044 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus30887bf2018-11-26 11:06:53 +00001045 // Make the original instruction a trunc now, and update its source.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001046 Observer.changingInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001047 MI.setDesc(TII.get(TargetOpcode::G_TRUNC));
1048 MI.getOperand(1).setReg(MIBNewOp->getOperand(0).getReg());
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001049 Observer.changedInstr(MI);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001050 return Legalized;
1051 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001052 case TargetOpcode::G_BSWAP: {
1053 Observer.changingInstr(MI);
1054 unsigned DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001055
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001056 unsigned ShrReg = MRI.createGenericVirtualRegister(WideTy);
1057 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
1058 unsigned ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
1059 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1060
1061 MI.getOperand(0).setReg(DstExt);
1062
1063 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1064
1065 LLT Ty = MRI.getType(DstReg);
1066 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1067 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1068 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1069 .addDef(ShrReg)
1070 .addUse(DstExt)
1071 .addUse(ShiftAmtReg);
1072
1073 MIRBuilder.buildTrunc(DstReg, ShrReg);
1074 Observer.changedInstr(MI);
1075 return Legalized;
1076 }
Tim Northover61c16142016-08-04 21:39:49 +00001077 case TargetOpcode::G_ADD:
1078 case TargetOpcode::G_AND:
1079 case TargetOpcode::G_MUL:
1080 case TargetOpcode::G_OR:
1081 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001082 case TargetOpcode::G_SUB:
Tim Northover32335812016-08-04 18:35:11 +00001083 // Perform operation at larger width (any extension is fine here, high bits
1084 // don't affect the result) and then truncate the result back to the
1085 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001086 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001087 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1088 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1089 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001090 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001091 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001092
Roman Tereshin6d266382018-05-09 21:43:30 +00001093 case TargetOpcode::G_SHL:
Matt Arsenault30989e42019-01-22 21:42:11 +00001094 Observer.changingInstr(MI);
1095
1096 if (TypeIdx == 0) {
1097 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1098 widenScalarDst(MI, WideTy);
1099 } else {
1100 assert(TypeIdx == 1);
1101 // The "number of bits to shift" operand must preserve its value as an
1102 // unsigned integer:
1103 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1104 }
1105
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001106 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001107 return Legalized;
1108
Tim Northover7a753d92016-08-26 17:46:06 +00001109 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001110 case TargetOpcode::G_SREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001111 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001112 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1113 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1114 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001115 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001116 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001117
Roman Tereshin6d266382018-05-09 21:43:30 +00001118 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001119 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001120 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001121
1122 if (TypeIdx == 0) {
1123 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1124 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1125
1126 widenScalarSrc(MI, WideTy, 1, CvtOp);
1127 widenScalarDst(MI, WideTy);
1128 } else {
1129 assert(TypeIdx == 1);
1130 // The "number of bits to shift" operand must preserve its value as an
1131 // unsigned integer:
1132 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1133 }
1134
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001135 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001136 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001137 case TargetOpcode::G_UDIV:
1138 case TargetOpcode::G_UREM:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001139 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001140 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1141 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1142 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001143 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001144 return Legalized;
1145
1146 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001147 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001148 if (TypeIdx == 0) {
1149 // Perform operation at larger width (any extension is fine here, high
1150 // bits don't affect the result) and then truncate the result back to the
1151 // original type.
1152 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1153 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1154 widenScalarDst(MI, WideTy);
1155 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001156 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001157 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001158 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001159 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001160 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001161 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001162
Ahmed Bougachab6137062017-01-23 21:10:14 +00001163 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001164 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001165 if (TypeIdx != 0)
1166 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001167 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001168 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001169 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001170 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001171
Ahmed Bougachad2948232017-01-20 01:37:24 +00001172 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001173 if (TypeIdx != 1)
1174 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001175 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001176 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001177 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001178 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001179
1180 case TargetOpcode::G_UITOFP:
1181 if (TypeIdx != 1)
1182 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001183 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001184 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001185 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001186 return Legalized;
1187
1188 case TargetOpcode::G_INSERT:
Tim Northover0e6afbd2017-02-06 21:56:47 +00001189 if (TypeIdx != 0)
1190 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001191 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001192 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1193 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001194 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001195 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001196
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001197 case TargetOpcode::G_LOAD:
Amara Emersoncbc02c72018-02-01 20:47:03 +00001198 // For some types like i24, we might try to widen to i32. To properly handle
1199 // this we should be using a dedicated extending load, until then avoid
1200 // trying to legalize.
1201 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
1202 WideTy.getSizeInBits())
1203 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001204 LLVM_FALLTHROUGH;
1205 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001206 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001207 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001208 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001209 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001210 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001211
Tim Northover3c73e362016-08-23 18:20:09 +00001212 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001213 if (TypeIdx != 0)
1214 return UnableToLegalize;
1215
1216 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1217 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001218 return UnableToLegalize;
1219
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001220 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001221
1222 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1223 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1224 widenScalarSrc(MI, WideTy, 0, ExtType);
1225
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001226 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001227 return Legalized;
1228 }
Tim Northoverea904f92016-08-19 22:40:00 +00001229 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001230 MachineOperand &SrcMO = MI.getOperand(1);
1231 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1232 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001233 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001234 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1235
1236 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001237 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001238 return Legalized;
1239 }
Tim Northovera11be042016-08-19 22:40:08 +00001240 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001241 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001242 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001243 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001244 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001245 switch (WideTy.getSizeInBits()) {
1246 case 32:
1247 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo);
1248 break;
1249 case 64:
1250 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo);
1251 break;
1252 default:
1253 llvm_unreachable("Unhandled fp widen type");
Tim Northover6cd4b232016-08-23 21:01:26 +00001254 }
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001255 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001256 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1257
1258 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001259 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001260 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001261 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001262 case TargetOpcode::G_IMPLICIT_DEF: {
1263 Observer.changingInstr(MI);
1264 widenScalarDst(MI, WideTy);
1265 Observer.changedInstr(MI);
1266 return Legalized;
1267 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001268 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001269 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001270 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001271 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001272 return Legalized;
1273
1274 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001275 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001276 if (TypeIdx == 0)
1277 widenScalarDst(MI, WideTy);
1278 else {
1279 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1280 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001281 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001282 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001283 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001284
1285 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001286 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001287 if (TypeIdx == 0)
1288 widenScalarDst(MI, WideTy);
1289 else {
1290 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1291 MI.getOperand(1).getPredicate()))
1292 ? TargetOpcode::G_SEXT
1293 : TargetOpcode::G_ZEXT;
1294 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1295 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1296 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001297 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001298 return Legalized;
1299
1300 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001301 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001302 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001303 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001304 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001305 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001306
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001307 case TargetOpcode::G_PHI: {
1308 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001309
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001310 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001311 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1312 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1313 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1314 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001315 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001316
1317 MachineBasicBlock &MBB = *MI.getParent();
1318 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1319 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001320 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001321 return Legalized;
1322 }
Matt Arsenault63786292019-01-22 20:38:15 +00001323 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1324 if (TypeIdx == 0) {
1325 unsigned VecReg = MI.getOperand(1).getReg();
1326 LLT VecTy = MRI.getType(VecReg);
1327 Observer.changingInstr(MI);
1328
1329 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1330 WideTy.getSizeInBits()),
1331 1, TargetOpcode::G_SEXT);
1332
1333 widenScalarDst(MI, WideTy, 0);
1334 Observer.changedInstr(MI);
1335 return Legalized;
1336 }
1337
Amara Emersoncbd86d82018-10-25 14:04:54 +00001338 if (TypeIdx != 2)
1339 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001340 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001341 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001342 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001343 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001344 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001345 case TargetOpcode::G_FADD:
1346 case TargetOpcode::G_FMUL:
1347 case TargetOpcode::G_FSUB:
1348 case TargetOpcode::G_FMA:
1349 case TargetOpcode::G_FNEG:
1350 case TargetOpcode::G_FABS:
1351 case TargetOpcode::G_FDIV:
1352 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001353 case TargetOpcode::G_FCEIL:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001354 case TargetOpcode::G_FCOS:
1355 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001356 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001357 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001358 case TargetOpcode::G_FLOG2:
Jessica Paquette22457f82019-01-30 21:03:52 +00001359 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001360 case TargetOpcode::G_FEXP:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001361 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001362 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001363
1364 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1365 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1366
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001367 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1368 Observer.changedInstr(MI);
1369 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001370 case TargetOpcode::G_INTTOPTR:
1371 if (TypeIdx != 1)
1372 return UnableToLegalize;
1373
1374 Observer.changingInstr(MI);
1375 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1376 Observer.changedInstr(MI);
1377 return Legalized;
1378 case TargetOpcode::G_PTRTOINT:
1379 if (TypeIdx != 0)
1380 return UnableToLegalize;
1381
1382 Observer.changingInstr(MI);
1383 widenScalarDst(MI, WideTy, 0);
1384 Observer.changedInstr(MI);
1385 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001386 }
Tim Northover33b07d62016-07-22 20:03:43 +00001387}
1388
Tim Northover69fa84a2016-10-14 22:18:18 +00001389LegalizerHelper::LegalizeResult
1390LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001391 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001392 MIRBuilder.setInstr(MI);
1393
1394 switch(MI.getOpcode()) {
1395 default:
1396 return UnableToLegalize;
1397 case TargetOpcode::G_SREM:
1398 case TargetOpcode::G_UREM: {
Tim Northover0f140c72016-09-09 11:46:34 +00001399 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
1400 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001401 .addDef(QuotReg)
1402 .addUse(MI.getOperand(1).getReg())
1403 .addUse(MI.getOperand(2).getReg());
1404
Tim Northover0f140c72016-09-09 11:46:34 +00001405 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
1406 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1407 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1408 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001409 MI.eraseFromParent();
1410 return Legalized;
1411 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001412 case TargetOpcode::G_SMULO:
1413 case TargetOpcode::G_UMULO: {
1414 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1415 // result.
1416 unsigned Res = MI.getOperand(0).getReg();
1417 unsigned Overflow = MI.getOperand(1).getReg();
1418 unsigned LHS = MI.getOperand(2).getReg();
1419 unsigned RHS = MI.getOperand(3).getReg();
1420
1421 MIRBuilder.buildMul(Res, LHS, RHS);
1422
1423 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1424 ? TargetOpcode::G_SMULH
1425 : TargetOpcode::G_UMULH;
1426
1427 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
1428 MIRBuilder.buildInstr(Opcode)
1429 .addDef(HiPart)
1430 .addUse(LHS)
1431 .addUse(RHS);
1432
1433 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
1434 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001435
1436 // For *signed* multiply, overflow is detected by checking:
1437 // (hi != (lo >> bitwidth-1))
1438 if (Opcode == TargetOpcode::G_SMULH) {
1439 unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
1440 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
1441 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1442 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1443 .addDef(Shifted)
1444 .addUse(Res)
1445 .addUse(ShiftAmt);
1446 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1447 } else {
1448 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1449 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001450 MI.eraseFromParent();
1451 return Legalized;
1452 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001453 case TargetOpcode::G_FNEG: {
1454 // TODO: Handle vector types once we are able to
1455 // represent them.
1456 if (Ty.isVector())
1457 return UnableToLegalize;
1458 unsigned Res = MI.getOperand(0).getReg();
1459 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001460 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001461 switch (Ty.getSizeInBits()) {
1462 case 16:
1463 ZeroTy = Type::getHalfTy(Ctx);
1464 break;
1465 case 32:
1466 ZeroTy = Type::getFloatTy(Ctx);
1467 break;
1468 case 64:
1469 ZeroTy = Type::getDoubleTy(Ctx);
1470 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001471 case 128:
1472 ZeroTy = Type::getFP128Ty(Ctx);
1473 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001474 default:
1475 llvm_unreachable("unexpected floating-point type");
1476 }
1477 ConstantFP &ZeroForNegation =
1478 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001479 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Volkan Keles5698b2a2017-03-08 18:09:14 +00001480 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
1481 .addDef(Res)
Volkan Keles02bb1742018-02-14 19:58:36 +00001482 .addUse(Zero->getOperand(0).getReg())
Volkan Keles5698b2a2017-03-08 18:09:14 +00001483 .addUse(MI.getOperand(1).getReg());
1484 MI.eraseFromParent();
1485 return Legalized;
1486 }
Volkan Keles225921a2017-03-10 21:25:09 +00001487 case TargetOpcode::G_FSUB: {
1488 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1489 // First, check if G_FNEG is marked as Lower. If so, we may
1490 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001491 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001492 return UnableToLegalize;
1493 unsigned Res = MI.getOperand(0).getReg();
1494 unsigned LHS = MI.getOperand(1).getReg();
1495 unsigned RHS = MI.getOperand(2).getReg();
1496 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
1497 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
1498 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
1499 .addDef(Res)
1500 .addUse(LHS)
1501 .addUse(Neg);
1502 MI.eraseFromParent();
1503 return Legalized;
1504 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001505 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1506 unsigned OldValRes = MI.getOperand(0).getReg();
1507 unsigned SuccessRes = MI.getOperand(1).getReg();
1508 unsigned Addr = MI.getOperand(2).getReg();
1509 unsigned CmpVal = MI.getOperand(3).getReg();
1510 unsigned NewVal = MI.getOperand(4).getReg();
1511 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1512 **MI.memoperands_begin());
1513 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1514 MI.eraseFromParent();
1515 return Legalized;
1516 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001517 case TargetOpcode::G_LOAD:
1518 case TargetOpcode::G_SEXTLOAD:
1519 case TargetOpcode::G_ZEXTLOAD: {
1520 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
1521 unsigned DstReg = MI.getOperand(0).getReg();
1522 unsigned PtrReg = MI.getOperand(1).getReg();
1523 LLT DstTy = MRI.getType(DstReg);
1524 auto &MMO = **MI.memoperands_begin();
1525
1526 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001527 // In the case of G_LOAD, this was a non-extending load already and we're
1528 // about to lower to the same instruction.
1529 if (MI.getOpcode() == TargetOpcode::G_LOAD)
1530 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001531 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1532 MI.eraseFromParent();
1533 return Legalized;
1534 }
1535
1536 if (DstTy.isScalar()) {
1537 unsigned TmpReg = MRI.createGenericVirtualRegister(
1538 LLT::scalar(MMO.getSize() /* in bytes */ * 8));
1539 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1540 switch (MI.getOpcode()) {
1541 default:
1542 llvm_unreachable("Unexpected opcode");
1543 case TargetOpcode::G_LOAD:
1544 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1545 break;
1546 case TargetOpcode::G_SEXTLOAD:
1547 MIRBuilder.buildSExt(DstReg, TmpReg);
1548 break;
1549 case TargetOpcode::G_ZEXTLOAD:
1550 MIRBuilder.buildZExt(DstReg, TmpReg);
1551 break;
1552 }
1553 MI.eraseFromParent();
1554 return Legalized;
1555 }
1556
1557 return UnableToLegalize;
1558 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001559 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1560 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1561 case TargetOpcode::G_CTLZ:
1562 case TargetOpcode::G_CTTZ:
1563 case TargetOpcode::G_CTPOP:
1564 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001565 case G_UADDE: {
1566 unsigned Res = MI.getOperand(0).getReg();
1567 unsigned CarryOut = MI.getOperand(1).getReg();
1568 unsigned LHS = MI.getOperand(2).getReg();
1569 unsigned RHS = MI.getOperand(3).getReg();
1570 unsigned CarryIn = MI.getOperand(4).getReg();
1571
1572 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1573 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
1574
1575 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1576 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1577 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1578 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1579
1580 MI.eraseFromParent();
1581 return Legalized;
1582 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001583 case G_USUBO: {
1584 unsigned Res = MI.getOperand(0).getReg();
1585 unsigned BorrowOut = MI.getOperand(1).getReg();
1586 unsigned LHS = MI.getOperand(2).getReg();
1587 unsigned RHS = MI.getOperand(3).getReg();
1588
1589 MIRBuilder.buildSub(Res, LHS, RHS);
1590 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1591
1592 MI.eraseFromParent();
1593 return Legalized;
1594 }
1595 case G_USUBE: {
1596 unsigned Res = MI.getOperand(0).getReg();
1597 unsigned BorrowOut = MI.getOperand(1).getReg();
1598 unsigned LHS = MI.getOperand(2).getReg();
1599 unsigned RHS = MI.getOperand(3).getReg();
1600 unsigned BorrowIn = MI.getOperand(4).getReg();
1601
1602 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty);
1603 unsigned ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1604 unsigned LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1605 unsigned LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1606
1607 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1608 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1609 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1610 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1611 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1612 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1613
1614 MI.eraseFromParent();
1615 return Legalized;
1616 }
Tim Northovercecee562016-08-26 17:46:13 +00001617 }
1618}
1619
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001620LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1621 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
1622 SmallVector<unsigned, 2> DstRegs;
1623
1624 unsigned NarrowSize = NarrowTy.getSizeInBits();
1625 unsigned DstReg = MI.getOperand(0).getReg();
1626 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1627 int NumParts = Size / NarrowSize;
1628 // FIXME: Don't know how to handle the situation where the small vectors
1629 // aren't all the same size yet.
1630 if (Size % NarrowSize != 0)
1631 return UnableToLegalize;
1632
1633 for (int i = 0; i < NumParts; ++i) {
1634 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1635 MIRBuilder.buildUndef(TmpReg);
1636 DstRegs.push_back(TmpReg);
1637 }
1638
1639 if (NarrowTy.isVector())
1640 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1641 else
1642 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1643
1644 MI.eraseFromParent();
1645 return Legalized;
1646}
1647
1648LegalizerHelper::LegalizeResult
1649LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
1650 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001651 const unsigned Opc = MI.getOpcode();
1652 const unsigned NumOps = MI.getNumOperands() - 1;
1653 const unsigned NarrowSize = NarrowTy.getSizeInBits();
1654 const unsigned DstReg = MI.getOperand(0).getReg();
1655 const unsigned Flags = MI.getFlags();
1656 const LLT DstTy = MRI.getType(DstReg);
1657 const unsigned Size = DstTy.getSizeInBits();
1658 const int NumParts = Size / NarrowSize;
1659 const LLT EltTy = DstTy.getElementType();
1660 const unsigned EltSize = EltTy.getSizeInBits();
1661 const unsigned BitsForNumParts = NarrowSize * NumParts;
1662
1663 // Check if we have any leftovers. If we do, then only handle the case where
1664 // the leftover is one element.
1665 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001666 return UnableToLegalize;
1667
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001668 if (BitsForNumParts != Size) {
1669 unsigned AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
1670 MIRBuilder.buildUndef(AccumDstReg);
1671
1672 // Handle the pieces which evenly divide into the requested type with
1673 // extract/op/insert sequence.
1674 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
1675 SmallVector<SrcOp, 4> SrcOps;
1676 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1677 unsigned PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
1678 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
1679 SrcOps.push_back(PartOpReg);
1680 }
1681
1682 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
1683 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1684
1685 unsigned PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
1686 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
1687 AccumDstReg = PartInsertReg;
1688 Offset += NarrowSize;
1689 }
1690
1691 // Handle the remaining element sized leftover piece.
1692 SmallVector<SrcOp, 4> SrcOps;
1693 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1694 unsigned PartOpReg = MRI.createGenericVirtualRegister(EltTy);
1695 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
1696 BitsForNumParts);
1697 SrcOps.push_back(PartOpReg);
1698 }
1699
1700 unsigned PartDstReg = MRI.createGenericVirtualRegister(EltTy);
1701 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1702 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
1703 MI.eraseFromParent();
1704
1705 return Legalized;
1706 }
1707
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001708 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1709
1710 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1711
1712 if (NumOps >= 2)
1713 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1714
1715 if (NumOps >= 3)
1716 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
1717
1718 for (int i = 0; i < NumParts; ++i) {
1719 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1720
1721 if (NumOps == 1)
1722 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1723 else if (NumOps == 2) {
1724 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1725 } else if (NumOps == 3) {
1726 MIRBuilder.buildInstr(Opc, {DstReg},
1727 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1728 }
1729
1730 DstRegs.push_back(DstReg);
1731 }
1732
1733 if (NarrowTy.isVector())
1734 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1735 else
1736 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1737
1738 MI.eraseFromParent();
1739 return Legalized;
1740}
1741
Tim Northover69fa84a2016-10-14 22:18:18 +00001742LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001743LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1744 LLT NarrowTy) {
1745 if (TypeIdx != 0)
1746 return UnableToLegalize;
1747
1748 unsigned DstReg = MI.getOperand(0).getReg();
1749 unsigned SrcReg = MI.getOperand(1).getReg();
1750 LLT DstTy = MRI.getType(DstReg);
1751 LLT SrcTy = MRI.getType(SrcReg);
1752
1753 LLT NarrowTy0 = NarrowTy;
1754 LLT NarrowTy1;
1755 unsigned NumParts;
1756
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001757 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00001758 // Uneven breakdown not handled.
1759 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1760 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1761 return UnableToLegalize;
1762
1763 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001764 } else {
1765 NumParts = DstTy.getNumElements();
1766 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00001767 }
1768
1769 SmallVector<unsigned, 4> SrcRegs, DstRegs;
1770 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1771
1772 for (unsigned I = 0; I < NumParts; ++I) {
1773 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1774 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1775 .addDef(DstReg)
1776 .addUse(SrcRegs[I]);
1777
1778 NewInst->setFlags(MI.getFlags());
1779 DstRegs.push_back(DstReg);
1780 }
1781
1782 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001783 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001784 else
1785 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1786
1787 MI.eraseFromParent();
1788 return Legalized;
1789}
1790
1791LegalizerHelper::LegalizeResult
1792LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1793 LLT NarrowTy) {
1794 unsigned DstReg = MI.getOperand(0).getReg();
1795 unsigned Src0Reg = MI.getOperand(2).getReg();
1796 LLT DstTy = MRI.getType(DstReg);
1797 LLT SrcTy = MRI.getType(Src0Reg);
1798
1799 unsigned NumParts;
1800 LLT NarrowTy0, NarrowTy1;
1801
1802 if (TypeIdx == 0) {
1803 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1804 unsigned OldElts = DstTy.getNumElements();
1805
1806 NarrowTy0 = NarrowTy;
1807 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
1808 NarrowTy1 = NarrowTy.isVector() ?
1809 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
1810 SrcTy.getElementType();
1811
1812 } else {
1813 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
1814 unsigned OldElts = SrcTy.getNumElements();
1815
1816 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
1817 NarrowTy.getNumElements();
1818 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
1819 DstTy.getScalarSizeInBits());
1820 NarrowTy1 = NarrowTy;
1821 }
1822
1823 // FIXME: Don't know how to handle the situation where the small vectors
1824 // aren't all the same size yet.
1825 if (NarrowTy1.isVector() &&
1826 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
1827 return UnableToLegalize;
1828
1829 CmpInst::Predicate Pred
1830 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
1831
1832 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1833 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
1834 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
1835
1836 for (unsigned I = 0; I < NumParts; ++I) {
1837 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1838 DstRegs.push_back(DstReg);
1839
1840 if (MI.getOpcode() == TargetOpcode::G_ICMP)
1841 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1842 else {
1843 MachineInstr *NewCmp
1844 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
1845 NewCmp->setFlags(MI.getFlags());
1846 }
1847 }
1848
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001849 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00001850 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1851 else
1852 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1853
1854 MI.eraseFromParent();
1855 return Legalized;
1856}
1857
1858LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00001859LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
1860 LLT NarrowTy) {
1861 unsigned DstReg = MI.getOperand(0).getReg();
1862 unsigned CondReg = MI.getOperand(1).getReg();
1863
1864 unsigned NumParts = 0;
1865 LLT NarrowTy0, NarrowTy1;
1866
1867 LLT DstTy = MRI.getType(DstReg);
1868 LLT CondTy = MRI.getType(CondReg);
1869 unsigned Size = DstTy.getSizeInBits();
1870
1871 assert(TypeIdx == 0 || CondTy.isVector());
1872
1873 if (TypeIdx == 0) {
1874 NarrowTy0 = NarrowTy;
1875 NarrowTy1 = CondTy;
1876
1877 unsigned NarrowSize = NarrowTy0.getSizeInBits();
1878 // FIXME: Don't know how to handle the situation where the small vectors
1879 // aren't all the same size yet.
1880 if (Size % NarrowSize != 0)
1881 return UnableToLegalize;
1882
1883 NumParts = Size / NarrowSize;
1884
1885 // Need to break down the condition type
1886 if (CondTy.isVector()) {
1887 if (CondTy.getNumElements() == NumParts)
1888 NarrowTy1 = CondTy.getElementType();
1889 else
1890 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
1891 CondTy.getScalarSizeInBits());
1892 }
1893 } else {
1894 NumParts = CondTy.getNumElements();
1895 if (NarrowTy.isVector()) {
1896 // TODO: Handle uneven breakdown.
1897 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
1898 return UnableToLegalize;
1899
1900 return UnableToLegalize;
1901 } else {
1902 NarrowTy0 = DstTy.getElementType();
1903 NarrowTy1 = NarrowTy;
1904 }
1905 }
1906
1907 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
1908 if (CondTy.isVector())
1909 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
1910
1911 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
1912 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
1913
1914 for (unsigned i = 0; i < NumParts; ++i) {
1915 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
1916 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
1917 Src1Regs[i], Src2Regs[i]);
1918 DstRegs.push_back(DstReg);
1919 }
1920
1921 if (NarrowTy0.isVector())
1922 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1923 else
1924 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1925
1926 MI.eraseFromParent();
1927 return Legalized;
1928}
1929
Matt Arsenaultc7bce732019-01-31 02:46:05 +00001930/// Try to break down \p OrigTy into \p NarrowTy sized pieces.
1931///
1932/// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy,
1933/// with any leftover piece as type \p LeftoverTy
1934///
1935/// Returns -1 if the breakdown is not satisfiable.
1936static int getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) {
1937 assert(!LeftoverTy.isValid() && "this is an out argument");
1938
1939 unsigned Size = OrigTy.getSizeInBits();
1940 unsigned NarrowSize = NarrowTy.getSizeInBits();
1941 unsigned NumParts = Size / NarrowSize;
1942 unsigned LeftoverSize = Size - NumParts * NarrowSize;
1943 assert(Size > NarrowSize);
1944
1945 if (LeftoverSize == 0)
1946 return NumParts;
1947
1948 if (NarrowTy.isVector()) {
1949 unsigned EltSize = OrigTy.getScalarSizeInBits();
1950 if (LeftoverSize % EltSize != 0)
1951 return -1;
1952 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
1953 } else {
1954 LeftoverTy = LLT::scalar(LeftoverSize);
1955 }
1956
1957 return NumParts;
1958}
1959
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00001960LegalizerHelper::LegalizeResult
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001961LegalizerHelper::fewerElementsVectorLoadStore(MachineInstr &MI, unsigned TypeIdx,
1962 LLT NarrowTy) {
1963 // FIXME: Don't know how to handle secondary types yet.
1964 if (TypeIdx != 0)
1965 return UnableToLegalize;
1966
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00001967 MachineMemOperand *MMO = *MI.memoperands_begin();
1968
1969 // This implementation doesn't work for atomics. Give up instead of doing
1970 // something invalid.
1971 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
1972 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
1973 return UnableToLegalize;
1974
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001975 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
1976 unsigned ValReg = MI.getOperand(0).getReg();
1977 unsigned AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00001978 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001979
Matt Arsenaultc7bce732019-01-31 02:46:05 +00001980 int NumParts = -1;
1981 LLT LeftoverTy;
1982 SmallVector<unsigned, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001983 if (IsLoad) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00001984 NumParts = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
1985 } else {
1986 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
1987 NarrowLeftoverRegs))
1988 NumParts = NarrowRegs.size();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001989 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00001990
1991 if (NumParts == -1)
1992 return UnableToLegalize;
1993
1994 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
1995
1996 unsigned TotalSize = ValTy.getSizeInBits();
1997
1998 // Split the load/store into PartTy sized pieces starting at Offset. If this
1999 // is a load, return the new registers in ValRegs. For a store, each elements
2000 // of ValRegs should be PartTy. Returns the next offset that needs to be
2001 // handled.
2002 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<unsigned> &ValRegs,
2003 unsigned Offset) -> unsigned {
2004 MachineFunction &MF = MIRBuilder.getMF();
2005 unsigned PartSize = PartTy.getSizeInBits();
2006 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2007 Offset += PartSize, ++Idx) {
2008 unsigned ByteSize = PartSize / 8;
2009 unsigned ByteOffset = Offset / 8;
2010 unsigned NewAddrReg = 0;
2011
2012 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2013
2014 MachineMemOperand *NewMMO =
2015 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2016
2017 if (IsLoad) {
2018 unsigned Dst = MRI.createGenericVirtualRegister(PartTy);
2019 ValRegs.push_back(Dst);
2020 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2021 } else {
2022 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2023 }
2024 }
2025
2026 return Offset;
2027 };
2028
2029 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2030
2031 // Handle the rest of the register if this isn't an even type breakdown.
2032 if (LeftoverTy.isValid())
2033 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2034
2035 if (IsLoad) {
2036 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2037 LeftoverTy, NarrowLeftoverRegs);
2038 }
2039
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002040 MI.eraseFromParent();
2041 return Legalized;
2042}
2043
2044LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002045LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2046 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002047 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002048
2049 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002050 switch (MI.getOpcode()) {
2051 case G_IMPLICIT_DEF:
2052 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2053 case G_AND:
2054 case G_OR:
2055 case G_XOR:
2056 case G_ADD:
2057 case G_SUB:
2058 case G_MUL:
2059 case G_SMULH:
2060 case G_UMULH:
2061 case G_FADD:
2062 case G_FMUL:
2063 case G_FSUB:
2064 case G_FNEG:
2065 case G_FABS:
2066 case G_FDIV:
2067 case G_FREM:
2068 case G_FMA:
2069 case G_FPOW:
2070 case G_FEXP:
2071 case G_FEXP2:
2072 case G_FLOG:
2073 case G_FLOG2:
2074 case G_FLOG10:
2075 case G_FCEIL:
2076 case G_INTRINSIC_ROUND:
2077 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002078 case G_FCOS:
2079 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002080 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002081 case G_BSWAP:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002082 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
2083 case G_ZEXT:
2084 case G_SEXT:
2085 case G_ANYEXT:
2086 case G_FPEXT:
2087 case G_FPTRUNC:
2088 case G_SITOFP:
2089 case G_UITOFP:
2090 case G_FPTOSI:
2091 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002092 case G_INTTOPTR:
2093 case G_PTRTOINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002094 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2095 case G_ICMP:
2096 case G_FCMP:
2097 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002098 case G_SELECT:
2099 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002100 case G_LOAD:
2101 case G_STORE:
2102 return fewerElementsVectorLoadStore(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002103 default:
2104 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002105 }
2106}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002107
2108LegalizerHelper::LegalizeResult
Matt Arsenault211e89d2019-01-27 00:52:51 +00002109LegalizerHelper::narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT NewTy) {
2110 unsigned DstReg = MI.getOperand(0).getReg();
2111 unsigned Src0 = MI.getOperand(1).getReg();
2112 unsigned Src1 = MI.getOperand(2).getReg();
2113 LLT Ty = MRI.getType(DstReg);
2114 if (Ty.isVector())
2115 return UnableToLegalize;
2116
2117 unsigned Size = Ty.getSizeInBits();
2118 unsigned NewSize = Size / 2;
2119 if (Size != 2 * NewSize)
2120 return UnableToLegalize;
2121
2122 LLT HalfTy = LLT::scalar(NewSize);
2123 // TODO: if HalfTy != NewTy, handle the breakdown all at once?
2124
2125 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
2126 unsigned Lo = MRI.createGenericVirtualRegister(HalfTy);
2127 unsigned Hi = MRI.createGenericVirtualRegister(HalfTy);
2128 unsigned ExtLo = MRI.createGenericVirtualRegister(Ty);
2129 unsigned ExtHi = MRI.createGenericVirtualRegister(Ty);
2130 unsigned ShiftedHi = MRI.createGenericVirtualRegister(Ty);
2131
2132 SmallVector<unsigned, 2> Src0Parts;
2133 SmallVector<unsigned, 2> Src1Parts;
2134
2135 extractParts(Src0, HalfTy, 2, Src0Parts);
2136 extractParts(Src1, HalfTy, 2, Src1Parts);
2137
2138 MIRBuilder.buildMul(Lo, Src0Parts[0], Src1Parts[0]);
2139
2140 // TODO: Use smulh or umulh depending on what the target has.
2141 MIRBuilder.buildUMulH(Hi, Src0Parts[1], Src1Parts[1]);
2142
2143 MIRBuilder.buildConstant(ShiftAmt, NewSize);
2144 MIRBuilder.buildAnyExt(ExtHi, Hi);
2145 MIRBuilder.buildShl(ShiftedHi, ExtHi, ShiftAmt);
2146
2147 MIRBuilder.buildZExt(ExtLo, Lo);
2148 MIRBuilder.buildOr(DstReg, ExtLo, ShiftedHi);
2149 MI.eraseFromParent();
2150 return Legalized;
2151}
2152
2153LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002154LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
2155 unsigned Opc = MI.getOpcode();
2156 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00002157 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002158 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00002159 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002160 };
2161 switch (Opc) {
2162 default:
2163 return UnableToLegalize;
2164 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
2165 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00002166 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002167 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00002168 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002169 return Legalized;
2170 }
2171 case TargetOpcode::G_CTLZ: {
2172 unsigned SrcReg = MI.getOperand(1).getReg();
2173 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002174 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00002175 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002176 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
2177 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002178 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
2179 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
2180 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
2181 SrcReg, MIBZero);
2182 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
2183 MIBCtlzZU);
2184 MI.eraseFromParent();
2185 return Legalized;
2186 }
2187 // for now, we do this:
2188 // NewLen = NextPowerOf2(Len);
2189 // x = x | (x >> 1);
2190 // x = x | (x >> 2);
2191 // ...
2192 // x = x | (x >>16);
2193 // x = x | (x >>32); // for 64-bit input
2194 // Upto NewLen/2
2195 // return Len - popcount(x);
2196 //
2197 // Ref: "Hacker's Delight" by Henry Warren
2198 unsigned Op = SrcReg;
2199 unsigned NewLen = PowerOf2Ceil(Len);
2200 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
2201 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
2202 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002203 TargetOpcode::G_OR, {Ty},
2204 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
2205 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002206 Op = MIBOp->getOperand(0).getReg();
2207 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002208 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
2209 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2210 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002211 MI.eraseFromParent();
2212 return Legalized;
2213 }
2214 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
2215 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00002216 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002217 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00002218 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002219 return Legalized;
2220 }
2221 case TargetOpcode::G_CTTZ: {
2222 unsigned SrcReg = MI.getOperand(1).getReg();
2223 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002224 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002225 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
2226 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002227 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
2228 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002229 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
2230 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
2231 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
2232 SrcReg, MIBZero);
2233 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
2234 MIBCttzZU);
2235 MI.eraseFromParent();
2236 return Legalized;
2237 }
2238 // for now, we use: { return popcount(~x & (x - 1)); }
2239 // unless the target has ctlz but not ctpop, in which case we use:
2240 // { return 32 - nlz(~x & (x-1)); }
2241 // Ref: "Hacker's Delight" by Henry Warren
2242 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
2243 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002244 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002245 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002246 TargetOpcode::G_AND, {Ty},
2247 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
2248 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00002249 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
2250 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002251 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
2252 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00002253 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
2254 {MIBCstLen,
2255 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002256 MI.eraseFromParent();
2257 return Legalized;
2258 }
2259 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
2260 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
2261 return Legalized;
2262 }
2263 }
2264}