blob: e2b5082503c608b59a233810b8e9d185438e610b [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
Matt Arsenaultc83b8232019-02-07 17:38:00 +000032/// Try to break down \p OrigTy into \p NarrowTy sized pieces.
33///
34/// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy,
35/// with any leftover piece as type \p LeftoverTy
36///
Matt Arsenaultd3093c22019-02-28 00:16:32 +000037/// Returns -1 in the first element of the pair if the breakdown is not
38/// satisfiable.
39static std::pair<int, int>
40getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) {
Matt Arsenaultc83b8232019-02-07 17:38:00 +000041 assert(!LeftoverTy.isValid() && "this is an out argument");
42
43 unsigned Size = OrigTy.getSizeInBits();
44 unsigned NarrowSize = NarrowTy.getSizeInBits();
45 unsigned NumParts = Size / NarrowSize;
46 unsigned LeftoverSize = Size - NumParts * NarrowSize;
47 assert(Size > NarrowSize);
48
49 if (LeftoverSize == 0)
Matt Arsenaultd3093c22019-02-28 00:16:32 +000050 return {NumParts, 0};
Matt Arsenaultc83b8232019-02-07 17:38:00 +000051
52 if (NarrowTy.isVector()) {
53 unsigned EltSize = OrigTy.getScalarSizeInBits();
54 if (LeftoverSize % EltSize != 0)
Matt Arsenaultd3093c22019-02-28 00:16:32 +000055 return {-1, -1};
Matt Arsenaultc83b8232019-02-07 17:38:00 +000056 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
57 } else {
58 LeftoverTy = LLT::scalar(LeftoverSize);
59 }
60
Matt Arsenaultd3093c22019-02-28 00:16:32 +000061 int NumLeftover = LeftoverSize / LeftoverTy.getSizeInBits();
62 return std::make_pair(NumParts, NumLeftover);
Matt Arsenaultc83b8232019-02-07 17:38:00 +000063}
64
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000065LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000066 GISelChangeObserver &Observer,
67 MachineIRBuilder &Builder)
68 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
69 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000070 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000071 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000072}
73
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000074LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000075 GISelChangeObserver &Observer,
76 MachineIRBuilder &B)
77 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000078 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000079 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000080}
Tim Northover69fa84a2016-10-14 22:18:18 +000081LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000082LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000083 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000084
Aditya Nandakumar1023a2e2019-07-01 17:53:50 +000085 if (MI.getOpcode() == TargetOpcode::G_INTRINSIC ||
86 MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS)
87 return LI.legalizeIntrinsic(MI, MRI, MIRBuilder) ? Legalized
88 : UnableToLegalize;
Daniel Sanders262ed0e2018-01-24 17:17:46 +000089 auto Step = LI.getAction(MI, MRI);
90 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000091 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000092 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000093 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000094 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000095 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000096 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000097 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000098 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000099 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000100 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000101 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000102 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000103 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000104 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000105 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000106 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000107 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000108 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000109 case MoreElements:
110 LLVM_DEBUG(dbgs() << ".. Increase number of elements\n");
111 return moreElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000112 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000113 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000114 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
115 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000116 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000117 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +0000118 return UnableToLegalize;
119 }
120}
121
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000122void LegalizerHelper::extractParts(Register Reg, LLT Ty, int NumParts,
123 SmallVectorImpl<Register> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +0000124 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +0000125 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +0000126 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +0000127}
128
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000129bool LegalizerHelper::extractParts(Register Reg, LLT RegTy,
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000130 LLT MainTy, LLT &LeftoverTy,
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000131 SmallVectorImpl<Register> &VRegs,
132 SmallVectorImpl<Register> &LeftoverRegs) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000133 assert(!LeftoverTy.isValid() && "this is an out argument");
134
135 unsigned RegSize = RegTy.getSizeInBits();
136 unsigned MainSize = MainTy.getSizeInBits();
137 unsigned NumParts = RegSize / MainSize;
138 unsigned LeftoverSize = RegSize - NumParts * MainSize;
139
140 // Use an unmerge when possible.
141 if (LeftoverSize == 0) {
142 for (unsigned I = 0; I < NumParts; ++I)
143 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy));
144 MIRBuilder.buildUnmerge(VRegs, Reg);
145 return true;
146 }
147
148 if (MainTy.isVector()) {
149 unsigned EltSize = MainTy.getScalarSizeInBits();
150 if (LeftoverSize % EltSize != 0)
151 return false;
152 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
153 } else {
154 LeftoverTy = LLT::scalar(LeftoverSize);
155 }
156
157 // For irregular sizes, extract the individual parts.
158 for (unsigned I = 0; I != NumParts; ++I) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000159 Register NewReg = MRI.createGenericVirtualRegister(MainTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000160 VRegs.push_back(NewReg);
161 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I);
162 }
163
164 for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
165 Offset += LeftoverSize) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000166 Register NewReg = MRI.createGenericVirtualRegister(LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000167 LeftoverRegs.push_back(NewReg);
168 MIRBuilder.buildExtract(NewReg, Reg, Offset);
169 }
170
171 return true;
172}
173
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000174void LegalizerHelper::insertParts(Register DstReg,
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000175 LLT ResultTy, LLT PartTy,
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000176 ArrayRef<Register> PartRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000177 LLT LeftoverTy,
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000178 ArrayRef<Register> LeftoverRegs) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000179 if (!LeftoverTy.isValid()) {
180 assert(LeftoverRegs.empty());
181
Matt Arsenault81511e52019-02-05 00:13:44 +0000182 if (!ResultTy.isVector()) {
183 MIRBuilder.buildMerge(DstReg, PartRegs);
184 return;
185 }
186
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000187 if (PartTy.isVector())
188 MIRBuilder.buildConcatVectors(DstReg, PartRegs);
189 else
190 MIRBuilder.buildBuildVector(DstReg, PartRegs);
191 return;
192 }
193
194 unsigned PartSize = PartTy.getSizeInBits();
195 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits();
196
Matt Arsenault3018d182019-06-28 01:47:44 +0000197 Register CurResultReg = MRI.createGenericVirtualRegister(ResultTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000198 MIRBuilder.buildUndef(CurResultReg);
199
200 unsigned Offset = 0;
Matt Arsenault3018d182019-06-28 01:47:44 +0000201 for (Register PartReg : PartRegs) {
202 Register NewResultReg = MRI.createGenericVirtualRegister(ResultTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000203 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset);
204 CurResultReg = NewResultReg;
205 Offset += PartSize;
206 }
207
208 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) {
209 // Use the original output register for the final insert to avoid a copy.
Matt Arsenault3018d182019-06-28 01:47:44 +0000210 Register NewResultReg = (I + 1 == E) ?
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000211 DstReg : MRI.createGenericVirtualRegister(ResultTy);
212
213 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset);
214 CurResultReg = NewResultReg;
215 Offset += LeftoverPartSize;
216 }
217}
218
Tim Northovere0418412017-02-08 23:23:39 +0000219static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
220 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +0000221 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000222 assert((Size == 32 || Size == 64) && "Unsupported size");
223 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +0000224 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000225 assert((Size == 32 || Size == 64) && "Unsupported size");
226 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000227 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000228 assert((Size == 32 || Size == 64) && "Unsupported size");
229 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000230 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000231 assert((Size == 32 || Size == 64) && "Unsupported size");
232 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000233 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
234 assert(Size == 32 && "Unsupported size");
235 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000236 case TargetOpcode::G_FADD:
237 assert((Size == 32 || Size == 64) && "Unsupported size");
238 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000239 case TargetOpcode::G_FSUB:
240 assert((Size == 32 || Size == 64) && "Unsupported size");
241 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000242 case TargetOpcode::G_FMUL:
243 assert((Size == 32 || Size == 64) && "Unsupported size");
244 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000245 case TargetOpcode::G_FDIV:
246 assert((Size == 32 || Size == 64) && "Unsupported size");
247 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Jessica Paquette84bedac2019-01-30 23:46:15 +0000248 case TargetOpcode::G_FEXP:
249 assert((Size == 32 || Size == 64) && "Unsupported size");
250 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32;
Jessica Paquettee7941212019-04-03 16:58:32 +0000251 case TargetOpcode::G_FEXP2:
252 assert((Size == 32 || Size == 64) && "Unsupported size");
253 return Size == 64 ? RTLIB::EXP2_F64 : RTLIB::EXP2_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000254 case TargetOpcode::G_FREM:
255 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
256 case TargetOpcode::G_FPOW:
257 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000258 case TargetOpcode::G_FMA:
259 assert((Size == 32 || Size == 64) && "Unsupported size");
260 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Jessica Paquette7db82d72019-01-28 18:34:18 +0000261 case TargetOpcode::G_FSIN:
262 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
263 return Size == 128 ? RTLIB::SIN_F128
264 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32;
265 case TargetOpcode::G_FCOS:
266 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
267 return Size == 128 ? RTLIB::COS_F128
268 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32;
Jessica Paquettec49428a2019-01-28 19:53:14 +0000269 case TargetOpcode::G_FLOG10:
270 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
271 return Size == 128 ? RTLIB::LOG10_F128
272 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32;
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000273 case TargetOpcode::G_FLOG:
274 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
275 return Size == 128 ? RTLIB::LOG_F128
276 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32;
Jessica Paquette0154bd12019-01-30 21:16:04 +0000277 case TargetOpcode::G_FLOG2:
278 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
279 return Size == 128 ? RTLIB::LOG2_F128
280 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32;
Petar Avramovicfaaa2b52019-06-06 09:02:24 +0000281 case TargetOpcode::G_FCEIL:
282 assert((Size == 32 || Size == 64) && "Unsupported size");
283 return Size == 64 ? RTLIB::CEIL_F64 : RTLIB::CEIL_F32;
284 case TargetOpcode::G_FFLOOR:
285 assert((Size == 32 || Size == 64) && "Unsupported size");
286 return Size == 64 ? RTLIB::FLOOR_F64 : RTLIB::FLOOR_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000287 }
288 llvm_unreachable("Unknown libcall function");
289}
290
Diana Picusfc1675e2017-07-05 12:57:24 +0000291LegalizerHelper::LegalizeResult
292llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
293 const CallLowering::ArgInfo &Result,
294 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000295 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
296 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000297 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000298
Diana Picuse97822e2017-04-24 07:22:31 +0000299 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northovere1a5f662019-08-09 08:26:38 +0000300
301 CallLowering::CallLoweringInfo Info;
302 Info.CallConv = TLI.getLibcallCallingConv(Libcall);
303 Info.Callee = MachineOperand::CreateES(Name);
304 Info.OrigRet = Result;
305 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs));
306 if (!CLI.lowerCall(MIRBuilder, Info))
Diana Picus02e11012017-06-15 10:53:31 +0000307 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000308
Diana Picuse97822e2017-04-24 07:22:31 +0000309 return LegalizerHelper::Legalized;
310}
311
Diana Picus65ed3642018-01-17 13:34:10 +0000312// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000313static LegalizerHelper::LegalizeResult
314simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
315 Type *OpType) {
316 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000317
318 SmallVector<CallLowering::ArgInfo, 3> Args;
319 for (unsigned i = 1; i < MI.getNumOperands(); i++)
320 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000321 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000322 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000323}
324
Amara Emersoncf12c782019-07-19 00:24:45 +0000325LegalizerHelper::LegalizeResult
326llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
327 MachineInstr &MI) {
328 assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
329 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
330
331 SmallVector<CallLowering::ArgInfo, 3> Args;
332 for (unsigned i = 1; i < MI.getNumOperands(); i++) {
333 Register Reg = MI.getOperand(i).getReg();
334
335 // Need derive an IR type for call lowering.
336 LLT OpLLT = MRI.getType(Reg);
337 Type *OpTy = nullptr;
338 if (OpLLT.isPointer())
339 OpTy = Type::getInt8PtrTy(Ctx, OpLLT.getAddressSpace());
340 else
341 OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits());
342 Args.push_back({Reg, OpTy});
343 }
344
345 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
346 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
347 Intrinsic::ID ID = MI.getOperand(0).getIntrinsicID();
348 RTLIB::Libcall RTLibcall;
349 switch (ID) {
350 case Intrinsic::memcpy:
351 RTLibcall = RTLIB::MEMCPY;
352 break;
353 case Intrinsic::memset:
354 RTLibcall = RTLIB::MEMSET;
355 break;
356 case Intrinsic::memmove:
357 RTLibcall = RTLIB::MEMMOVE;
358 break;
359 default:
360 return LegalizerHelper::UnableToLegalize;
361 }
362 const char *Name = TLI.getLibcallName(RTLibcall);
363
364 MIRBuilder.setInstr(MI);
365 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northovere1a5f662019-08-09 08:26:38 +0000366
367 CallLowering::CallLoweringInfo Info;
368 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
369 Info.Callee = MachineOperand::CreateES(Name);
370 Info.OrigRet = CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx));
371 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs));
372 if (!CLI.lowerCall(MIRBuilder, Info))
Amara Emersoncf12c782019-07-19 00:24:45 +0000373 return LegalizerHelper::UnableToLegalize;
374
375 return LegalizerHelper::Legalized;
376}
377
Diana Picus65ed3642018-01-17 13:34:10 +0000378static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
379 Type *FromType) {
380 auto ToMVT = MVT::getVT(ToType);
381 auto FromMVT = MVT::getVT(FromType);
382
383 switch (Opcode) {
384 case TargetOpcode::G_FPEXT:
385 return RTLIB::getFPEXT(FromMVT, ToMVT);
386 case TargetOpcode::G_FPTRUNC:
387 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000388 case TargetOpcode::G_FPTOSI:
389 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
390 case TargetOpcode::G_FPTOUI:
391 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000392 case TargetOpcode::G_SITOFP:
393 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
394 case TargetOpcode::G_UITOFP:
395 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000396 }
397 llvm_unreachable("Unsupported libcall function");
398}
399
400static LegalizerHelper::LegalizeResult
401conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
402 Type *FromType) {
403 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
404 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
405 {{MI.getOperand(1).getReg(), FromType}});
406}
407
Tim Northover69fa84a2016-10-14 22:18:18 +0000408LegalizerHelper::LegalizeResult
409LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000410 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
411 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000412 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000413
Diana Picusfc1675e2017-07-05 12:57:24 +0000414 MIRBuilder.setInstr(MI);
415
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000416 switch (MI.getOpcode()) {
417 default:
418 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000419 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000420 case TargetOpcode::G_UDIV:
421 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000422 case TargetOpcode::G_UREM:
423 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000424 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000425 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
426 if (Status != Legalized)
427 return Status;
428 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000429 }
Diana Picus1314a282017-04-11 10:52:34 +0000430 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000431 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000432 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000433 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000434 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000435 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000436 case TargetOpcode::G_FREM:
437 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000438 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000439 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000440 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000441 case TargetOpcode::G_FLOG2:
Jessica Paquettee7941212019-04-03 16:58:32 +0000442 case TargetOpcode::G_FEXP:
Petar Avramovicfaaa2b52019-06-06 09:02:24 +0000443 case TargetOpcode::G_FEXP2:
444 case TargetOpcode::G_FCEIL:
445 case TargetOpcode::G_FFLOOR: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000446 if (Size > 64) {
447 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
448 return UnableToLegalize;
449 }
Diana Picus02e11012017-06-15 10:53:31 +0000450 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000451 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
452 if (Status != Legalized)
453 return Status;
454 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000455 }
Diana Picus65ed3642018-01-17 13:34:10 +0000456 case TargetOpcode::G_FPEXT: {
457 // FIXME: Support other floating point types (half, fp128 etc)
458 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
459 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
460 if (ToSize != 64 || FromSize != 32)
461 return UnableToLegalize;
462 LegalizeResult Status = conversionLibcall(
463 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
464 if (Status != Legalized)
465 return Status;
466 break;
467 }
468 case TargetOpcode::G_FPTRUNC: {
469 // FIXME: Support other floating point types (half, fp128 etc)
470 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
471 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
472 if (ToSize != 32 || FromSize != 64)
473 return UnableToLegalize;
474 LegalizeResult Status = conversionLibcall(
475 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
476 if (Status != Legalized)
477 return Status;
478 break;
479 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000480 case TargetOpcode::G_FPTOSI:
481 case TargetOpcode::G_FPTOUI: {
482 // FIXME: Support other types
483 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
484 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000485 if ((ToSize != 32 && ToSize != 64) || (FromSize != 32 && FromSize != 64))
Diana Picus4ed0ee72018-01-30 07:54:52 +0000486 return UnableToLegalize;
487 LegalizeResult Status = conversionLibcall(
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000488 MI, MIRBuilder,
489 ToSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx),
Diana Picus4ed0ee72018-01-30 07:54:52 +0000490 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
491 if (Status != Legalized)
492 return Status;
493 break;
494 }
Diana Picus517531e2018-01-30 09:15:17 +0000495 case TargetOpcode::G_SITOFP:
496 case TargetOpcode::G_UITOFP: {
497 // FIXME: Support other types
498 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
499 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic153bd242019-06-20 09:05:02 +0000500 if ((FromSize != 32 && FromSize != 64) || (ToSize != 32 && ToSize != 64))
Diana Picus517531e2018-01-30 09:15:17 +0000501 return UnableToLegalize;
502 LegalizeResult Status = conversionLibcall(
503 MI, MIRBuilder,
504 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
Petar Avramovic153bd242019-06-20 09:05:02 +0000505 FromSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx));
Diana Picus517531e2018-01-30 09:15:17 +0000506 if (Status != Legalized)
507 return Status;
508 break;
509 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000510 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000511
512 MI.eraseFromParent();
513 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000514}
515
Tim Northover69fa84a2016-10-14 22:18:18 +0000516LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
517 unsigned TypeIdx,
518 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000519 MIRBuilder.setInstr(MI);
520
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000521 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
522 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000523
Tim Northover9656f142016-08-04 20:54:13 +0000524 switch (MI.getOpcode()) {
525 default:
526 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000527 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000528 // FIXME: add support for when SizeOp0 isn't an exact multiple of
529 // NarrowSize.
530 if (SizeOp0 % NarrowSize != 0)
531 return UnableToLegalize;
532 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000533
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000534 SmallVector<Register, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000535 for (int i = 0; i < NumParts; ++i)
536 DstRegs.push_back(
537 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000538
Matt Arsenault3018d182019-06-28 01:47:44 +0000539 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000540 if(MRI.getType(DstReg).isVector())
541 MIRBuilder.buildBuildVector(DstReg, DstRegs);
542 else
543 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000544 MI.eraseFromParent();
545 return Legalized;
546 }
Matt Arsenault71872722019-04-10 17:27:53 +0000547 case TargetOpcode::G_CONSTANT: {
548 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
549 const APInt &Val = MI.getOperand(1).getCImm()->getValue();
550 unsigned TotalSize = Ty.getSizeInBits();
551 unsigned NarrowSize = NarrowTy.getSizeInBits();
552 int NumParts = TotalSize / NarrowSize;
553
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000554 SmallVector<Register, 4> PartRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000555 for (int I = 0; I != NumParts; ++I) {
556 unsigned Offset = I * NarrowSize;
557 auto K = MIRBuilder.buildConstant(NarrowTy,
558 Val.lshr(Offset).trunc(NarrowSize));
559 PartRegs.push_back(K.getReg(0));
560 }
561
562 LLT LeftoverTy;
563 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000564 SmallVector<Register, 1> LeftoverRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000565 if (LeftoverBits != 0) {
566 LeftoverTy = LLT::scalar(LeftoverBits);
567 auto K = MIRBuilder.buildConstant(
568 LeftoverTy,
569 Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits));
570 LeftoverRegs.push_back(K.getReg(0));
571 }
572
573 insertParts(MI.getOperand(0).getReg(),
574 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
575
576 MI.eraseFromParent();
577 return Legalized;
578 }
Amara Emerson7bc4fad2019-07-26 23:46:38 +0000579 case TargetOpcode::G_SEXT: {
580 if (TypeIdx != 0)
581 return UnableToLegalize;
582
583 if (NarrowTy.getSizeInBits() != SizeOp0 / 2) {
584 LLVM_DEBUG(dbgs() << "Can't narrow sext to type " << NarrowTy << "\n");
585 return UnableToLegalize;
586 }
587
588 Register SrcReg = MI.getOperand(1).getReg();
589
590 // Shift the sign bit of the low register through the high register.
591 auto ShiftAmt =
592 MIRBuilder.buildConstant(LLT::scalar(64), NarrowTy.getSizeInBits() - 1);
593 auto Shift = MIRBuilder.buildAShr(NarrowTy, SrcReg, ShiftAmt);
594 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {SrcReg, Shift.getReg(0)});
595 MI.eraseFromParent();
596 return Legalized;
597 }
598
Tim Northover9656f142016-08-04 20:54:13 +0000599 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000600 // FIXME: add support for when SizeOp0 isn't an exact multiple of
601 // NarrowSize.
602 if (SizeOp0 % NarrowSize != 0)
603 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000604 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000605 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000606
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000607 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000608 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
609 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
610
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000611 Register CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover0f140c72016-09-09 11:46:34 +0000612 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000613
614 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000615 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
616 Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000617
Tim Northover0f140c72016-09-09 11:46:34 +0000618 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000619 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000620
621 DstRegs.push_back(DstReg);
622 CarryIn = CarryOut;
623 }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000624 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000625 if(MRI.getType(DstReg).isVector())
626 MIRBuilder.buildBuildVector(DstReg, DstRegs);
627 else
628 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000629 MI.eraseFromParent();
630 return Legalized;
631 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000632 case TargetOpcode::G_SUB: {
633 // FIXME: add support for when SizeOp0 isn't an exact multiple of
634 // NarrowSize.
635 if (SizeOp0 % NarrowSize != 0)
636 return UnableToLegalize;
637
638 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
639
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000640 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000641 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
642 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
643
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000644 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
645 Register BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000646 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
647 {Src1Regs[0], Src2Regs[0]});
648 DstRegs.push_back(DstReg);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000649 Register BorrowIn = BorrowOut;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000650 for (int i = 1; i < NumParts; ++i) {
651 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
652 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
653
654 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
655 {Src1Regs[i], Src2Regs[i], BorrowIn});
656
657 DstRegs.push_back(DstReg);
658 BorrowIn = BorrowOut;
659 }
660 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
661 MI.eraseFromParent();
662 return Legalized;
663 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000664 case TargetOpcode::G_MUL:
Petar Avramovic5229f472019-03-11 10:08:44 +0000665 case TargetOpcode::G_UMULH:
Petar Avramovic0b17e592019-03-11 10:00:17 +0000666 return narrowScalarMul(MI, NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +0000667 case TargetOpcode::G_EXTRACT:
668 return narrowScalarExtract(MI, TypeIdx, NarrowTy);
669 case TargetOpcode::G_INSERT:
670 return narrowScalarInsert(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000671 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000672 const auto &MMO = **MI.memoperands_begin();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000673 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000674 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000675 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000676 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000677
678 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000679 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000680 auto &MMO = **MI.memoperands_begin();
681 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
682 MIRBuilder.buildAnyExt(DstReg, TmpReg);
683 MI.eraseFromParent();
684 return Legalized;
685 }
686
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000687 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000688 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000689 case TargetOpcode::G_ZEXTLOAD:
690 case TargetOpcode::G_SEXTLOAD: {
691 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000692 Register DstReg = MI.getOperand(0).getReg();
693 Register PtrReg = MI.getOperand(1).getReg();
Matt Arsenault6614f852019-01-22 19:02:10 +0000694
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000695 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault6614f852019-01-22 19:02:10 +0000696 auto &MMO = **MI.memoperands_begin();
Amara Emersond51adf02019-04-17 22:21:05 +0000697 if (MMO.getSizeInBits() == NarrowSize) {
Matt Arsenault6614f852019-01-22 19:02:10 +0000698 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
699 } else {
700 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
701 : TargetOpcode::G_SEXTLOAD;
702 MIRBuilder.buildInstr(ExtLoad)
703 .addDef(TmpReg)
704 .addUse(PtrReg)
705 .addMemOperand(&MMO);
706 }
707
708 if (ZExt)
709 MIRBuilder.buildZExt(DstReg, TmpReg);
710 else
711 MIRBuilder.buildSExt(DstReg, TmpReg);
712
713 MI.eraseFromParent();
714 return Legalized;
715 }
Justin Bognerfde01042017-01-18 17:29:54 +0000716 case TargetOpcode::G_STORE: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000717 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000718
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000719 Register SrcReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000720 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000721 if (SrcTy.isVector())
722 return UnableToLegalize;
723
724 int NumParts = SizeOp0 / NarrowSize;
725 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
726 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
727 if (SrcTy.isVector() && LeftoverBits != 0)
728 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000729
730 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000731 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000732 auto &MMO = **MI.memoperands_begin();
733 MIRBuilder.buildTrunc(TmpReg, SrcReg);
734 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
735 MI.eraseFromParent();
736 return Legalized;
737 }
738
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000739 return reduceLoadStoreWidth(MI, 0, NarrowTy);
Justin Bognerfde01042017-01-18 17:29:54 +0000740 }
Matt Arsenault81511e52019-02-05 00:13:44 +0000741 case TargetOpcode::G_SELECT:
742 return narrowScalarSelect(MI, TypeIdx, NarrowTy);
Petar Avramovic150fd432018-12-18 11:36:14 +0000743 case TargetOpcode::G_AND:
744 case TargetOpcode::G_OR:
745 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000746 // Legalize bitwise operation:
747 // A = BinOp<Ty> B, C
748 // into:
749 // B1, ..., BN = G_UNMERGE_VALUES B
750 // C1, ..., CN = G_UNMERGE_VALUES C
751 // A1 = BinOp<Ty/N> B1, C2
752 // ...
753 // AN = BinOp<Ty/N> BN, CN
754 // A = G_MERGE_VALUES A1, ..., AN
Matt Arsenault9e0eeba2019-04-10 17:07:56 +0000755 return narrowScalarBasic(MI, TypeIdx, NarrowTy);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000756 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000757 case TargetOpcode::G_SHL:
758 case TargetOpcode::G_LSHR:
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +0000759 case TargetOpcode::G_ASHR:
760 return narrowScalarShift(MI, TypeIdx, NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000761 case TargetOpcode::G_CTLZ:
762 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
763 case TargetOpcode::G_CTTZ:
764 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
765 case TargetOpcode::G_CTPOP:
766 if (TypeIdx != 0)
767 return UnableToLegalize; // TODO
768
769 Observer.changingInstr(MI);
770 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
771 Observer.changedInstr(MI);
772 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000773 case TargetOpcode::G_INTTOPTR:
774 if (TypeIdx != 1)
775 return UnableToLegalize;
776
777 Observer.changingInstr(MI);
778 narrowScalarSrc(MI, NarrowTy, 1);
779 Observer.changedInstr(MI);
780 return Legalized;
781 case TargetOpcode::G_PTRTOINT:
782 if (TypeIdx != 0)
783 return UnableToLegalize;
784
785 Observer.changingInstr(MI);
786 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
787 Observer.changedInstr(MI);
788 return Legalized;
Petar Avramovicbe20e362019-07-09 14:36:17 +0000789 case TargetOpcode::G_PHI: {
790 unsigned NumParts = SizeOp0 / NarrowSize;
791 SmallVector<Register, 2> DstRegs;
792 SmallVector<SmallVector<Register, 2>, 2> SrcRegs;
793 DstRegs.resize(NumParts);
794 SrcRegs.resize(MI.getNumOperands() / 2);
795 Observer.changingInstr(MI);
796 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
797 MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB();
798 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
799 extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts,
800 SrcRegs[i / 2]);
801 }
802 MachineBasicBlock &MBB = *MI.getParent();
803 MIRBuilder.setInsertPt(MBB, MI);
804 for (unsigned i = 0; i < NumParts; ++i) {
805 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
806 MachineInstrBuilder MIB =
807 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
808 for (unsigned j = 1; j < MI.getNumOperands(); j += 2)
809 MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1));
810 }
811 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
812 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
813 Observer.changedInstr(MI);
814 MI.eraseFromParent();
815 return Legalized;
816 }
Matt Arsenault434d6642019-07-15 19:37:34 +0000817 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
818 case TargetOpcode::G_INSERT_VECTOR_ELT: {
819 if (TypeIdx != 2)
820 return UnableToLegalize;
821
822 int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
823 Observer.changingInstr(MI);
824 narrowScalarSrc(MI, NarrowTy, OpIdx);
825 Observer.changedInstr(MI);
826 return Legalized;
827 }
Petar Avramovic1e626352019-07-17 12:08:01 +0000828 case TargetOpcode::G_ICMP: {
829 uint64_t SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
830 if (NarrowSize * 2 != SrcSize)
831 return UnableToLegalize;
832
833 Observer.changingInstr(MI);
834 Register LHSL = MRI.createGenericVirtualRegister(NarrowTy);
835 Register LHSH = MRI.createGenericVirtualRegister(NarrowTy);
836 MIRBuilder.buildUnmerge({LHSL, LHSH}, MI.getOperand(2).getReg());
837
838 Register RHSL = MRI.createGenericVirtualRegister(NarrowTy);
839 Register RHSH = MRI.createGenericVirtualRegister(NarrowTy);
840 MIRBuilder.buildUnmerge({RHSL, RHSH}, MI.getOperand(3).getReg());
841
842 CmpInst::Predicate Pred =
843 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
Amara Emersona1997ce2019-07-24 20:46:42 +0000844 LLT ResTy = MRI.getType(MI.getOperand(0).getReg());
Petar Avramovic1e626352019-07-17 12:08:01 +0000845
846 if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) {
847 MachineInstrBuilder XorL = MIRBuilder.buildXor(NarrowTy, LHSL, RHSL);
848 MachineInstrBuilder XorH = MIRBuilder.buildXor(NarrowTy, LHSH, RHSH);
849 MachineInstrBuilder Or = MIRBuilder.buildOr(NarrowTy, XorL, XorH);
850 MachineInstrBuilder Zero = MIRBuilder.buildConstant(NarrowTy, 0);
851 MIRBuilder.buildICmp(Pred, MI.getOperand(0).getReg(), Or, Zero);
852 } else {
Amara Emersona1997ce2019-07-24 20:46:42 +0000853 MachineInstrBuilder CmpH = MIRBuilder.buildICmp(Pred, ResTy, LHSH, RHSH);
Petar Avramovic1e626352019-07-17 12:08:01 +0000854 MachineInstrBuilder CmpHEQ =
Amara Emersona1997ce2019-07-24 20:46:42 +0000855 MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy, LHSH, RHSH);
Petar Avramovic1e626352019-07-17 12:08:01 +0000856 MachineInstrBuilder CmpLU = MIRBuilder.buildICmp(
Amara Emersona1997ce2019-07-24 20:46:42 +0000857 ICmpInst::getUnsignedPredicate(Pred), ResTy, LHSL, RHSL);
Petar Avramovic1e626352019-07-17 12:08:01 +0000858 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), CmpHEQ, CmpLU, CmpH);
859 }
860 Observer.changedInstr(MI);
861 MI.eraseFromParent();
862 return Legalized;
863 }
Daniel Sanderse9a57c22019-08-09 21:11:20 +0000864 case TargetOpcode::G_SEXT_INREG: {
865 if (TypeIdx != 0)
866 return UnableToLegalize;
867
868 if (!MI.getOperand(2).isImm())
869 return UnableToLegalize;
870 int64_t SizeInBits = MI.getOperand(2).getImm();
871
872 // So long as the new type has more bits than the bits we're extending we
873 // don't need to break it apart.
874 if (NarrowTy.getScalarSizeInBits() >= SizeInBits) {
875 Observer.changingInstr(MI);
876 // We don't lose any non-extension bits by truncating the src and
877 // sign-extending the dst.
878 MachineOperand &MO1 = MI.getOperand(1);
879 auto TruncMIB = MIRBuilder.buildTrunc(NarrowTy, MO1.getReg());
880 MO1.setReg(TruncMIB->getOperand(0).getReg());
881
882 MachineOperand &MO2 = MI.getOperand(0);
883 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
884 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
885 MIRBuilder.buildInstr(TargetOpcode::G_SEXT, {MO2.getReg()}, {DstExt});
886 MO2.setReg(DstExt);
887 Observer.changedInstr(MI);
888 return Legalized;
889 }
890
891 // Break it apart. Components below the extension point are unmodified. The
892 // component containing the extension point becomes a narrower SEXT_INREG.
893 // Components above it are ashr'd from the component containing the
894 // extension point.
895 if (SizeOp0 % NarrowSize != 0)
896 return UnableToLegalize;
897 int NumParts = SizeOp0 / NarrowSize;
898
899 // List the registers where the destination will be scattered.
900 SmallVector<Register, 2> DstRegs;
901 // List the registers where the source will be split.
902 SmallVector<Register, 2> SrcRegs;
903
904 // Create all the temporary registers.
905 for (int i = 0; i < NumParts; ++i) {
906 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
907
908 SrcRegs.push_back(SrcReg);
909 }
910
911 // Explode the big arguments into smaller chunks.
912 MIRBuilder.buildUnmerge(SrcRegs, MI.getOperand(1).getReg());
913
914 Register AshrCstReg =
915 MIRBuilder.buildConstant(NarrowTy, NarrowTy.getScalarSizeInBits() - 1)
916 ->getOperand(0)
917 .getReg();
918 Register FullExtensionReg = 0;
919 Register PartialExtensionReg = 0;
920
921 // Do the operation on each small part.
922 for (int i = 0; i < NumParts; ++i) {
923 if ((i + 1) * NarrowTy.getScalarSizeInBits() < SizeInBits)
924 DstRegs.push_back(SrcRegs[i]);
925 else if (i * NarrowTy.getScalarSizeInBits() > SizeInBits) {
926 assert(PartialExtensionReg &&
927 "Expected to visit partial extension before full");
928 if (FullExtensionReg) {
929 DstRegs.push_back(FullExtensionReg);
930 continue;
931 }
932 DstRegs.push_back(MIRBuilder
933 .buildInstr(TargetOpcode::G_ASHR, {NarrowTy},
934 {PartialExtensionReg, AshrCstReg})
935 ->getOperand(0)
936 .getReg());
937 FullExtensionReg = DstRegs.back();
938 } else {
939 DstRegs.push_back(
940 MIRBuilder
941 .buildInstr(
942 TargetOpcode::G_SEXT_INREG, {NarrowTy},
943 {SrcRegs[i], SizeInBits % NarrowTy.getScalarSizeInBits()})
944 ->getOperand(0)
945 .getReg());
946 PartialExtensionReg = DstRegs.back();
947 }
948 }
949
950 // Gather the destination registers into the final destination.
951 Register DstReg = MI.getOperand(0).getReg();
952 MIRBuilder.buildMerge(DstReg, DstRegs);
953 MI.eraseFromParent();
954 return Legalized;
955 }
Tim Northover9656f142016-08-04 20:54:13 +0000956 }
Tim Northover33b07d62016-07-22 20:03:43 +0000957}
958
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000959void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
960 unsigned OpIdx, unsigned ExtOpcode) {
961 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000962 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000963 MO.setReg(ExtB->getOperand(0).getReg());
964}
965
Matt Arsenault30989e42019-01-22 21:42:11 +0000966void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
967 unsigned OpIdx) {
968 MachineOperand &MO = MI.getOperand(OpIdx);
969 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
970 {MO.getReg()});
971 MO.setReg(ExtB->getOperand(0).getReg());
972}
973
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000974void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
975 unsigned OpIdx, unsigned TruncOpcode) {
976 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000977 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000978 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000979 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000980 MO.setReg(DstExt);
981}
982
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000983void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
984 unsigned OpIdx, unsigned ExtOpcode) {
985 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000986 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000987 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
988 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
989 MO.setReg(DstTrunc);
990}
991
Matt Arsenault18ec3822019-02-11 22:00:39 +0000992void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy,
993 unsigned OpIdx) {
994 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000995 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000996 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
997 MIRBuilder.buildExtract(MO.getReg(), DstExt, 0);
998 MO.setReg(DstExt);
999}
1000
Matt Arsenault26b7e852019-02-19 16:30:19 +00001001void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy,
1002 unsigned OpIdx) {
1003 MachineOperand &MO = MI.getOperand(OpIdx);
1004
1005 LLT OldTy = MRI.getType(MO.getReg());
1006 unsigned OldElts = OldTy.getNumElements();
1007 unsigned NewElts = MoreTy.getNumElements();
1008
1009 unsigned NumParts = NewElts / OldElts;
1010
1011 // Use concat_vectors if the result is a multiple of the number of elements.
1012 if (NumParts * OldElts == NewElts) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001013 SmallVector<Register, 8> Parts;
Matt Arsenault26b7e852019-02-19 16:30:19 +00001014 Parts.push_back(MO.getReg());
1015
Matt Arsenault3018d182019-06-28 01:47:44 +00001016 Register ImpDef = MIRBuilder.buildUndef(OldTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +00001017 for (unsigned I = 1; I != NumParts; ++I)
1018 Parts.push_back(ImpDef);
1019
1020 auto Concat = MIRBuilder.buildConcatVectors(MoreTy, Parts);
1021 MO.setReg(Concat.getReg(0));
1022 return;
1023 }
1024
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001025 Register MoreReg = MRI.createGenericVirtualRegister(MoreTy);
1026 Register ImpDef = MIRBuilder.buildUndef(MoreTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +00001027 MIRBuilder.buildInsert(MoreReg, ImpDef, MO.getReg(), 0);
1028 MO.setReg(MoreReg);
1029}
1030
Tim Northover69fa84a2016-10-14 22:18:18 +00001031LegalizerHelper::LegalizeResult
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001032LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
1033 LLT WideTy) {
1034 if (TypeIdx != 1)
1035 return UnableToLegalize;
1036
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001037 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001038 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault43cbca52019-07-03 23:08:06 +00001039 if (DstTy.isVector())
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001040 return UnableToLegalize;
1041
Matt Arsenaultc9f14f22019-07-01 19:36:10 +00001042 Register Src1 = MI.getOperand(1).getReg();
1043 LLT SrcTy = MRI.getType(Src1);
Matt Arsenault0966dd02019-07-17 20:22:44 +00001044 const int DstSize = DstTy.getSizeInBits();
1045 const int SrcSize = SrcTy.getSizeInBits();
1046 const int WideSize = WideTy.getSizeInBits();
1047 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
Matt Arsenaultc9f14f22019-07-01 19:36:10 +00001048
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001049 unsigned NumOps = MI.getNumOperands();
1050 unsigned NumSrc = MI.getNumOperands() - 1;
1051 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
1052
Matt Arsenault0966dd02019-07-17 20:22:44 +00001053 if (WideSize >= DstSize) {
1054 // Directly pack the bits in the target type.
1055 Register ResultReg = MIRBuilder.buildZExt(WideTy, Src1).getReg(0);
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001056
Matt Arsenault0966dd02019-07-17 20:22:44 +00001057 for (unsigned I = 2; I != NumOps; ++I) {
1058 const unsigned Offset = (I - 1) * PartSize;
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001059
Matt Arsenault0966dd02019-07-17 20:22:44 +00001060 Register SrcReg = MI.getOperand(I).getReg();
1061 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
1062
1063 auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg);
1064
Matt Arsenault5faa5332019-08-01 18:13:16 +00001065 Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg :
Matt Arsenault0966dd02019-07-17 20:22:44 +00001066 MRI.createGenericVirtualRegister(WideTy);
1067
1068 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset);
1069 auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
1070 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
1071 ResultReg = NextResult;
1072 }
1073
1074 if (WideSize > DstSize)
1075 MIRBuilder.buildTrunc(DstReg, ResultReg);
Matt Arsenault5faa5332019-08-01 18:13:16 +00001076 else if (DstTy.isPointer())
1077 MIRBuilder.buildIntToPtr(DstReg, ResultReg);
Matt Arsenault0966dd02019-07-17 20:22:44 +00001078
1079 MI.eraseFromParent();
1080 return Legalized;
1081 }
1082
1083 // Unmerge the original values to the GCD type, and recombine to the next
1084 // multiple greater than the original type.
1085 //
1086 // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6
1087 // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0
1088 // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1
1089 // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2
1090 // %10:_(s6) = G_MERGE_VALUES %4, %5, %6
1091 // %11:_(s6) = G_MERGE_VALUES %7, %8, %9
1092 // %12:_(s12) = G_MERGE_VALUES %10, %11
1093 //
1094 // Padding with undef if necessary:
1095 //
1096 // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6
1097 // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0
1098 // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1
1099 // %7:_(s2) = G_IMPLICIT_DEF
1100 // %8:_(s6) = G_MERGE_VALUES %3, %4, %5
1101 // %9:_(s6) = G_MERGE_VALUES %6, %7, %7
1102 // %10:_(s12) = G_MERGE_VALUES %8, %9
1103
1104 const int GCD = greatestCommonDivisor(SrcSize, WideSize);
1105 LLT GCDTy = LLT::scalar(GCD);
1106
1107 SmallVector<Register, 8> Parts;
1108 SmallVector<Register, 8> NewMergeRegs;
1109 SmallVector<Register, 8> Unmerges;
1110 LLT WideDstTy = LLT::scalar(NumMerge * WideSize);
1111
1112 // Decompose the original operands if they don't evenly divide.
1113 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001114 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenault0966dd02019-07-17 20:22:44 +00001115 if (GCD == SrcSize) {
1116 Unmerges.push_back(SrcReg);
1117 } else {
1118 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg);
1119 for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
1120 Unmerges.push_back(Unmerge.getReg(J));
1121 }
1122 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001123
Matt Arsenault0966dd02019-07-17 20:22:44 +00001124 // Pad with undef to the next size that is a multiple of the requested size.
1125 if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) {
1126 Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0);
1127 for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I)
1128 Unmerges.push_back(UndefReg);
1129 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001130
Matt Arsenault0966dd02019-07-17 20:22:44 +00001131 const int PartsPerGCD = WideSize / GCD;
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001132
Matt Arsenault0966dd02019-07-17 20:22:44 +00001133 // Build merges of each piece.
1134 ArrayRef<Register> Slicer(Unmerges);
1135 for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) {
1136 auto Merge = MIRBuilder.buildMerge(WideTy, Slicer.take_front(PartsPerGCD));
1137 NewMergeRegs.push_back(Merge.getReg(0));
1138 }
1139
1140 // A truncate may be necessary if the requested type doesn't evenly divide the
1141 // original result type.
1142 if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) {
1143 MIRBuilder.buildMerge(DstReg, NewMergeRegs);
1144 } else {
1145 auto FinalMerge = MIRBuilder.buildMerge(WideDstTy, NewMergeRegs);
1146 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001147 }
1148
1149 MI.eraseFromParent();
1150 return Legalized;
1151}
1152
1153LegalizerHelper::LegalizeResult
1154LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
1155 LLT WideTy) {
1156 if (TypeIdx != 0)
1157 return UnableToLegalize;
1158
1159 unsigned NumDst = MI.getNumOperands() - 1;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001160 Register SrcReg = MI.getOperand(NumDst).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001161 LLT SrcTy = MRI.getType(SrcReg);
1162 if (!SrcTy.isScalar())
1163 return UnableToLegalize;
1164
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001165 Register Dst0Reg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001166 LLT DstTy = MRI.getType(Dst0Reg);
1167 if (!DstTy.isScalar())
1168 return UnableToLegalize;
1169
1170 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
1171 LLT NewSrcTy = LLT::scalar(NewSrcSize);
1172 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
1173
1174 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
1175
1176 for (unsigned I = 1; I != NumDst; ++I) {
1177 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
1178 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
1179 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
1180 }
1181
1182 Observer.changingInstr(MI);
1183
1184 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
1185 for (unsigned I = 0; I != NumDst; ++I)
1186 widenScalarDst(MI, WideTy, I);
1187
1188 Observer.changedInstr(MI);
1189
1190 return Legalized;
1191}
1192
1193LegalizerHelper::LegalizeResult
Matt Arsenault1cf71362019-02-12 14:54:52 +00001194LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
1195 LLT WideTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001196 Register DstReg = MI.getOperand(0).getReg();
1197 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00001198 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenaultfbe92a52019-02-18 22:39:27 +00001199
1200 LLT DstTy = MRI.getType(DstReg);
1201 unsigned Offset = MI.getOperand(2).getImm();
1202
1203 if (TypeIdx == 0) {
1204 if (SrcTy.isVector() || DstTy.isVector())
1205 return UnableToLegalize;
1206
1207 SrcOp Src(SrcReg);
1208 if (SrcTy.isPointer()) {
1209 // Extracts from pointers can be handled only if they are really just
1210 // simple integers.
1211 const DataLayout &DL = MIRBuilder.getDataLayout();
1212 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
1213 return UnableToLegalize;
1214
1215 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
1216 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
1217 SrcTy = SrcAsIntTy;
1218 }
1219
1220 if (DstTy.isPointer())
1221 return UnableToLegalize;
1222
1223 if (Offset == 0) {
1224 // Avoid a shift in the degenerate case.
1225 MIRBuilder.buildTrunc(DstReg,
1226 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
1227 MI.eraseFromParent();
1228 return Legalized;
1229 }
1230
1231 // Do a shift in the source type.
1232 LLT ShiftTy = SrcTy;
1233 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
1234 Src = MIRBuilder.buildAnyExt(WideTy, Src);
1235 ShiftTy = WideTy;
1236 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits())
1237 return UnableToLegalize;
1238
1239 auto LShr = MIRBuilder.buildLShr(
1240 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
1241 MIRBuilder.buildTrunc(DstReg, LShr);
1242 MI.eraseFromParent();
1243 return Legalized;
1244 }
1245
Matt Arsenault8f624ab2019-04-22 15:10:42 +00001246 if (SrcTy.isScalar()) {
1247 Observer.changingInstr(MI);
1248 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1249 Observer.changedInstr(MI);
1250 return Legalized;
1251 }
1252
Matt Arsenault1cf71362019-02-12 14:54:52 +00001253 if (!SrcTy.isVector())
1254 return UnableToLegalize;
1255
Matt Arsenault1cf71362019-02-12 14:54:52 +00001256 if (DstTy != SrcTy.getElementType())
1257 return UnableToLegalize;
1258
Matt Arsenault1cf71362019-02-12 14:54:52 +00001259 if (Offset % SrcTy.getScalarSizeInBits() != 0)
1260 return UnableToLegalize;
1261
1262 Observer.changingInstr(MI);
1263 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1264
1265 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
1266 Offset);
1267 widenScalarDst(MI, WideTy.getScalarType(), 0);
1268 Observer.changedInstr(MI);
1269 return Legalized;
1270}
1271
1272LegalizerHelper::LegalizeResult
1273LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
1274 LLT WideTy) {
1275 if (TypeIdx != 0)
1276 return UnableToLegalize;
1277 Observer.changingInstr(MI);
1278 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1279 widenScalarDst(MI, WideTy);
1280 Observer.changedInstr(MI);
1281 return Legalized;
1282}
1283
1284LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001285LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +00001286 MIRBuilder.setInstr(MI);
1287
Tim Northover32335812016-08-04 18:35:11 +00001288 switch (MI.getOpcode()) {
1289 default:
1290 return UnableToLegalize;
Matt Arsenault1cf71362019-02-12 14:54:52 +00001291 case TargetOpcode::G_EXTRACT:
1292 return widenScalarExtract(MI, TypeIdx, WideTy);
1293 case TargetOpcode::G_INSERT:
1294 return widenScalarInsert(MI, TypeIdx, WideTy);
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001295 case TargetOpcode::G_MERGE_VALUES:
1296 return widenScalarMergeValues(MI, TypeIdx, WideTy);
1297 case TargetOpcode::G_UNMERGE_VALUES:
1298 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001299 case TargetOpcode::G_UADDO:
1300 case TargetOpcode::G_USUBO: {
1301 if (TypeIdx == 1)
1302 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001303 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1304 {MI.getOperand(2).getReg()});
1305 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1306 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001307 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
1308 ? TargetOpcode::G_ADD
1309 : TargetOpcode::G_SUB;
1310 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001311 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001312 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
1313 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
1314 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001315 TargetOpcode::G_AND, {WideTy},
1316 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001317 // There is no overflow if the AndOp is the same as NewOp.
1318 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1319 AndOp);
1320 // Now trunc the NewOp to the original result.
1321 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1322 MI.eraseFromParent();
1323 return Legalized;
1324 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001325 case TargetOpcode::G_CTTZ:
1326 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1327 case TargetOpcode::G_CTLZ:
1328 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1329 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001330 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001331 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001332 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001333 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001334 return Legalized;
1335 }
1336
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001337 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001338
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001339 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001340 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1341 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001342 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1343 // The count is the same in the larger type except if the original
1344 // value was zero. This can be handled by setting the bit just off
1345 // the top of the original type.
1346 auto TopBit =
1347 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001348 MIBSrc = MIRBuilder.buildOr(
1349 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001350 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001351
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001352 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001353 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001354 // This is already the correct result for CTPOP and CTTZs
1355 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1356 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1357 // The correct result is NewOp - (Difference in widety and current ty).
1358 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001359 MIBNewOp = MIRBuilder.buildInstr(
1360 TargetOpcode::G_SUB, {WideTy},
1361 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001362 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001363
1364 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1365 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001366 return Legalized;
1367 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001368 case TargetOpcode::G_BSWAP: {
1369 Observer.changingInstr(MI);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001370 Register DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001371
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001372 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
1373 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
1374 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001375 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1376
1377 MI.getOperand(0).setReg(DstExt);
1378
1379 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1380
1381 LLT Ty = MRI.getType(DstReg);
1382 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1383 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1384 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1385 .addDef(ShrReg)
1386 .addUse(DstExt)
1387 .addUse(ShiftAmtReg);
1388
1389 MIRBuilder.buildTrunc(DstReg, ShrReg);
1390 Observer.changedInstr(MI);
1391 return Legalized;
1392 }
Tim Northover61c16142016-08-04 21:39:49 +00001393 case TargetOpcode::G_ADD:
1394 case TargetOpcode::G_AND:
1395 case TargetOpcode::G_MUL:
1396 case TargetOpcode::G_OR:
1397 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001398 case TargetOpcode::G_SUB:
Matt Arsenault1cf71362019-02-12 14:54:52 +00001399 // Perform operation at larger width (any extension is fines here, high bits
Tim Northover32335812016-08-04 18:35:11 +00001400 // don't affect the result) and then truncate the result back to the
1401 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001402 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001403 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1404 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1405 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001406 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001407 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001408
Roman Tereshin6d266382018-05-09 21:43:30 +00001409 case TargetOpcode::G_SHL:
Matt Arsenault012ecbb2019-05-16 04:08:46 +00001410 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001411
1412 if (TypeIdx == 0) {
1413 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1414 widenScalarDst(MI, WideTy);
1415 } else {
1416 assert(TypeIdx == 1);
1417 // The "number of bits to shift" operand must preserve its value as an
1418 // unsigned integer:
1419 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1420 }
1421
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001422 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001423 return Legalized;
1424
Tim Northover7a753d92016-08-26 17:46:06 +00001425 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001426 case TargetOpcode::G_SREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001427 case TargetOpcode::G_SMIN:
1428 case TargetOpcode::G_SMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001429 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001430 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1431 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1432 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001433 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001434 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001435
Roman Tereshin6d266382018-05-09 21:43:30 +00001436 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001437 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001438 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001439
1440 if (TypeIdx == 0) {
1441 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1442 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1443
1444 widenScalarSrc(MI, WideTy, 1, CvtOp);
1445 widenScalarDst(MI, WideTy);
1446 } else {
1447 assert(TypeIdx == 1);
1448 // The "number of bits to shift" operand must preserve its value as an
1449 // unsigned integer:
1450 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1451 }
1452
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001453 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001454 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001455 case TargetOpcode::G_UDIV:
1456 case TargetOpcode::G_UREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001457 case TargetOpcode::G_UMIN:
1458 case TargetOpcode::G_UMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001459 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001460 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1461 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1462 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001463 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001464 return Legalized;
1465
1466 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001467 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001468 if (TypeIdx == 0) {
1469 // Perform operation at larger width (any extension is fine here, high
1470 // bits don't affect the result) and then truncate the result back to the
1471 // original type.
1472 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1473 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1474 widenScalarDst(MI, WideTy);
1475 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001476 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001477 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001478 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001479 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001480 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001481 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001482
Ahmed Bougachab6137062017-01-23 21:10:14 +00001483 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001484 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001485 if (TypeIdx != 0)
1486 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001487 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001488 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001489 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001490 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001491
Ahmed Bougachad2948232017-01-20 01:37:24 +00001492 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001493 if (TypeIdx != 1)
1494 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001495 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001496 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001497 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001498 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001499
1500 case TargetOpcode::G_UITOFP:
1501 if (TypeIdx != 1)
1502 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001503 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001504 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001505 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001506 return Legalized;
1507
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001508 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001509 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001510 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001511 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001512 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001513 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001514 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001515
Tim Northover3c73e362016-08-23 18:20:09 +00001516 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001517 if (TypeIdx != 0)
1518 return UnableToLegalize;
1519
1520 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1521 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001522 return UnableToLegalize;
1523
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001524 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001525
1526 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1527 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1528 widenScalarSrc(MI, WideTy, 0, ExtType);
1529
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001530 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001531 return Legalized;
1532 }
Tim Northoverea904f92016-08-19 22:40:00 +00001533 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001534 MachineOperand &SrcMO = MI.getOperand(1);
1535 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1536 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001537 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001538 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1539
1540 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001541 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001542 return Legalized;
1543 }
Tim Northovera11be042016-08-19 22:40:08 +00001544 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001545 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001546 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001547 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001548 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001549 switch (WideTy.getSizeInBits()) {
1550 case 32:
Matt Arsenault996c6662019-02-12 14:54:54 +00001551 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
1552 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001553 break;
1554 case 64:
Matt Arsenault996c6662019-02-12 14:54:54 +00001555 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
1556 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001557 break;
1558 default:
Matt Arsenault996c6662019-02-12 14:54:54 +00001559 return UnableToLegalize;
Tim Northover6cd4b232016-08-23 21:01:26 +00001560 }
Matt Arsenault996c6662019-02-12 14:54:54 +00001561
1562 assert(!LosesInfo && "extend should always be lossless");
1563
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001564 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001565 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1566
1567 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001568 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001569 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001570 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001571 case TargetOpcode::G_IMPLICIT_DEF: {
1572 Observer.changingInstr(MI);
1573 widenScalarDst(MI, WideTy);
1574 Observer.changedInstr(MI);
1575 return Legalized;
1576 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001577 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001578 Observer.changingInstr(MI);
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +00001579 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001580 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001581 return Legalized;
1582
1583 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001584 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001585 if (TypeIdx == 0)
1586 widenScalarDst(MI, WideTy);
1587 else {
1588 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1589 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001590 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001591 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001592 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001593
1594 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001595 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001596 if (TypeIdx == 0)
1597 widenScalarDst(MI, WideTy);
1598 else {
1599 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1600 MI.getOperand(1).getPredicate()))
1601 ? TargetOpcode::G_SEXT
1602 : TargetOpcode::G_ZEXT;
1603 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1604 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1605 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001606 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001607 return Legalized;
1608
1609 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001610 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001611 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001612 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001613 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001614 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001615
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001616 case TargetOpcode::G_PHI: {
1617 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001618
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001619 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001620 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1621 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1622 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1623 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001624 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001625
1626 MachineBasicBlock &MBB = *MI.getParent();
1627 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1628 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001629 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001630 return Legalized;
1631 }
Matt Arsenault63786292019-01-22 20:38:15 +00001632 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1633 if (TypeIdx == 0) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001634 Register VecReg = MI.getOperand(1).getReg();
Matt Arsenault63786292019-01-22 20:38:15 +00001635 LLT VecTy = MRI.getType(VecReg);
1636 Observer.changingInstr(MI);
1637
1638 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1639 WideTy.getSizeInBits()),
1640 1, TargetOpcode::G_SEXT);
1641
1642 widenScalarDst(MI, WideTy, 0);
1643 Observer.changedInstr(MI);
1644 return Legalized;
1645 }
1646
Amara Emersoncbd86d82018-10-25 14:04:54 +00001647 if (TypeIdx != 2)
1648 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001649 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001650 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001651 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001652 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001653 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001654 case TargetOpcode::G_FADD:
1655 case TargetOpcode::G_FMUL:
1656 case TargetOpcode::G_FSUB:
1657 case TargetOpcode::G_FMA:
1658 case TargetOpcode::G_FNEG:
1659 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001660 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001661 case TargetOpcode::G_FMINNUM:
1662 case TargetOpcode::G_FMAXNUM:
1663 case TargetOpcode::G_FMINNUM_IEEE:
1664 case TargetOpcode::G_FMAXNUM_IEEE:
1665 case TargetOpcode::G_FMINIMUM:
1666 case TargetOpcode::G_FMAXIMUM:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001667 case TargetOpcode::G_FDIV:
1668 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001669 case TargetOpcode::G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00001670 case TargetOpcode::G_FFLOOR:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001671 case TargetOpcode::G_FCOS:
1672 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001673 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001674 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001675 case TargetOpcode::G_FLOG2:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00001676 case TargetOpcode::G_FRINT:
Jessica Paquetteba557672019-04-25 16:44:40 +00001677 case TargetOpcode::G_FNEARBYINT:
Jessica Paquette22457f82019-01-30 21:03:52 +00001678 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001679 case TargetOpcode::G_FEXP:
Jessica Paquettee7941212019-04-03 16:58:32 +00001680 case TargetOpcode::G_FEXP2:
Jessica Paquettedfd87f62019-04-19 16:28:08 +00001681 case TargetOpcode::G_FPOW:
Jessica Paquette56342642019-04-23 18:20:44 +00001682 case TargetOpcode::G_INTRINSIC_TRUNC:
Jessica Paquette3cc6d1f2019-04-23 21:11:57 +00001683 case TargetOpcode::G_INTRINSIC_ROUND:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001684 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001685 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001686
1687 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1688 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1689
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001690 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1691 Observer.changedInstr(MI);
1692 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001693 case TargetOpcode::G_INTTOPTR:
1694 if (TypeIdx != 1)
1695 return UnableToLegalize;
1696
1697 Observer.changingInstr(MI);
1698 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1699 Observer.changedInstr(MI);
1700 return Legalized;
1701 case TargetOpcode::G_PTRTOINT:
1702 if (TypeIdx != 0)
1703 return UnableToLegalize;
1704
1705 Observer.changingInstr(MI);
1706 widenScalarDst(MI, WideTy, 0);
1707 Observer.changedInstr(MI);
1708 return Legalized;
Matt Arsenaultbd791b52019-07-08 13:48:06 +00001709 case TargetOpcode::G_BUILD_VECTOR: {
1710 Observer.changingInstr(MI);
1711
1712 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType();
1713 for (int I = 1, E = MI.getNumOperands(); I != E; ++I)
1714 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT);
1715
1716 // Avoid changing the result vector type if the source element type was
1717 // requested.
1718 if (TypeIdx == 1) {
1719 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
1720 MI.setDesc(TII.get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
1721 } else {
1722 widenScalarDst(MI, WideTy, 0);
1723 }
1724
1725 Observer.changedInstr(MI);
1726 return Legalized;
1727 }
Daniel Sanderse9a57c22019-08-09 21:11:20 +00001728 case TargetOpcode::G_SEXT_INREG:
1729 if (TypeIdx != 0)
1730 return UnableToLegalize;
1731
1732 Observer.changingInstr(MI);
1733 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1734 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_TRUNC);
1735 Observer.changedInstr(MI);
1736 return Legalized;
Tim Northover32335812016-08-04 18:35:11 +00001737 }
Tim Northover33b07d62016-07-22 20:03:43 +00001738}
1739
Tim Northover69fa84a2016-10-14 22:18:18 +00001740LegalizerHelper::LegalizeResult
1741LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001742 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001743 MIRBuilder.setInstr(MI);
1744
1745 switch(MI.getOpcode()) {
1746 default:
1747 return UnableToLegalize;
1748 case TargetOpcode::G_SREM:
1749 case TargetOpcode::G_UREM: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001750 Register QuotReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001751 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001752 .addDef(QuotReg)
1753 .addUse(MI.getOperand(1).getReg())
1754 .addUse(MI.getOperand(2).getReg());
1755
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001756 Register ProdReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001757 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1758 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1759 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001760 MI.eraseFromParent();
1761 return Legalized;
1762 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001763 case TargetOpcode::G_SMULO:
1764 case TargetOpcode::G_UMULO: {
1765 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1766 // result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001767 Register Res = MI.getOperand(0).getReg();
1768 Register Overflow = MI.getOperand(1).getReg();
1769 Register LHS = MI.getOperand(2).getReg();
1770 Register RHS = MI.getOperand(3).getReg();
Tim Northover0a9b2792017-02-08 21:22:15 +00001771
1772 MIRBuilder.buildMul(Res, LHS, RHS);
1773
1774 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1775 ? TargetOpcode::G_SMULH
1776 : TargetOpcode::G_UMULH;
1777
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001778 Register HiPart = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001779 MIRBuilder.buildInstr(Opcode)
1780 .addDef(HiPart)
1781 .addUse(LHS)
1782 .addUse(RHS);
1783
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001784 Register Zero = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001785 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001786
1787 // For *signed* multiply, overflow is detected by checking:
1788 // (hi != (lo >> bitwidth-1))
1789 if (Opcode == TargetOpcode::G_SMULH) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001790 Register Shifted = MRI.createGenericVirtualRegister(Ty);
1791 Register ShiftAmt = MRI.createGenericVirtualRegister(Ty);
Amara Emerson9de62132018-01-03 04:56:56 +00001792 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1793 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1794 .addDef(Shifted)
1795 .addUse(Res)
1796 .addUse(ShiftAmt);
1797 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1798 } else {
1799 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1800 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001801 MI.eraseFromParent();
1802 return Legalized;
1803 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001804 case TargetOpcode::G_FNEG: {
1805 // TODO: Handle vector types once we are able to
1806 // represent them.
1807 if (Ty.isVector())
1808 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001809 Register Res = MI.getOperand(0).getReg();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001810 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001811 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001812 switch (Ty.getSizeInBits()) {
1813 case 16:
1814 ZeroTy = Type::getHalfTy(Ctx);
1815 break;
1816 case 32:
1817 ZeroTy = Type::getFloatTy(Ctx);
1818 break;
1819 case 64:
1820 ZeroTy = Type::getDoubleTy(Ctx);
1821 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001822 case 128:
1823 ZeroTy = Type::getFP128Ty(Ctx);
1824 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001825 default:
1826 llvm_unreachable("unexpected floating-point type");
1827 }
1828 ConstantFP &ZeroForNegation =
1829 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001830 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001831 Register SubByReg = MI.getOperand(1).getReg();
1832 Register ZeroReg = Zero->getOperand(0).getReg();
Michael Bergd573aa02019-04-18 18:48:57 +00001833 MIRBuilder.buildInstr(TargetOpcode::G_FSUB, {Res}, {ZeroReg, SubByReg},
Matt Arsenault5a321b82019-06-17 23:48:43 +00001834 MI.getFlags());
Volkan Keles5698b2a2017-03-08 18:09:14 +00001835 MI.eraseFromParent();
1836 return Legalized;
1837 }
Volkan Keles225921a2017-03-10 21:25:09 +00001838 case TargetOpcode::G_FSUB: {
1839 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1840 // First, check if G_FNEG is marked as Lower. If so, we may
1841 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001842 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001843 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001844 Register Res = MI.getOperand(0).getReg();
1845 Register LHS = MI.getOperand(1).getReg();
1846 Register RHS = MI.getOperand(2).getReg();
1847 Register Neg = MRI.createGenericVirtualRegister(Ty);
Volkan Keles225921a2017-03-10 21:25:09 +00001848 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
Michael Bergd573aa02019-04-18 18:48:57 +00001849 MIRBuilder.buildInstr(TargetOpcode::G_FADD, {Res}, {LHS, Neg}, MI.getFlags());
Volkan Keles225921a2017-03-10 21:25:09 +00001850 MI.eraseFromParent();
1851 return Legalized;
1852 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001853 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001854 Register OldValRes = MI.getOperand(0).getReg();
1855 Register SuccessRes = MI.getOperand(1).getReg();
1856 Register Addr = MI.getOperand(2).getReg();
1857 Register CmpVal = MI.getOperand(3).getReg();
1858 Register NewVal = MI.getOperand(4).getReg();
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001859 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1860 **MI.memoperands_begin());
1861 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1862 MI.eraseFromParent();
1863 return Legalized;
1864 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001865 case TargetOpcode::G_LOAD:
1866 case TargetOpcode::G_SEXTLOAD:
1867 case TargetOpcode::G_ZEXTLOAD: {
1868 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001869 Register DstReg = MI.getOperand(0).getReg();
1870 Register PtrReg = MI.getOperand(1).getReg();
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001871 LLT DstTy = MRI.getType(DstReg);
1872 auto &MMO = **MI.memoperands_begin();
1873
Amara Emersonc8351642019-08-02 23:44:24 +00001874 if (DstTy.getSizeInBits() == MMO.getSizeInBits()) {
1875 if (MI.getOpcode() == TargetOpcode::G_LOAD) {
1876 // This load needs splitting into power of 2 sized loads.
1877 if (DstTy.isVector())
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001878 return UnableToLegalize;
Amara Emersonc8351642019-08-02 23:44:24 +00001879 if (isPowerOf2_32(DstTy.getSizeInBits()))
1880 return UnableToLegalize; // Don't know what we're being asked to do.
1881
1882 // Our strategy here is to generate anyextending loads for the smaller
1883 // types up to next power-2 result type, and then combine the two larger
1884 // result values together, before truncating back down to the non-pow-2
1885 // type.
1886 // E.g. v1 = i24 load =>
1887 // v2 = i32 load (2 byte)
1888 // v3 = i32 load (1 byte)
1889 // v4 = i32 shl v3, 16
1890 // v5 = i32 or v4, v2
1891 // v1 = i24 trunc v5
1892 // By doing this we generate the correct truncate which should get
1893 // combined away as an artifact with a matching extend.
1894 uint64_t LargeSplitSize = PowerOf2Floor(DstTy.getSizeInBits());
1895 uint64_t SmallSplitSize = DstTy.getSizeInBits() - LargeSplitSize;
1896
1897 MachineFunction &MF = MIRBuilder.getMF();
1898 MachineMemOperand *LargeMMO =
1899 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
1900 MachineMemOperand *SmallMMO = MF.getMachineMemOperand(
1901 &MMO, LargeSplitSize / 8, SmallSplitSize / 8);
1902
1903 LLT PtrTy = MRI.getType(PtrReg);
1904 unsigned AnyExtSize = NextPowerOf2(DstTy.getSizeInBits());
1905 LLT AnyExtTy = LLT::scalar(AnyExtSize);
1906 Register LargeLdReg = MRI.createGenericVirtualRegister(AnyExtTy);
1907 Register SmallLdReg = MRI.createGenericVirtualRegister(AnyExtTy);
1908 auto LargeLoad =
1909 MIRBuilder.buildLoad(LargeLdReg, PtrReg, *LargeMMO);
1910
1911 auto OffsetCst =
1912 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8);
1913 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy);
1914 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0));
1915 auto SmallLoad = MIRBuilder.buildLoad(SmallLdReg, SmallPtr.getReg(0),
1916 *SmallMMO);
1917
1918 auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
1919 auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
1920 auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
1921 MIRBuilder.buildTrunc(DstReg, {Or.getReg(0)});
1922 MI.eraseFromParent();
1923 return Legalized;
1924 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001925 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1926 MI.eraseFromParent();
1927 return Legalized;
1928 }
1929
1930 if (DstTy.isScalar()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001931 Register TmpReg =
Amara Emersond51adf02019-04-17 22:21:05 +00001932 MRI.createGenericVirtualRegister(LLT::scalar(MMO.getSizeInBits()));
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001933 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1934 switch (MI.getOpcode()) {
1935 default:
1936 llvm_unreachable("Unexpected opcode");
1937 case TargetOpcode::G_LOAD:
1938 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1939 break;
1940 case TargetOpcode::G_SEXTLOAD:
1941 MIRBuilder.buildSExt(DstReg, TmpReg);
1942 break;
1943 case TargetOpcode::G_ZEXTLOAD:
1944 MIRBuilder.buildZExt(DstReg, TmpReg);
1945 break;
1946 }
1947 MI.eraseFromParent();
1948 return Legalized;
1949 }
1950
1951 return UnableToLegalize;
1952 }
Amara Emersonc8351642019-08-02 23:44:24 +00001953 case TargetOpcode::G_STORE: {
1954 // Lower a non-power of 2 store into multiple pow-2 stores.
1955 // E.g. split an i24 store into an i16 store + i8 store.
1956 // We do this by first extending the stored value to the next largest power
1957 // of 2 type, and then using truncating stores to store the components.
1958 // By doing this, likewise with G_LOAD, generate an extend that can be
1959 // artifact-combined away instead of leaving behind extracts.
1960 Register SrcReg = MI.getOperand(0).getReg();
1961 Register PtrReg = MI.getOperand(1).getReg();
1962 LLT SrcTy = MRI.getType(SrcReg);
1963 MachineMemOperand &MMO = **MI.memoperands_begin();
1964 if (SrcTy.getSizeInBits() != MMO.getSizeInBits())
1965 return UnableToLegalize;
1966 if (SrcTy.isVector())
1967 return UnableToLegalize;
1968 if (isPowerOf2_32(SrcTy.getSizeInBits()))
1969 return UnableToLegalize; // Don't know what we're being asked to do.
1970
1971 // Extend to the next pow-2.
1972 const LLT ExtendTy = LLT::scalar(NextPowerOf2(SrcTy.getSizeInBits()));
1973 auto ExtVal = MIRBuilder.buildAnyExt(ExtendTy, SrcReg);
1974
1975 // Obtain the smaller value by shifting away the larger value.
1976 uint64_t LargeSplitSize = PowerOf2Floor(SrcTy.getSizeInBits());
1977 uint64_t SmallSplitSize = SrcTy.getSizeInBits() - LargeSplitSize;
1978 auto ShiftAmt = MIRBuilder.buildConstant(ExtendTy, LargeSplitSize);
1979 auto SmallVal = MIRBuilder.buildLShr(ExtendTy, ExtVal, ShiftAmt);
1980
1981 // Generate the GEP and truncating stores.
1982 LLT PtrTy = MRI.getType(PtrReg);
1983 auto OffsetCst =
1984 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8);
1985 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy);
1986 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0));
1987
1988 MachineFunction &MF = MIRBuilder.getMF();
1989 MachineMemOperand *LargeMMO =
1990 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
1991 MachineMemOperand *SmallMMO =
1992 MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8);
1993 MIRBuilder.buildStore(ExtVal.getReg(0), PtrReg, *LargeMMO);
1994 MIRBuilder.buildStore(SmallVal.getReg(0), SmallPtr.getReg(0), *SmallMMO);
1995 MI.eraseFromParent();
1996 return Legalized;
1997 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001998 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1999 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2000 case TargetOpcode::G_CTLZ:
2001 case TargetOpcode::G_CTTZ:
2002 case TargetOpcode::G_CTPOP:
2003 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicbd395692019-02-26 17:22:42 +00002004 case G_UADDO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002005 Register Res = MI.getOperand(0).getReg();
2006 Register CarryOut = MI.getOperand(1).getReg();
2007 Register LHS = MI.getOperand(2).getReg();
2008 Register RHS = MI.getOperand(3).getReg();
Petar Avramovicbd395692019-02-26 17:22:42 +00002009
2010 MIRBuilder.buildAdd(Res, LHS, RHS);
2011 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS);
2012
2013 MI.eraseFromParent();
2014 return Legalized;
2015 }
Petar Avramovicb8276f22018-12-17 12:31:07 +00002016 case G_UADDE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002017 Register Res = MI.getOperand(0).getReg();
2018 Register CarryOut = MI.getOperand(1).getReg();
2019 Register LHS = MI.getOperand(2).getReg();
2020 Register RHS = MI.getOperand(3).getReg();
2021 Register CarryIn = MI.getOperand(4).getReg();
Petar Avramovicb8276f22018-12-17 12:31:07 +00002022
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002023 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
2024 Register ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00002025
2026 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
2027 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
2028 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
2029 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
2030
2031 MI.eraseFromParent();
2032 return Legalized;
2033 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00002034 case G_USUBO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002035 Register Res = MI.getOperand(0).getReg();
2036 Register BorrowOut = MI.getOperand(1).getReg();
2037 Register LHS = MI.getOperand(2).getReg();
2038 Register RHS = MI.getOperand(3).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00002039
2040 MIRBuilder.buildSub(Res, LHS, RHS);
2041 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
2042
2043 MI.eraseFromParent();
2044 return Legalized;
2045 }
2046 case G_USUBE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002047 Register Res = MI.getOperand(0).getReg();
2048 Register BorrowOut = MI.getOperand(1).getReg();
2049 Register LHS = MI.getOperand(2).getReg();
2050 Register RHS = MI.getOperand(3).getReg();
2051 Register BorrowIn = MI.getOperand(4).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00002052
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002053 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
2054 Register ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
2055 Register LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
2056 Register LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +00002057
2058 MIRBuilder.buildSub(TmpRes, LHS, RHS);
2059 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
2060 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
2061 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
2062 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
2063 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
2064
2065 MI.eraseFromParent();
2066 return Legalized;
2067 }
Matt Arsenault02b5ca82019-05-17 23:05:13 +00002068 case G_UITOFP:
2069 return lowerUITOFP(MI, TypeIdx, Ty);
2070 case G_SITOFP:
2071 return lowerSITOFP(MI, TypeIdx, Ty);
Matt Arsenault6f74f552019-07-01 17:18:03 +00002072 case G_SMIN:
2073 case G_SMAX:
2074 case G_UMIN:
2075 case G_UMAX:
2076 return lowerMinMax(MI, TypeIdx, Ty);
Matt Arsenaultb1843e12019-07-09 23:34:29 +00002077 case G_FCOPYSIGN:
2078 return lowerFCopySign(MI, TypeIdx, Ty);
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00002079 case G_FMINNUM:
2080 case G_FMAXNUM:
2081 return lowerFMinNumMaxNum(MI);
Matt Arsenaultd9d30a42019-08-01 19:10:05 +00002082 case G_UNMERGE_VALUES:
2083 return lowerUnmergeValues(MI);
Daniel Sanderse9a57c22019-08-09 21:11:20 +00002084 case TargetOpcode::G_SEXT_INREG: {
2085 assert(MI.getOperand(2).isImm() && "Expected immediate");
2086 int64_t SizeInBits = MI.getOperand(2).getImm();
2087
2088 Register DstReg = MI.getOperand(0).getReg();
2089 Register SrcReg = MI.getOperand(1).getReg();
2090 LLT DstTy = MRI.getType(DstReg);
2091 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
2092
2093 auto MIBSz = MIRBuilder.buildConstant(DstTy, DstTy.getScalarSizeInBits() - SizeInBits);
2094 MIRBuilder.buildInstr(TargetOpcode::G_SHL, {TmpRes}, {SrcReg, MIBSz->getOperand(0).getReg()});
2095 MIRBuilder.buildInstr(TargetOpcode::G_ASHR, {DstReg}, {TmpRes, MIBSz->getOperand(0).getReg()});
2096 MI.eraseFromParent();
2097 return Legalized;
2098 }
Tim Northovercecee562016-08-26 17:46:13 +00002099 }
2100}
2101
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002102LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
2103 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002104 SmallVector<Register, 2> DstRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002105
2106 unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002107 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002108 unsigned Size = MRI.getType(DstReg).getSizeInBits();
2109 int NumParts = Size / NarrowSize;
2110 // FIXME: Don't know how to handle the situation where the small vectors
2111 // aren't all the same size yet.
2112 if (Size % NarrowSize != 0)
2113 return UnableToLegalize;
2114
2115 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002116 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002117 MIRBuilder.buildUndef(TmpReg);
2118 DstRegs.push_back(TmpReg);
2119 }
2120
2121 if (NarrowTy.isVector())
2122 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2123 else
2124 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2125
2126 MI.eraseFromParent();
2127 return Legalized;
2128}
2129
2130LegalizerHelper::LegalizeResult
2131LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
2132 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002133 const unsigned Opc = MI.getOpcode();
2134 const unsigned NumOps = MI.getNumOperands() - 1;
2135 const unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenault3018d182019-06-28 01:47:44 +00002136 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002137 const unsigned Flags = MI.getFlags();
2138 const LLT DstTy = MRI.getType(DstReg);
2139 const unsigned Size = DstTy.getSizeInBits();
2140 const int NumParts = Size / NarrowSize;
2141 const LLT EltTy = DstTy.getElementType();
2142 const unsigned EltSize = EltTy.getSizeInBits();
2143 const unsigned BitsForNumParts = NarrowSize * NumParts;
2144
2145 // Check if we have any leftovers. If we do, then only handle the case where
2146 // the leftover is one element.
2147 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002148 return UnableToLegalize;
2149
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002150 if (BitsForNumParts != Size) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002151 Register AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002152 MIRBuilder.buildUndef(AccumDstReg);
2153
2154 // Handle the pieces which evenly divide into the requested type with
2155 // extract/op/insert sequence.
2156 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
2157 SmallVector<SrcOp, 4> SrcOps;
2158 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002159 Register PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002160 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
2161 SrcOps.push_back(PartOpReg);
2162 }
2163
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002164 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002165 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
2166
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002167 Register PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002168 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
2169 AccumDstReg = PartInsertReg;
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002170 }
2171
2172 // Handle the remaining element sized leftover piece.
2173 SmallVector<SrcOp, 4> SrcOps;
2174 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002175 Register PartOpReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002176 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
2177 BitsForNumParts);
2178 SrcOps.push_back(PartOpReg);
2179 }
2180
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002181 Register PartDstReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002182 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
2183 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
2184 MI.eraseFromParent();
2185
2186 return Legalized;
2187 }
2188
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002189 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002190
2191 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
2192
2193 if (NumOps >= 2)
2194 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
2195
2196 if (NumOps >= 3)
2197 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
2198
2199 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002200 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002201
2202 if (NumOps == 1)
2203 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
2204 else if (NumOps == 2) {
2205 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
2206 } else if (NumOps == 3) {
2207 MIRBuilder.buildInstr(Opc, {DstReg},
2208 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
2209 }
2210
2211 DstRegs.push_back(DstReg);
2212 }
2213
2214 if (NarrowTy.isVector())
2215 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2216 else
2217 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2218
2219 MI.eraseFromParent();
2220 return Legalized;
2221}
2222
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002223// Handle splitting vector operations which need to have the same number of
2224// elements in each type index, but each type index may have a different element
2225// type.
2226//
2227// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
2228// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2229// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2230//
2231// Also handles some irregular breakdown cases, e.g.
2232// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
2233// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2234// s64 = G_SHL s64, s32
2235LegalizerHelper::LegalizeResult
2236LegalizerHelper::fewerElementsVectorMultiEltType(
2237 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
2238 if (TypeIdx != 0)
2239 return UnableToLegalize;
2240
2241 const LLT NarrowTy0 = NarrowTyArg;
2242 const unsigned NewNumElts =
2243 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
2244
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002245 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002246 LLT DstTy = MRI.getType(DstReg);
2247 LLT LeftoverTy0;
2248
2249 // All of the operands need to have the same number of elements, so if we can
2250 // determine a type breakdown for the result type, we can for all of the
2251 // source types.
Fangrui Songb251cc02019-07-12 14:58:15 +00002252 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0).first;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002253 if (NumParts < 0)
2254 return UnableToLegalize;
2255
2256 SmallVector<MachineInstrBuilder, 4> NewInsts;
2257
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002258 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
2259 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002260
2261 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
2262 LLT LeftoverTy;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002263 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002264 LLT SrcTyI = MRI.getType(SrcReg);
2265 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
2266 LLT LeftoverTyI;
2267
2268 // Split this operand into the requested typed registers, and any leftover
2269 // required to reproduce the original type.
2270 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
2271 LeftoverRegs))
2272 return UnableToLegalize;
2273
2274 if (I == 1) {
2275 // For the first operand, create an instruction for each part and setup
2276 // the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002277 for (Register PartReg : PartRegs) {
2278 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002279 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2280 .addDef(PartDstReg)
2281 .addUse(PartReg));
2282 DstRegs.push_back(PartDstReg);
2283 }
2284
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002285 for (Register LeftoverReg : LeftoverRegs) {
2286 Register PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002287 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2288 .addDef(PartDstReg)
2289 .addUse(LeftoverReg));
2290 LeftoverDstRegs.push_back(PartDstReg);
2291 }
2292 } else {
2293 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
2294
2295 // Add the newly created operand splits to the existing instructions. The
2296 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2297 // pieces.
2298 unsigned InstCount = 0;
2299 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
2300 NewInsts[InstCount++].addUse(PartRegs[J]);
2301 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
2302 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
2303 }
2304
2305 PartRegs.clear();
2306 LeftoverRegs.clear();
2307 }
2308
2309 // Insert the newly built operations and rebuild the result register.
2310 for (auto &MIB : NewInsts)
2311 MIRBuilder.insertInstr(MIB);
2312
2313 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
2314
2315 MI.eraseFromParent();
2316 return Legalized;
2317}
2318
Tim Northover69fa84a2016-10-14 22:18:18 +00002319LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00002320LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
2321 LLT NarrowTy) {
2322 if (TypeIdx != 0)
2323 return UnableToLegalize;
2324
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002325 Register DstReg = MI.getOperand(0).getReg();
2326 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenaultca676342019-01-25 02:36:32 +00002327 LLT DstTy = MRI.getType(DstReg);
2328 LLT SrcTy = MRI.getType(SrcReg);
2329
2330 LLT NarrowTy0 = NarrowTy;
2331 LLT NarrowTy1;
2332 unsigned NumParts;
2333
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002334 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00002335 // Uneven breakdown not handled.
2336 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
2337 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
2338 return UnableToLegalize;
2339
2340 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002341 } else {
2342 NumParts = DstTy.getNumElements();
2343 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00002344 }
2345
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002346 SmallVector<Register, 4> SrcRegs, DstRegs;
Matt Arsenaultca676342019-01-25 02:36:32 +00002347 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
2348
2349 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002350 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultca676342019-01-25 02:36:32 +00002351 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
2352 .addDef(DstReg)
2353 .addUse(SrcRegs[I]);
2354
2355 NewInst->setFlags(MI.getFlags());
2356 DstRegs.push_back(DstReg);
2357 }
2358
2359 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002360 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002361 else
2362 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2363
2364 MI.eraseFromParent();
2365 return Legalized;
2366}
2367
2368LegalizerHelper::LegalizeResult
2369LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
2370 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002371 Register DstReg = MI.getOperand(0).getReg();
2372 Register Src0Reg = MI.getOperand(2).getReg();
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002373 LLT DstTy = MRI.getType(DstReg);
2374 LLT SrcTy = MRI.getType(Src0Reg);
2375
2376 unsigned NumParts;
2377 LLT NarrowTy0, NarrowTy1;
2378
2379 if (TypeIdx == 0) {
2380 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2381 unsigned OldElts = DstTy.getNumElements();
2382
2383 NarrowTy0 = NarrowTy;
2384 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
2385 NarrowTy1 = NarrowTy.isVector() ?
2386 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
2387 SrcTy.getElementType();
2388
2389 } else {
2390 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2391 unsigned OldElts = SrcTy.getNumElements();
2392
2393 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
2394 NarrowTy.getNumElements();
2395 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
2396 DstTy.getScalarSizeInBits());
2397 NarrowTy1 = NarrowTy;
2398 }
2399
2400 // FIXME: Don't know how to handle the situation where the small vectors
2401 // aren't all the same size yet.
2402 if (NarrowTy1.isVector() &&
2403 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
2404 return UnableToLegalize;
2405
2406 CmpInst::Predicate Pred
2407 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
2408
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002409 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002410 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
2411 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
2412
2413 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002414 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002415 DstRegs.push_back(DstReg);
2416
2417 if (MI.getOpcode() == TargetOpcode::G_ICMP)
2418 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2419 else {
2420 MachineInstr *NewCmp
2421 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2422 NewCmp->setFlags(MI.getFlags());
2423 }
2424 }
2425
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002426 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00002427 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2428 else
2429 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2430
2431 MI.eraseFromParent();
2432 return Legalized;
2433}
2434
2435LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002436LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
2437 LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002438 Register DstReg = MI.getOperand(0).getReg();
2439 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002440
2441 unsigned NumParts = 0;
2442 LLT NarrowTy0, NarrowTy1;
2443
2444 LLT DstTy = MRI.getType(DstReg);
2445 LLT CondTy = MRI.getType(CondReg);
2446 unsigned Size = DstTy.getSizeInBits();
2447
2448 assert(TypeIdx == 0 || CondTy.isVector());
2449
2450 if (TypeIdx == 0) {
2451 NarrowTy0 = NarrowTy;
2452 NarrowTy1 = CondTy;
2453
2454 unsigned NarrowSize = NarrowTy0.getSizeInBits();
2455 // FIXME: Don't know how to handle the situation where the small vectors
2456 // aren't all the same size yet.
2457 if (Size % NarrowSize != 0)
2458 return UnableToLegalize;
2459
2460 NumParts = Size / NarrowSize;
2461
2462 // Need to break down the condition type
2463 if (CondTy.isVector()) {
2464 if (CondTy.getNumElements() == NumParts)
2465 NarrowTy1 = CondTy.getElementType();
2466 else
2467 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
2468 CondTy.getScalarSizeInBits());
2469 }
2470 } else {
2471 NumParts = CondTy.getNumElements();
2472 if (NarrowTy.isVector()) {
2473 // TODO: Handle uneven breakdown.
2474 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
2475 return UnableToLegalize;
2476
2477 return UnableToLegalize;
2478 } else {
2479 NarrowTy0 = DstTy.getElementType();
2480 NarrowTy1 = NarrowTy;
2481 }
2482 }
2483
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002484 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002485 if (CondTy.isVector())
2486 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2487
2488 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2489 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2490
2491 for (unsigned i = 0; i < NumParts; ++i) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002492 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002493 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2494 Src1Regs[i], Src2Regs[i]);
2495 DstRegs.push_back(DstReg);
2496 }
2497
2498 if (NarrowTy0.isVector())
2499 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2500 else
2501 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2502
2503 MI.eraseFromParent();
2504 return Legalized;
2505}
2506
2507LegalizerHelper::LegalizeResult
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002508LegalizerHelper::fewerElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2509 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002510 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002511 LLT PhiTy = MRI.getType(DstReg);
2512 LLT LeftoverTy;
2513
2514 // All of the operands need to have the same number of elements, so if we can
2515 // determine a type breakdown for the result type, we can for all of the
2516 // source types.
2517 int NumParts, NumLeftover;
2518 std::tie(NumParts, NumLeftover)
2519 = getNarrowTypeBreakDown(PhiTy, NarrowTy, LeftoverTy);
2520 if (NumParts < 0)
2521 return UnableToLegalize;
2522
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002523 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002524 SmallVector<MachineInstrBuilder, 4> NewInsts;
2525
2526 const int TotalNumParts = NumParts + NumLeftover;
2527
2528 // Insert the new phis in the result block first.
2529 for (int I = 0; I != TotalNumParts; ++I) {
2530 LLT Ty = I < NumParts ? NarrowTy : LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002531 Register PartDstReg = MRI.createGenericVirtualRegister(Ty);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002532 NewInsts.push_back(MIRBuilder.buildInstr(TargetOpcode::G_PHI)
2533 .addDef(PartDstReg));
2534 if (I < NumParts)
2535 DstRegs.push_back(PartDstReg);
2536 else
2537 LeftoverDstRegs.push_back(PartDstReg);
2538 }
2539
2540 MachineBasicBlock *MBB = MI.getParent();
2541 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
2542 insertParts(DstReg, PhiTy, NarrowTy, DstRegs, LeftoverTy, LeftoverDstRegs);
2543
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002544 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002545
2546 // Insert code to extract the incoming values in each predecessor block.
2547 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2548 PartRegs.clear();
2549 LeftoverRegs.clear();
2550
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002551 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002552 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2553 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2554
2555 LLT Unused;
2556 if (!extractParts(SrcReg, PhiTy, NarrowTy, Unused, PartRegs,
2557 LeftoverRegs))
2558 return UnableToLegalize;
2559
2560 // Add the newly created operand splits to the existing instructions. The
2561 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2562 // pieces.
2563 for (int J = 0; J != TotalNumParts; ++J) {
2564 MachineInstrBuilder MIB = NewInsts[J];
2565 MIB.addUse(J < NumParts ? PartRegs[J] : LeftoverRegs[J - NumParts]);
2566 MIB.addMBB(&OpMBB);
2567 }
2568 }
2569
2570 MI.eraseFromParent();
2571 return Legalized;
2572}
2573
2574LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002575LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2576 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002577 // FIXME: Don't know how to handle secondary types yet.
2578 if (TypeIdx != 0)
2579 return UnableToLegalize;
2580
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002581 MachineMemOperand *MMO = *MI.memoperands_begin();
2582
2583 // This implementation doesn't work for atomics. Give up instead of doing
2584 // something invalid.
2585 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2586 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2587 return UnableToLegalize;
2588
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002589 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002590 Register ValReg = MI.getOperand(0).getReg();
2591 Register AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002592 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002593
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002594 int NumParts = -1;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002595 int NumLeftover = -1;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002596 LLT LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002597 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002598 if (IsLoad) {
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002599 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002600 } else {
2601 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002602 NarrowLeftoverRegs)) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002603 NumParts = NarrowRegs.size();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002604 NumLeftover = NarrowLeftoverRegs.size();
2605 }
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002606 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002607
2608 if (NumParts == -1)
2609 return UnableToLegalize;
2610
2611 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2612
2613 unsigned TotalSize = ValTy.getSizeInBits();
2614
2615 // Split the load/store into PartTy sized pieces starting at Offset. If this
2616 // is a load, return the new registers in ValRegs. For a store, each elements
2617 // of ValRegs should be PartTy. Returns the next offset that needs to be
2618 // handled.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002619 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002620 unsigned Offset) -> unsigned {
2621 MachineFunction &MF = MIRBuilder.getMF();
2622 unsigned PartSize = PartTy.getSizeInBits();
2623 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2624 Offset += PartSize, ++Idx) {
2625 unsigned ByteSize = PartSize / 8;
2626 unsigned ByteOffset = Offset / 8;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002627 Register NewAddrReg;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002628
2629 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2630
2631 MachineMemOperand *NewMMO =
2632 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2633
2634 if (IsLoad) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002635 Register Dst = MRI.createGenericVirtualRegister(PartTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002636 ValRegs.push_back(Dst);
2637 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2638 } else {
2639 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2640 }
2641 }
2642
2643 return Offset;
2644 };
2645
2646 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2647
2648 // Handle the rest of the register if this isn't an even type breakdown.
2649 if (LeftoverTy.isValid())
2650 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2651
2652 if (IsLoad) {
2653 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2654 LeftoverTy, NarrowLeftoverRegs);
2655 }
2656
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002657 MI.eraseFromParent();
2658 return Legalized;
2659}
2660
2661LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002662LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2663 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002664 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002665
2666 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002667 switch (MI.getOpcode()) {
2668 case G_IMPLICIT_DEF:
2669 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2670 case G_AND:
2671 case G_OR:
2672 case G_XOR:
2673 case G_ADD:
2674 case G_SUB:
2675 case G_MUL:
2676 case G_SMULH:
2677 case G_UMULH:
2678 case G_FADD:
2679 case G_FMUL:
2680 case G_FSUB:
2681 case G_FNEG:
2682 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002683 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002684 case G_FDIV:
2685 case G_FREM:
2686 case G_FMA:
2687 case G_FPOW:
2688 case G_FEXP:
2689 case G_FEXP2:
2690 case G_FLOG:
2691 case G_FLOG2:
2692 case G_FLOG10:
Jessica Paquetteba557672019-04-25 16:44:40 +00002693 case G_FNEARBYINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002694 case G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00002695 case G_FFLOOR:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00002696 case G_FRINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002697 case G_INTRINSIC_ROUND:
2698 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002699 case G_FCOS:
2700 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002701 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002702 case G_BSWAP:
Amara Emersonae878da2019-04-10 23:06:08 +00002703 case G_SDIV:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002704 case G_SMIN:
2705 case G_SMAX:
2706 case G_UMIN:
2707 case G_UMAX:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00002708 case G_FMINNUM:
2709 case G_FMAXNUM:
2710 case G_FMINNUM_IEEE:
2711 case G_FMAXNUM_IEEE:
2712 case G_FMINIMUM:
2713 case G_FMAXIMUM:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002714 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002715 case G_SHL:
2716 case G_LSHR:
2717 case G_ASHR:
Matt Arsenault75e30c42019-02-20 16:42:52 +00002718 case G_CTLZ:
2719 case G_CTLZ_ZERO_UNDEF:
2720 case G_CTTZ:
2721 case G_CTTZ_ZERO_UNDEF:
2722 case G_CTPOP:
Matt Arsenault1448f562019-05-17 12:19:52 +00002723 case G_FCOPYSIGN:
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002724 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002725 case G_ZEXT:
2726 case G_SEXT:
2727 case G_ANYEXT:
2728 case G_FPEXT:
2729 case G_FPTRUNC:
2730 case G_SITOFP:
2731 case G_UITOFP:
2732 case G_FPTOSI:
2733 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002734 case G_INTTOPTR:
2735 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002736 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002737 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2738 case G_ICMP:
2739 case G_FCMP:
2740 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002741 case G_SELECT:
2742 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002743 case G_PHI:
2744 return fewerElementsVectorPhi(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002745 case G_LOAD:
2746 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002747 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002748 default:
2749 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002750 }
2751}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002752
2753LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002754LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2755 const LLT HalfTy, const LLT AmtTy) {
2756
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002757 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2758 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002759 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2760
2761 if (Amt.isNullValue()) {
2762 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2763 MI.eraseFromParent();
2764 return Legalized;
2765 }
2766
2767 LLT NVT = HalfTy;
2768 unsigned NVTBits = HalfTy.getSizeInBits();
2769 unsigned VTBits = 2 * NVTBits;
2770
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002771 SrcOp Lo(Register(0)), Hi(Register(0));
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002772 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2773 if (Amt.ugt(VTBits)) {
2774 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2775 } else if (Amt.ugt(NVTBits)) {
2776 Lo = MIRBuilder.buildConstant(NVT, 0);
2777 Hi = MIRBuilder.buildShl(NVT, InL,
2778 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2779 } else if (Amt == NVTBits) {
2780 Lo = MIRBuilder.buildConstant(NVT, 0);
2781 Hi = InL;
2782 } else {
2783 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002784 auto OrLHS =
2785 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2786 auto OrRHS = MIRBuilder.buildLShr(
2787 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2788 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002789 }
2790 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2791 if (Amt.ugt(VTBits)) {
2792 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2793 } else if (Amt.ugt(NVTBits)) {
2794 Lo = MIRBuilder.buildLShr(NVT, InH,
2795 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2796 Hi = MIRBuilder.buildConstant(NVT, 0);
2797 } else if (Amt == NVTBits) {
2798 Lo = InH;
2799 Hi = MIRBuilder.buildConstant(NVT, 0);
2800 } else {
2801 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2802
2803 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2804 auto OrRHS = MIRBuilder.buildShl(
2805 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2806
2807 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2808 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2809 }
2810 } else {
2811 if (Amt.ugt(VTBits)) {
2812 Hi = Lo = MIRBuilder.buildAShr(
2813 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2814 } else if (Amt.ugt(NVTBits)) {
2815 Lo = MIRBuilder.buildAShr(NVT, InH,
2816 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2817 Hi = MIRBuilder.buildAShr(NVT, InH,
2818 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2819 } else if (Amt == NVTBits) {
2820 Lo = InH;
2821 Hi = MIRBuilder.buildAShr(NVT, InH,
2822 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2823 } else {
2824 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2825
2826 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2827 auto OrRHS = MIRBuilder.buildShl(
2828 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2829
2830 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2831 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2832 }
2833 }
2834
2835 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2836 MI.eraseFromParent();
2837
2838 return Legalized;
2839}
2840
2841// TODO: Optimize if constant shift amount.
2842LegalizerHelper::LegalizeResult
2843LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2844 LLT RequestedTy) {
2845 if (TypeIdx == 1) {
2846 Observer.changingInstr(MI);
2847 narrowScalarSrc(MI, RequestedTy, 2);
2848 Observer.changedInstr(MI);
2849 return Legalized;
2850 }
2851
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002852 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002853 LLT DstTy = MRI.getType(DstReg);
2854 if (DstTy.isVector())
2855 return UnableToLegalize;
2856
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002857 Register Amt = MI.getOperand(2).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002858 LLT ShiftAmtTy = MRI.getType(Amt);
2859 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2860 if (DstEltSize % 2 != 0)
2861 return UnableToLegalize;
2862
2863 // Ignore the input type. We can only go to exactly half the size of the
2864 // input. If that isn't small enough, the resulting pieces will be further
2865 // legalized.
2866 const unsigned NewBitSize = DstEltSize / 2;
2867 const LLT HalfTy = LLT::scalar(NewBitSize);
2868 const LLT CondTy = LLT::scalar(1);
2869
2870 if (const MachineInstr *KShiftAmt =
2871 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2872 return narrowScalarShiftByConstant(
2873 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2874 }
2875
2876 // TODO: Expand with known bits.
2877
2878 // Handle the fully general expansion by an unknown amount.
2879 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2880
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002881 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2882 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002883 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2884
2885 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2886 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2887
2888 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2889 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2890 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2891
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002892 Register ResultRegs[2];
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002893 switch (MI.getOpcode()) {
2894 case TargetOpcode::G_SHL: {
2895 // Short: ShAmt < NewBitSize
2896 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2897
2898 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2899 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2900 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2901
2902 // Long: ShAmt >= NewBitSize
2903 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2904 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2905
2906 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2907 auto Hi = MIRBuilder.buildSelect(
2908 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2909
2910 ResultRegs[0] = Lo.getReg(0);
2911 ResultRegs[1] = Hi.getReg(0);
2912 break;
2913 }
2914 case TargetOpcode::G_LSHR: {
2915 // Short: ShAmt < NewBitSize
2916 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2917
2918 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2919 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2920 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2921
2922 // Long: ShAmt >= NewBitSize
2923 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2924 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2925
2926 auto Lo = MIRBuilder.buildSelect(
2927 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2928 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2929
2930 ResultRegs[0] = Lo.getReg(0);
2931 ResultRegs[1] = Hi.getReg(0);
2932 break;
2933 }
2934 case TargetOpcode::G_ASHR: {
2935 // Short: ShAmt < NewBitSize
2936 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2937
2938 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2939 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2940 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2941
2942 // Long: ShAmt >= NewBitSize
2943
2944 // Sign of Hi part.
2945 auto HiL = MIRBuilder.buildAShr(
2946 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2947
2948 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2949
2950 auto Lo = MIRBuilder.buildSelect(
2951 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2952
2953 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2954
2955 ResultRegs[0] = Lo.getReg(0);
2956 ResultRegs[1] = Hi.getReg(0);
2957 break;
2958 }
2959 default:
2960 llvm_unreachable("not a shift");
2961 }
2962
2963 MIRBuilder.buildMerge(DstReg, ResultRegs);
2964 MI.eraseFromParent();
2965 return Legalized;
2966}
2967
2968LegalizerHelper::LegalizeResult
Matt Arsenault72bcf152019-02-28 00:01:05 +00002969LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2970 LLT MoreTy) {
2971 assert(TypeIdx == 0 && "Expecting only Idx 0");
2972
2973 Observer.changingInstr(MI);
2974 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2975 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2976 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2977 moreElementsVectorSrc(MI, MoreTy, I);
2978 }
2979
2980 MachineBasicBlock &MBB = *MI.getParent();
2981 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
2982 moreElementsVectorDst(MI, MoreTy, 0);
2983 Observer.changedInstr(MI);
2984 return Legalized;
2985}
2986
2987LegalizerHelper::LegalizeResult
Matt Arsenault18ec3822019-02-11 22:00:39 +00002988LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
2989 LLT MoreTy) {
2990 MIRBuilder.setInstr(MI);
2991 unsigned Opc = MI.getOpcode();
2992 switch (Opc) {
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002993 case TargetOpcode::G_IMPLICIT_DEF:
2994 case TargetOpcode::G_LOAD: {
2995 if (TypeIdx != 0)
2996 return UnableToLegalize;
Matt Arsenault18ec3822019-02-11 22:00:39 +00002997 Observer.changingInstr(MI);
2998 moreElementsVectorDst(MI, MoreTy, 0);
2999 Observer.changedInstr(MI);
3000 return Legalized;
3001 }
Matt Arsenault7bedceb2019-08-01 01:44:22 +00003002 case TargetOpcode::G_STORE:
3003 if (TypeIdx != 0)
3004 return UnableToLegalize;
3005 Observer.changingInstr(MI);
3006 moreElementsVectorSrc(MI, MoreTy, 0);
3007 Observer.changedInstr(MI);
3008 return Legalized;
Matt Arsenault26b7e852019-02-19 16:30:19 +00003009 case TargetOpcode::G_AND:
3010 case TargetOpcode::G_OR:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00003011 case TargetOpcode::G_XOR:
3012 case TargetOpcode::G_SMIN:
3013 case TargetOpcode::G_SMAX:
3014 case TargetOpcode::G_UMIN:
3015 case TargetOpcode::G_UMAX: {
Matt Arsenault26b7e852019-02-19 16:30:19 +00003016 Observer.changingInstr(MI);
3017 moreElementsVectorSrc(MI, MoreTy, 1);
3018 moreElementsVectorSrc(MI, MoreTy, 2);
3019 moreElementsVectorDst(MI, MoreTy, 0);
3020 Observer.changedInstr(MI);
3021 return Legalized;
3022 }
Matt Arsenault4d884272019-02-19 16:44:22 +00003023 case TargetOpcode::G_EXTRACT:
3024 if (TypeIdx != 1)
3025 return UnableToLegalize;
3026 Observer.changingInstr(MI);
3027 moreElementsVectorSrc(MI, MoreTy, 1);
3028 Observer.changedInstr(MI);
3029 return Legalized;
Matt Arsenaultc4d07552019-02-20 16:11:22 +00003030 case TargetOpcode::G_INSERT:
3031 if (TypeIdx != 0)
3032 return UnableToLegalize;
3033 Observer.changingInstr(MI);
3034 moreElementsVectorSrc(MI, MoreTy, 1);
3035 moreElementsVectorDst(MI, MoreTy, 0);
3036 Observer.changedInstr(MI);
3037 return Legalized;
Matt Arsenaultb4c95b32019-02-19 17:03:09 +00003038 case TargetOpcode::G_SELECT:
3039 if (TypeIdx != 0)
3040 return UnableToLegalize;
3041 if (MRI.getType(MI.getOperand(1).getReg()).isVector())
3042 return UnableToLegalize;
3043
3044 Observer.changingInstr(MI);
3045 moreElementsVectorSrc(MI, MoreTy, 2);
3046 moreElementsVectorSrc(MI, MoreTy, 3);
3047 moreElementsVectorDst(MI, MoreTy, 0);
3048 Observer.changedInstr(MI);
3049 return Legalized;
Matt Arsenault72bcf152019-02-28 00:01:05 +00003050 case TargetOpcode::G_PHI:
3051 return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +00003052 default:
3053 return UnableToLegalize;
3054 }
3055}
3056
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003057void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
3058 ArrayRef<Register> Src1Regs,
3059 ArrayRef<Register> Src2Regs,
Petar Avramovic0b17e592019-03-11 10:00:17 +00003060 LLT NarrowTy) {
3061 MachineIRBuilder &B = MIRBuilder;
3062 unsigned SrcParts = Src1Regs.size();
3063 unsigned DstParts = DstRegs.size();
3064
3065 unsigned DstIdx = 0; // Low bits of the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003066 Register FactorSum =
Petar Avramovic0b17e592019-03-11 10:00:17 +00003067 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
3068 DstRegs[DstIdx] = FactorSum;
3069
3070 unsigned CarrySumPrevDstIdx;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003071 SmallVector<Register, 4> Factors;
Petar Avramovic0b17e592019-03-11 10:00:17 +00003072
3073 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
3074 // Collect low parts of muls for DstIdx.
3075 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
3076 i <= std::min(DstIdx, SrcParts - 1); ++i) {
3077 MachineInstrBuilder Mul =
3078 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
3079 Factors.push_back(Mul.getReg(0));
3080 }
3081 // Collect high parts of muls from previous DstIdx.
3082 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
3083 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
3084 MachineInstrBuilder Umulh =
3085 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
3086 Factors.push_back(Umulh.getReg(0));
3087 }
3088 // Add CarrySum from additons calculated for previous DstIdx.
3089 if (DstIdx != 1) {
3090 Factors.push_back(CarrySumPrevDstIdx);
3091 }
3092
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003093 Register CarrySum;
Petar Avramovic0b17e592019-03-11 10:00:17 +00003094 // Add all factors and accumulate all carries into CarrySum.
3095 if (DstIdx != DstParts - 1) {
3096 MachineInstrBuilder Uaddo =
3097 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]);
3098 FactorSum = Uaddo.getReg(0);
3099 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0);
3100 for (unsigned i = 2; i < Factors.size(); ++i) {
3101 MachineInstrBuilder Uaddo =
3102 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]);
3103 FactorSum = Uaddo.getReg(0);
3104 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1));
3105 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
3106 }
3107 } else {
3108 // Since value for the next index is not calculated, neither is CarrySum.
3109 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
3110 for (unsigned i = 2; i < Factors.size(); ++i)
3111 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
3112 }
3113
3114 CarrySumPrevDstIdx = CarrySum;
3115 DstRegs[DstIdx] = FactorSum;
3116 Factors.clear();
3117 }
3118}
3119
Matt Arsenault18ec3822019-02-11 22:00:39 +00003120LegalizerHelper::LegalizeResult
Petar Avramovic0b17e592019-03-11 10:00:17 +00003121LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003122 Register DstReg = MI.getOperand(0).getReg();
3123 Register Src1 = MI.getOperand(1).getReg();
3124 Register Src2 = MI.getOperand(2).getReg();
Petar Avramovic0b17e592019-03-11 10:00:17 +00003125
Matt Arsenault211e89d2019-01-27 00:52:51 +00003126 LLT Ty = MRI.getType(DstReg);
3127 if (Ty.isVector())
3128 return UnableToLegalize;
3129
Petar Avramovic0b17e592019-03-11 10:00:17 +00003130 unsigned SrcSize = MRI.getType(Src1).getSizeInBits();
3131 unsigned DstSize = Ty.getSizeInBits();
3132 unsigned NarrowSize = NarrowTy.getSizeInBits();
3133 if (DstSize % NarrowSize != 0 || SrcSize % NarrowSize != 0)
Matt Arsenault211e89d2019-01-27 00:52:51 +00003134 return UnableToLegalize;
3135
Petar Avramovic0b17e592019-03-11 10:00:17 +00003136 unsigned NumDstParts = DstSize / NarrowSize;
3137 unsigned NumSrcParts = SrcSize / NarrowSize;
Petar Avramovic5229f472019-03-11 10:08:44 +00003138 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH;
3139 unsigned DstTmpParts = NumDstParts * (IsMulHigh ? 2 : 1);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003140
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003141 SmallVector<Register, 2> Src1Parts, Src2Parts, DstTmpRegs;
Petar Avramovic0b17e592019-03-11 10:00:17 +00003142 extractParts(Src1, NarrowTy, NumSrcParts, Src1Parts);
3143 extractParts(Src2, NarrowTy, NumSrcParts, Src2Parts);
Petar Avramovic5229f472019-03-11 10:08:44 +00003144 DstTmpRegs.resize(DstTmpParts);
3145 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003146
Petar Avramovic5229f472019-03-11 10:08:44 +00003147 // Take only high half of registers if this is high mul.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003148 ArrayRef<Register> DstRegs(
Petar Avramovic5229f472019-03-11 10:08:44 +00003149 IsMulHigh ? &DstTmpRegs[DstTmpParts / 2] : &DstTmpRegs[0], NumDstParts);
Petar Avramovic0b17e592019-03-11 10:00:17 +00003150 MIRBuilder.buildMerge(DstReg, DstRegs);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003151 MI.eraseFromParent();
3152 return Legalized;
3153}
3154
Matt Arsenault1cf71362019-02-12 14:54:52 +00003155LegalizerHelper::LegalizeResult
3156LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
3157 LLT NarrowTy) {
3158 if (TypeIdx != 1)
3159 return UnableToLegalize;
3160
3161 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3162
3163 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
3164 // FIXME: add support for when SizeOp1 isn't an exact multiple of
3165 // NarrowSize.
3166 if (SizeOp1 % NarrowSize != 0)
3167 return UnableToLegalize;
3168 int NumParts = SizeOp1 / NarrowSize;
3169
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003170 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003171 SmallVector<uint64_t, 2> Indexes;
3172 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3173
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003174 Register OpReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003175 uint64_t OpStart = MI.getOperand(2).getImm();
3176 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3177 for (int i = 0; i < NumParts; ++i) {
3178 unsigned SrcStart = i * NarrowSize;
3179
3180 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
3181 // No part of the extract uses this subregister, ignore it.
3182 continue;
3183 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3184 // The entire subregister is extracted, forward the value.
3185 DstRegs.push_back(SrcRegs[i]);
3186 continue;
3187 }
3188
3189 // OpSegStart is where this destination segment would start in OpReg if it
3190 // extended infinitely in both directions.
3191 int64_t ExtractOffset;
3192 uint64_t SegSize;
3193 if (OpStart < SrcStart) {
3194 ExtractOffset = 0;
3195 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
3196 } else {
3197 ExtractOffset = OpStart - SrcStart;
3198 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
3199 }
3200
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003201 Register SegReg = SrcRegs[i];
Matt Arsenault1cf71362019-02-12 14:54:52 +00003202 if (ExtractOffset != 0 || SegSize != NarrowSize) {
3203 // A genuine extract is needed.
3204 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3205 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
3206 }
3207
3208 DstRegs.push_back(SegReg);
3209 }
3210
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003211 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003212 if(MRI.getType(DstReg).isVector())
3213 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3214 else
3215 MIRBuilder.buildMerge(DstReg, DstRegs);
3216 MI.eraseFromParent();
3217 return Legalized;
3218}
3219
3220LegalizerHelper::LegalizeResult
3221LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
3222 LLT NarrowTy) {
3223 // FIXME: Don't know how to handle secondary types yet.
3224 if (TypeIdx != 0)
3225 return UnableToLegalize;
3226
3227 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
3228 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3229
3230 // FIXME: add support for when SizeOp0 isn't an exact multiple of
3231 // NarrowSize.
3232 if (SizeOp0 % NarrowSize != 0)
3233 return UnableToLegalize;
3234
3235 int NumParts = SizeOp0 / NarrowSize;
3236
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003237 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003238 SmallVector<uint64_t, 2> Indexes;
3239 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3240
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003241 Register OpReg = MI.getOperand(2).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003242 uint64_t OpStart = MI.getOperand(3).getImm();
3243 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3244 for (int i = 0; i < NumParts; ++i) {
3245 unsigned DstStart = i * NarrowSize;
3246
3247 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
3248 // No part of the insert affects this subregister, forward the original.
3249 DstRegs.push_back(SrcRegs[i]);
3250 continue;
3251 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3252 // The entire subregister is defined by this insert, forward the new
3253 // value.
3254 DstRegs.push_back(OpReg);
3255 continue;
3256 }
3257
3258 // OpSegStart is where this destination segment would start in OpReg if it
3259 // extended infinitely in both directions.
3260 int64_t ExtractOffset, InsertOffset;
3261 uint64_t SegSize;
3262 if (OpStart < DstStart) {
3263 InsertOffset = 0;
3264 ExtractOffset = DstStart - OpStart;
3265 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
3266 } else {
3267 InsertOffset = OpStart - DstStart;
3268 ExtractOffset = 0;
3269 SegSize =
3270 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
3271 }
3272
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003273 Register SegReg = OpReg;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003274 if (ExtractOffset != 0 || SegSize != OpSize) {
3275 // A genuine extract is needed.
3276 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3277 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
3278 }
3279
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003280 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +00003281 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
3282 DstRegs.push_back(DstReg);
3283 }
3284
3285 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003286 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003287 if(MRI.getType(DstReg).isVector())
3288 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3289 else
3290 MIRBuilder.buildMerge(DstReg, DstRegs);
3291 MI.eraseFromParent();
3292 return Legalized;
3293}
3294
Matt Arsenault211e89d2019-01-27 00:52:51 +00003295LegalizerHelper::LegalizeResult
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003296LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx,
3297 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003298 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003299 LLT DstTy = MRI.getType(DstReg);
3300
3301 assert(MI.getNumOperands() == 3 && TypeIdx == 0);
3302
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003303 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3304 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs;
3305 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003306 LLT LeftoverTy;
3307 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
3308 Src0Regs, Src0LeftoverRegs))
3309 return UnableToLegalize;
3310
3311 LLT Unused;
3312 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
3313 Src1Regs, Src1LeftoverRegs))
3314 llvm_unreachable("inconsistent extractParts result");
3315
3316 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3317 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
3318 {Src0Regs[I], Src1Regs[I]});
3319 DstRegs.push_back(Inst->getOperand(0).getReg());
3320 }
3321
3322 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3323 auto Inst = MIRBuilder.buildInstr(
3324 MI.getOpcode(),
3325 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
3326 DstLeftoverRegs.push_back(Inst->getOperand(0).getReg());
3327 }
3328
3329 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3330 LeftoverTy, DstLeftoverRegs);
3331
3332 MI.eraseFromParent();
3333 return Legalized;
3334}
3335
3336LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00003337LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
3338 LLT NarrowTy) {
3339 if (TypeIdx != 0)
3340 return UnableToLegalize;
3341
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003342 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003343 LLT CondTy = MRI.getType(CondReg);
3344 if (CondTy.isVector()) // TODO: Handle vselect
3345 return UnableToLegalize;
3346
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003347 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003348 LLT DstTy = MRI.getType(DstReg);
3349
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003350 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3351 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
3352 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs;
Matt Arsenault81511e52019-02-05 00:13:44 +00003353 LLT LeftoverTy;
3354 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
3355 Src1Regs, Src1LeftoverRegs))
3356 return UnableToLegalize;
3357
3358 LLT Unused;
3359 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
3360 Src2Regs, Src2LeftoverRegs))
3361 llvm_unreachable("inconsistent extractParts result");
3362
3363 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3364 auto Select = MIRBuilder.buildSelect(NarrowTy,
3365 CondReg, Src1Regs[I], Src2Regs[I]);
3366 DstRegs.push_back(Select->getOperand(0).getReg());
3367 }
3368
3369 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3370 auto Select = MIRBuilder.buildSelect(
3371 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
3372 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
3373 }
3374
3375 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3376 LeftoverTy, DstLeftoverRegs);
3377
3378 MI.eraseFromParent();
3379 return Legalized;
3380}
3381
3382LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003383LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3384 unsigned Opc = MI.getOpcode();
3385 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00003386 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003387 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00003388 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003389 };
3390 switch (Opc) {
3391 default:
3392 return UnableToLegalize;
3393 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
3394 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003395 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003396 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003397 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003398 return Legalized;
3399 }
3400 case TargetOpcode::G_CTLZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003401 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003402 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003403 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00003404 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003405 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
3406 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003407 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3408 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3409 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3410 SrcReg, MIBZero);
3411 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3412 MIBCtlzZU);
3413 MI.eraseFromParent();
3414 return Legalized;
3415 }
3416 // for now, we do this:
3417 // NewLen = NextPowerOf2(Len);
3418 // x = x | (x >> 1);
3419 // x = x | (x >> 2);
3420 // ...
3421 // x = x | (x >>16);
3422 // x = x | (x >>32); // for 64-bit input
3423 // Upto NewLen/2
3424 // return Len - popcount(x);
3425 //
3426 // Ref: "Hacker's Delight" by Henry Warren
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003427 Register Op = SrcReg;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003428 unsigned NewLen = PowerOf2Ceil(Len);
3429 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
3430 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
3431 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003432 TargetOpcode::G_OR, {Ty},
3433 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
3434 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003435 Op = MIBOp->getOperand(0).getReg();
3436 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003437 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
3438 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3439 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003440 MI.eraseFromParent();
3441 return Legalized;
3442 }
3443 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
3444 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003445 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003446 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003447 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003448 return Legalized;
3449 }
3450 case TargetOpcode::G_CTTZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003451 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003452 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003453 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003454 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
3455 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003456 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
3457 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003458 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3459 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3460 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3461 SrcReg, MIBZero);
3462 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3463 MIBCttzZU);
3464 MI.eraseFromParent();
3465 return Legalized;
3466 }
3467 // for now, we use: { return popcount(~x & (x - 1)); }
3468 // unless the target has ctlz but not ctpop, in which case we use:
3469 // { return 32 - nlz(~x & (x-1)); }
3470 // Ref: "Hacker's Delight" by Henry Warren
3471 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
3472 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003473 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003474 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003475 TargetOpcode::G_AND, {Ty},
3476 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
3477 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003478 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
3479 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003480 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
3481 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003482 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3483 {MIBCstLen,
3484 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003485 MI.eraseFromParent();
3486 return Legalized;
3487 }
3488 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
3489 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
3490 return Legalized;
3491 }
3492 }
3493}
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003494
3495// Expand s32 = G_UITOFP s64 using bit operations to an IEEE float
3496// representation.
3497LegalizerHelper::LegalizeResult
3498LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003499 Register Dst = MI.getOperand(0).getReg();
3500 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003501 const LLT S64 = LLT::scalar(64);
3502 const LLT S32 = LLT::scalar(32);
3503 const LLT S1 = LLT::scalar(1);
3504
3505 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);
3506
3507 // unsigned cul2f(ulong u) {
3508 // uint lz = clz(u);
3509 // uint e = (u != 0) ? 127U + 63U - lz : 0;
3510 // u = (u << lz) & 0x7fffffffffffffffUL;
3511 // ulong t = u & 0xffffffffffUL;
3512 // uint v = (e << 23) | (uint)(u >> 40);
3513 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
3514 // return as_float(v + r);
3515 // }
3516
3517 auto Zero32 = MIRBuilder.buildConstant(S32, 0);
3518 auto Zero64 = MIRBuilder.buildConstant(S64, 0);
3519
3520 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src);
3521
3522 auto K = MIRBuilder.buildConstant(S32, 127U + 63U);
3523 auto Sub = MIRBuilder.buildSub(S32, K, LZ);
3524
3525 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64);
3526 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32);
3527
3528 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1);
3529 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ);
3530
3531 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0);
3532
3533 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL);
3534 auto T = MIRBuilder.buildAnd(S64, U, Mask1);
3535
3536 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40));
3537 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23));
3538 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl));
3539
3540 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL);
3541 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C);
3542 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C);
3543 auto One = MIRBuilder.buildConstant(S32, 1);
3544
3545 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One);
3546 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32);
3547 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0);
3548 MIRBuilder.buildAdd(Dst, V, R);
3549
3550 return Legalized;
3551}
3552
3553LegalizerHelper::LegalizeResult
3554LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003555 Register Dst = MI.getOperand(0).getReg();
3556 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003557 LLT DstTy = MRI.getType(Dst);
3558 LLT SrcTy = MRI.getType(Src);
3559
3560 if (SrcTy != LLT::scalar(64))
3561 return UnableToLegalize;
3562
3563 if (DstTy == LLT::scalar(32)) {
3564 // TODO: SelectionDAG has several alternative expansions to port which may
3565 // be more reasonble depending on the available instructions. If a target
3566 // has sitofp, does not have CTLZ, or can efficiently use f64 as an
3567 // intermediate type, this is probably worse.
3568 return lowerU64ToF32BitOps(MI);
3569 }
3570
3571 return UnableToLegalize;
3572}
3573
3574LegalizerHelper::LegalizeResult
3575LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003576 Register Dst = MI.getOperand(0).getReg();
3577 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003578 LLT DstTy = MRI.getType(Dst);
3579 LLT SrcTy = MRI.getType(Src);
3580
3581 const LLT S64 = LLT::scalar(64);
3582 const LLT S32 = LLT::scalar(32);
3583 const LLT S1 = LLT::scalar(1);
3584
3585 if (SrcTy != S64)
3586 return UnableToLegalize;
3587
3588 if (DstTy == S32) {
3589 // signed cl2f(long l) {
3590 // long s = l >> 63;
3591 // float r = cul2f((l + s) ^ s);
3592 // return s ? -r : r;
3593 // }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003594 Register L = Src;
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003595 auto SignBit = MIRBuilder.buildConstant(S64, 63);
3596 auto S = MIRBuilder.buildAShr(S64, L, SignBit);
3597
3598 auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
3599 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
3600 auto R = MIRBuilder.buildUITOFP(S32, Xor);
3601
3602 auto RNeg = MIRBuilder.buildFNeg(S32, R);
3603 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
3604 MIRBuilder.buildConstant(S64, 0));
3605 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
3606 return Legalized;
3607 }
3608
3609 return UnableToLegalize;
3610}
Matt Arsenault6f74f552019-07-01 17:18:03 +00003611
3612static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
3613 switch (Opc) {
3614 case TargetOpcode::G_SMIN:
3615 return CmpInst::ICMP_SLT;
3616 case TargetOpcode::G_SMAX:
3617 return CmpInst::ICMP_SGT;
3618 case TargetOpcode::G_UMIN:
3619 return CmpInst::ICMP_ULT;
3620 case TargetOpcode::G_UMAX:
3621 return CmpInst::ICMP_UGT;
3622 default:
3623 llvm_unreachable("not in integer min/max");
3624 }
3625}
3626
3627LegalizerHelper::LegalizeResult
3628LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3629 Register Dst = MI.getOperand(0).getReg();
3630 Register Src0 = MI.getOperand(1).getReg();
3631 Register Src1 = MI.getOperand(2).getReg();
3632
3633 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
3634 LLT CmpType = MRI.getType(Dst).changeElementSize(1);
3635
3636 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
3637 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
3638
3639 MI.eraseFromParent();
3640 return Legalized;
3641}
Matt Arsenaultb1843e12019-07-09 23:34:29 +00003642
3643LegalizerHelper::LegalizeResult
3644LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3645 Register Dst = MI.getOperand(0).getReg();
3646 Register Src0 = MI.getOperand(1).getReg();
3647 Register Src1 = MI.getOperand(2).getReg();
3648
3649 const LLT Src0Ty = MRI.getType(Src0);
3650 const LLT Src1Ty = MRI.getType(Src1);
3651
3652 const int Src0Size = Src0Ty.getScalarSizeInBits();
3653 const int Src1Size = Src1Ty.getScalarSizeInBits();
3654
3655 auto SignBitMask = MIRBuilder.buildConstant(
3656 Src0Ty, APInt::getSignMask(Src0Size));
3657
3658 auto NotSignBitMask = MIRBuilder.buildConstant(
3659 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
3660
3661 auto And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask);
3662 MachineInstr *Or;
3663
3664 if (Src0Ty == Src1Ty) {
3665 auto And1 = MIRBuilder.buildAnd(Src1Ty, Src0, SignBitMask);
3666 Or = MIRBuilder.buildOr(Dst, And0, And1);
3667 } else if (Src0Size > Src1Size) {
3668 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
3669 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
3670 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
3671 auto And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask);
3672 Or = MIRBuilder.buildOr(Dst, And0, And1);
3673 } else {
3674 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
3675 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
3676 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
3677 auto And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask);
3678 Or = MIRBuilder.buildOr(Dst, And0, And1);
3679 }
3680
3681 // Be careful about setting nsz/nnan/ninf on every instruction, since the
3682 // constants are a nan and -0.0, but the final result should preserve
3683 // everything.
3684 if (unsigned Flags = MI.getFlags())
3685 Or->setFlags(Flags);
3686
3687 MI.eraseFromParent();
3688 return Legalized;
3689}
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00003690
3691LegalizerHelper::LegalizeResult
3692LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
3693 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ?
3694 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE;
3695
3696 Register Dst = MI.getOperand(0).getReg();
3697 Register Src0 = MI.getOperand(1).getReg();
3698 Register Src1 = MI.getOperand(2).getReg();
3699 LLT Ty = MRI.getType(Dst);
3700
3701 if (!MI.getFlag(MachineInstr::FmNoNans)) {
3702 // Insert canonicalizes if it's possible we need to quiet to get correct
3703 // sNaN behavior.
3704
3705 // Note this must be done here, and not as an optimization combine in the
3706 // absence of a dedicate quiet-snan instruction as we're using an
3707 // omni-purpose G_FCANONICALIZE.
3708 if (!isKnownNeverSNaN(Src0, MRI))
3709 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);
3710
3711 if (!isKnownNeverSNaN(Src1, MRI))
3712 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
3713 }
3714
3715 // If there are no nans, it's safe to simply replace this with the non-IEEE
3716 // version.
3717 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags());
3718 MI.eraseFromParent();
3719 return Legalized;
3720}
Matt Arsenaultd9d30a42019-08-01 19:10:05 +00003721
3722LegalizerHelper::LegalizeResult
3723LegalizerHelper::lowerUnmergeValues(MachineInstr &MI) {
3724 const unsigned NumDst = MI.getNumOperands() - 1;
3725 const Register SrcReg = MI.getOperand(NumDst).getReg();
3726 LLT SrcTy = MRI.getType(SrcReg);
3727
3728 Register Dst0Reg = MI.getOperand(0).getReg();
3729 LLT DstTy = MRI.getType(Dst0Reg);
3730
3731
3732 // Expand scalarizing unmerge as bitcast to integer and shift.
3733 if (!DstTy.isVector() && SrcTy.isVector() &&
3734 SrcTy.getElementType() == DstTy) {
3735 LLT IntTy = LLT::scalar(SrcTy.getSizeInBits());
3736 Register Cast = MIRBuilder.buildBitcast(IntTy, SrcReg).getReg(0);
3737
3738 MIRBuilder.buildTrunc(Dst0Reg, Cast);
3739
3740 const unsigned DstSize = DstTy.getSizeInBits();
3741 unsigned Offset = DstSize;
3742 for (unsigned I = 1; I != NumDst; ++I, Offset += DstSize) {
3743 auto ShiftAmt = MIRBuilder.buildConstant(IntTy, Offset);
3744 auto Shift = MIRBuilder.buildLShr(IntTy, Cast, ShiftAmt);
3745 MIRBuilder.buildTrunc(MI.getOperand(I), Shift);
3746 }
3747
3748 MI.eraseFromParent();
3749 return Legalized;
3750 }
3751
3752 return UnableToLegalize;
3753}