blob: bf3cca4115a13f0e002f19ebabbf630a639e52bb [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);
Diana Picus02e11012017-06-15 10:53:31 +0000300 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
301 MachineOperand::CreateES(Name), Result, Args))
302 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000303
Diana Picuse97822e2017-04-24 07:22:31 +0000304 return LegalizerHelper::Legalized;
305}
306
Diana Picus65ed3642018-01-17 13:34:10 +0000307// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000308static LegalizerHelper::LegalizeResult
309simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
310 Type *OpType) {
311 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000312
313 SmallVector<CallLowering::ArgInfo, 3> Args;
314 for (unsigned i = 1; i < MI.getNumOperands(); i++)
315 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000316 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000317 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000318}
319
Diana Picus65ed3642018-01-17 13:34:10 +0000320static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
321 Type *FromType) {
322 auto ToMVT = MVT::getVT(ToType);
323 auto FromMVT = MVT::getVT(FromType);
324
325 switch (Opcode) {
326 case TargetOpcode::G_FPEXT:
327 return RTLIB::getFPEXT(FromMVT, ToMVT);
328 case TargetOpcode::G_FPTRUNC:
329 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000330 case TargetOpcode::G_FPTOSI:
331 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
332 case TargetOpcode::G_FPTOUI:
333 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000334 case TargetOpcode::G_SITOFP:
335 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
336 case TargetOpcode::G_UITOFP:
337 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000338 }
339 llvm_unreachable("Unsupported libcall function");
340}
341
342static LegalizerHelper::LegalizeResult
343conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
344 Type *FromType) {
345 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
346 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
347 {{MI.getOperand(1).getReg(), FromType}});
348}
349
Tim Northover69fa84a2016-10-14 22:18:18 +0000350LegalizerHelper::LegalizeResult
351LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000352 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
353 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000354 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000355
Diana Picusfc1675e2017-07-05 12:57:24 +0000356 MIRBuilder.setInstr(MI);
357
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000358 switch (MI.getOpcode()) {
359 default:
360 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000361 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000362 case TargetOpcode::G_UDIV:
363 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000364 case TargetOpcode::G_UREM:
365 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000366 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000367 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
368 if (Status != Legalized)
369 return Status;
370 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000371 }
Diana Picus1314a282017-04-11 10:52:34 +0000372 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000373 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000374 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000375 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000376 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000377 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000378 case TargetOpcode::G_FREM:
379 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000380 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000381 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000382 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000383 case TargetOpcode::G_FLOG2:
Jessica Paquettee7941212019-04-03 16:58:32 +0000384 case TargetOpcode::G_FEXP:
Petar Avramovicfaaa2b52019-06-06 09:02:24 +0000385 case TargetOpcode::G_FEXP2:
386 case TargetOpcode::G_FCEIL:
387 case TargetOpcode::G_FFLOOR: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000388 if (Size > 64) {
389 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
390 return UnableToLegalize;
391 }
Diana Picus02e11012017-06-15 10:53:31 +0000392 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000393 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
394 if (Status != Legalized)
395 return Status;
396 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000397 }
Diana Picus65ed3642018-01-17 13:34:10 +0000398 case TargetOpcode::G_FPEXT: {
399 // FIXME: Support other floating point types (half, fp128 etc)
400 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
401 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
402 if (ToSize != 64 || FromSize != 32)
403 return UnableToLegalize;
404 LegalizeResult Status = conversionLibcall(
405 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
406 if (Status != Legalized)
407 return Status;
408 break;
409 }
410 case TargetOpcode::G_FPTRUNC: {
411 // FIXME: Support other floating point types (half, fp128 etc)
412 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
413 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
414 if (ToSize != 32 || FromSize != 64)
415 return UnableToLegalize;
416 LegalizeResult Status = conversionLibcall(
417 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
418 if (Status != Legalized)
419 return Status;
420 break;
421 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000422 case TargetOpcode::G_FPTOSI:
423 case TargetOpcode::G_FPTOUI: {
424 // FIXME: Support other types
425 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
426 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000427 if ((ToSize != 32 && ToSize != 64) || (FromSize != 32 && FromSize != 64))
Diana Picus4ed0ee72018-01-30 07:54:52 +0000428 return UnableToLegalize;
429 LegalizeResult Status = conversionLibcall(
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000430 MI, MIRBuilder,
431 ToSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx),
Diana Picus4ed0ee72018-01-30 07:54:52 +0000432 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
433 if (Status != Legalized)
434 return Status;
435 break;
436 }
Diana Picus517531e2018-01-30 09:15:17 +0000437 case TargetOpcode::G_SITOFP:
438 case TargetOpcode::G_UITOFP: {
439 // FIXME: Support other types
440 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
441 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic153bd242019-06-20 09:05:02 +0000442 if ((FromSize != 32 && FromSize != 64) || (ToSize != 32 && ToSize != 64))
Diana Picus517531e2018-01-30 09:15:17 +0000443 return UnableToLegalize;
444 LegalizeResult Status = conversionLibcall(
445 MI, MIRBuilder,
446 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
Petar Avramovic153bd242019-06-20 09:05:02 +0000447 FromSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx));
Diana Picus517531e2018-01-30 09:15:17 +0000448 if (Status != Legalized)
449 return Status;
450 break;
451 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000452 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000453
454 MI.eraseFromParent();
455 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000456}
457
Tim Northover69fa84a2016-10-14 22:18:18 +0000458LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
459 unsigned TypeIdx,
460 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000461 MIRBuilder.setInstr(MI);
462
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000463 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
464 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000465
Tim Northover9656f142016-08-04 20:54:13 +0000466 switch (MI.getOpcode()) {
467 default:
468 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000469 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000470 // FIXME: add support for when SizeOp0 isn't an exact multiple of
471 // NarrowSize.
472 if (SizeOp0 % NarrowSize != 0)
473 return UnableToLegalize;
474 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000475
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000476 SmallVector<Register, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000477 for (int i = 0; i < NumParts; ++i)
478 DstRegs.push_back(
479 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000480
Matt Arsenault3018d182019-06-28 01:47:44 +0000481 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000482 if(MRI.getType(DstReg).isVector())
483 MIRBuilder.buildBuildVector(DstReg, DstRegs);
484 else
485 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000486 MI.eraseFromParent();
487 return Legalized;
488 }
Matt Arsenault71872722019-04-10 17:27:53 +0000489 case TargetOpcode::G_CONSTANT: {
490 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
491 const APInt &Val = MI.getOperand(1).getCImm()->getValue();
492 unsigned TotalSize = Ty.getSizeInBits();
493 unsigned NarrowSize = NarrowTy.getSizeInBits();
494 int NumParts = TotalSize / NarrowSize;
495
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000496 SmallVector<Register, 4> PartRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000497 for (int I = 0; I != NumParts; ++I) {
498 unsigned Offset = I * NarrowSize;
499 auto K = MIRBuilder.buildConstant(NarrowTy,
500 Val.lshr(Offset).trunc(NarrowSize));
501 PartRegs.push_back(K.getReg(0));
502 }
503
504 LLT LeftoverTy;
505 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000506 SmallVector<Register, 1> LeftoverRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000507 if (LeftoverBits != 0) {
508 LeftoverTy = LLT::scalar(LeftoverBits);
509 auto K = MIRBuilder.buildConstant(
510 LeftoverTy,
511 Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits));
512 LeftoverRegs.push_back(K.getReg(0));
513 }
514
515 insertParts(MI.getOperand(0).getReg(),
516 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
517
518 MI.eraseFromParent();
519 return Legalized;
520 }
Tim Northover9656f142016-08-04 20:54:13 +0000521 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000522 // FIXME: add support for when SizeOp0 isn't an exact multiple of
523 // NarrowSize.
524 if (SizeOp0 % NarrowSize != 0)
525 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000526 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000527 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000528
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000529 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000530 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
531 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
532
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000533 Register CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover0f140c72016-09-09 11:46:34 +0000534 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000535
536 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000537 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
538 Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000539
Tim Northover0f140c72016-09-09 11:46:34 +0000540 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000541 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000542
543 DstRegs.push_back(DstReg);
544 CarryIn = CarryOut;
545 }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000546 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000547 if(MRI.getType(DstReg).isVector())
548 MIRBuilder.buildBuildVector(DstReg, DstRegs);
549 else
550 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000551 MI.eraseFromParent();
552 return Legalized;
553 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000554 case TargetOpcode::G_SUB: {
555 // FIXME: add support for when SizeOp0 isn't an exact multiple of
556 // NarrowSize.
557 if (SizeOp0 % NarrowSize != 0)
558 return UnableToLegalize;
559
560 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
561
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000562 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000563 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
564 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
565
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000566 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
567 Register BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000568 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
569 {Src1Regs[0], Src2Regs[0]});
570 DstRegs.push_back(DstReg);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000571 Register BorrowIn = BorrowOut;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000572 for (int i = 1; i < NumParts; ++i) {
573 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
574 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
575
576 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
577 {Src1Regs[i], Src2Regs[i], BorrowIn});
578
579 DstRegs.push_back(DstReg);
580 BorrowIn = BorrowOut;
581 }
582 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
583 MI.eraseFromParent();
584 return Legalized;
585 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000586 case TargetOpcode::G_MUL:
Petar Avramovic5229f472019-03-11 10:08:44 +0000587 case TargetOpcode::G_UMULH:
Petar Avramovic0b17e592019-03-11 10:00:17 +0000588 return narrowScalarMul(MI, NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +0000589 case TargetOpcode::G_EXTRACT:
590 return narrowScalarExtract(MI, TypeIdx, NarrowTy);
591 case TargetOpcode::G_INSERT:
592 return narrowScalarInsert(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000593 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000594 const auto &MMO = **MI.memoperands_begin();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000595 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000596 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000597 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000598 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000599
600 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000601 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000602 auto &MMO = **MI.memoperands_begin();
603 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
604 MIRBuilder.buildAnyExt(DstReg, TmpReg);
605 MI.eraseFromParent();
606 return Legalized;
607 }
608
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000609 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000610 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000611 case TargetOpcode::G_ZEXTLOAD:
612 case TargetOpcode::G_SEXTLOAD: {
613 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000614 Register DstReg = MI.getOperand(0).getReg();
615 Register PtrReg = MI.getOperand(1).getReg();
Matt Arsenault6614f852019-01-22 19:02:10 +0000616
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000617 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault6614f852019-01-22 19:02:10 +0000618 auto &MMO = **MI.memoperands_begin();
Amara Emersond51adf02019-04-17 22:21:05 +0000619 if (MMO.getSizeInBits() == NarrowSize) {
Matt Arsenault6614f852019-01-22 19:02:10 +0000620 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
621 } else {
622 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
623 : TargetOpcode::G_SEXTLOAD;
624 MIRBuilder.buildInstr(ExtLoad)
625 .addDef(TmpReg)
626 .addUse(PtrReg)
627 .addMemOperand(&MMO);
628 }
629
630 if (ZExt)
631 MIRBuilder.buildZExt(DstReg, TmpReg);
632 else
633 MIRBuilder.buildSExt(DstReg, TmpReg);
634
635 MI.eraseFromParent();
636 return Legalized;
637 }
Justin Bognerfde01042017-01-18 17:29:54 +0000638 case TargetOpcode::G_STORE: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000639 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000640
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000641 Register SrcReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000642 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000643 if (SrcTy.isVector())
644 return UnableToLegalize;
645
646 int NumParts = SizeOp0 / NarrowSize;
647 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
648 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
649 if (SrcTy.isVector() && LeftoverBits != 0)
650 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000651
652 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000653 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000654 auto &MMO = **MI.memoperands_begin();
655 MIRBuilder.buildTrunc(TmpReg, SrcReg);
656 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
657 MI.eraseFromParent();
658 return Legalized;
659 }
660
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000661 return reduceLoadStoreWidth(MI, 0, NarrowTy);
Justin Bognerfde01042017-01-18 17:29:54 +0000662 }
Matt Arsenault81511e52019-02-05 00:13:44 +0000663 case TargetOpcode::G_SELECT:
664 return narrowScalarSelect(MI, TypeIdx, NarrowTy);
Petar Avramovic150fd432018-12-18 11:36:14 +0000665 case TargetOpcode::G_AND:
666 case TargetOpcode::G_OR:
667 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000668 // Legalize bitwise operation:
669 // A = BinOp<Ty> B, C
670 // into:
671 // B1, ..., BN = G_UNMERGE_VALUES B
672 // C1, ..., CN = G_UNMERGE_VALUES C
673 // A1 = BinOp<Ty/N> B1, C2
674 // ...
675 // AN = BinOp<Ty/N> BN, CN
676 // A = G_MERGE_VALUES A1, ..., AN
Matt Arsenault9e0eeba2019-04-10 17:07:56 +0000677 return narrowScalarBasic(MI, TypeIdx, NarrowTy);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000678 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000679 case TargetOpcode::G_SHL:
680 case TargetOpcode::G_LSHR:
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +0000681 case TargetOpcode::G_ASHR:
682 return narrowScalarShift(MI, TypeIdx, NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000683 case TargetOpcode::G_CTLZ:
684 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
685 case TargetOpcode::G_CTTZ:
686 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
687 case TargetOpcode::G_CTPOP:
688 if (TypeIdx != 0)
689 return UnableToLegalize; // TODO
690
691 Observer.changingInstr(MI);
692 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
693 Observer.changedInstr(MI);
694 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000695 case TargetOpcode::G_INTTOPTR:
696 if (TypeIdx != 1)
697 return UnableToLegalize;
698
699 Observer.changingInstr(MI);
700 narrowScalarSrc(MI, NarrowTy, 1);
701 Observer.changedInstr(MI);
702 return Legalized;
703 case TargetOpcode::G_PTRTOINT:
704 if (TypeIdx != 0)
705 return UnableToLegalize;
706
707 Observer.changingInstr(MI);
708 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
709 Observer.changedInstr(MI);
710 return Legalized;
Petar Avramovicbe20e362019-07-09 14:36:17 +0000711 case TargetOpcode::G_PHI: {
712 unsigned NumParts = SizeOp0 / NarrowSize;
713 SmallVector<Register, 2> DstRegs;
714 SmallVector<SmallVector<Register, 2>, 2> SrcRegs;
715 DstRegs.resize(NumParts);
716 SrcRegs.resize(MI.getNumOperands() / 2);
717 Observer.changingInstr(MI);
718 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
719 MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB();
720 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
721 extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts,
722 SrcRegs[i / 2]);
723 }
724 MachineBasicBlock &MBB = *MI.getParent();
725 MIRBuilder.setInsertPt(MBB, MI);
726 for (unsigned i = 0; i < NumParts; ++i) {
727 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
728 MachineInstrBuilder MIB =
729 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
730 for (unsigned j = 1; j < MI.getNumOperands(); j += 2)
731 MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1));
732 }
733 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
734 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
735 Observer.changedInstr(MI);
736 MI.eraseFromParent();
737 return Legalized;
738 }
Matt Arsenault434d6642019-07-15 19:37:34 +0000739 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
740 case TargetOpcode::G_INSERT_VECTOR_ELT: {
741 if (TypeIdx != 2)
742 return UnableToLegalize;
743
744 int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
745 Observer.changingInstr(MI);
746 narrowScalarSrc(MI, NarrowTy, OpIdx);
747 Observer.changedInstr(MI);
748 return Legalized;
749 }
Tim Northover9656f142016-08-04 20:54:13 +0000750 }
Tim Northover33b07d62016-07-22 20:03:43 +0000751}
752
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000753void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
754 unsigned OpIdx, unsigned ExtOpcode) {
755 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000756 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000757 MO.setReg(ExtB->getOperand(0).getReg());
758}
759
Matt Arsenault30989e42019-01-22 21:42:11 +0000760void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
761 unsigned OpIdx) {
762 MachineOperand &MO = MI.getOperand(OpIdx);
763 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
764 {MO.getReg()});
765 MO.setReg(ExtB->getOperand(0).getReg());
766}
767
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000768void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
769 unsigned OpIdx, unsigned TruncOpcode) {
770 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000771 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000772 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000773 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000774 MO.setReg(DstExt);
775}
776
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000777void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
778 unsigned OpIdx, unsigned ExtOpcode) {
779 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000780 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000781 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
782 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
783 MO.setReg(DstTrunc);
784}
785
Matt Arsenault18ec3822019-02-11 22:00:39 +0000786void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy,
787 unsigned OpIdx) {
788 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000789 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000790 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
791 MIRBuilder.buildExtract(MO.getReg(), DstExt, 0);
792 MO.setReg(DstExt);
793}
794
Matt Arsenault26b7e852019-02-19 16:30:19 +0000795void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy,
796 unsigned OpIdx) {
797 MachineOperand &MO = MI.getOperand(OpIdx);
798
799 LLT OldTy = MRI.getType(MO.getReg());
800 unsigned OldElts = OldTy.getNumElements();
801 unsigned NewElts = MoreTy.getNumElements();
802
803 unsigned NumParts = NewElts / OldElts;
804
805 // Use concat_vectors if the result is a multiple of the number of elements.
806 if (NumParts * OldElts == NewElts) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000807 SmallVector<Register, 8> Parts;
Matt Arsenault26b7e852019-02-19 16:30:19 +0000808 Parts.push_back(MO.getReg());
809
Matt Arsenault3018d182019-06-28 01:47:44 +0000810 Register ImpDef = MIRBuilder.buildUndef(OldTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +0000811 for (unsigned I = 1; I != NumParts; ++I)
812 Parts.push_back(ImpDef);
813
814 auto Concat = MIRBuilder.buildConcatVectors(MoreTy, Parts);
815 MO.setReg(Concat.getReg(0));
816 return;
817 }
818
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000819 Register MoreReg = MRI.createGenericVirtualRegister(MoreTy);
820 Register ImpDef = MIRBuilder.buildUndef(MoreTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +0000821 MIRBuilder.buildInsert(MoreReg, ImpDef, MO.getReg(), 0);
822 MO.setReg(MoreReg);
823}
824
Tim Northover69fa84a2016-10-14 22:18:18 +0000825LegalizerHelper::LegalizeResult
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000826LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
827 LLT WideTy) {
828 if (TypeIdx != 1)
829 return UnableToLegalize;
830
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000831 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000832 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault43cbca52019-07-03 23:08:06 +0000833 if (DstTy.isVector())
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000834 return UnableToLegalize;
835
Matt Arsenaultc9f14f22019-07-01 19:36:10 +0000836 Register Src1 = MI.getOperand(1).getReg();
837 LLT SrcTy = MRI.getType(Src1);
838 int NumMerge = DstTy.getSizeInBits() / WideTy.getSizeInBits();
839
840 // Try to turn this into a merge of merges if we can use the requested type as
841 // the source.
842
843 // TODO: Pad with undef if DstTy > WideTy
844 if (NumMerge > 1 && WideTy.getSizeInBits() % SrcTy.getSizeInBits() == 0) {
845 int PartsPerMerge = WideTy.getSizeInBits() / SrcTy.getSizeInBits();
846 SmallVector<Register, 4> Parts;
847 SmallVector<Register, 4> SubMerges;
848
849 for (int I = 0; I != NumMerge; ++I) {
850 for (int J = 0; J != PartsPerMerge; ++J)
851 Parts.push_back(MI.getOperand(I * PartsPerMerge + J + 1).getReg());
852
853 auto SubMerge = MIRBuilder.buildMerge(WideTy, Parts);
854 SubMerges.push_back(SubMerge.getReg(0));
855 Parts.clear();
856 }
857
858 MIRBuilder.buildMerge(DstReg, SubMerges);
859 MI.eraseFromParent();
860 return Legalized;
861 }
862
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000863 unsigned NumOps = MI.getNumOperands();
864 unsigned NumSrc = MI.getNumOperands() - 1;
865 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
866
Matt Arsenaultc9f14f22019-07-01 19:36:10 +0000867 Register ResultReg = MIRBuilder.buildZExt(DstTy, Src1).getReg(0);
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000868
869 for (unsigned I = 2; I != NumOps; ++I) {
870 const unsigned Offset = (I - 1) * PartSize;
871
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000872 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000873 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
874
875 auto ZextInput = MIRBuilder.buildZExt(DstTy, SrcReg);
876
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000877 Register NextResult = I + 1 == NumOps ? DstReg :
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000878 MRI.createGenericVirtualRegister(DstTy);
879
880 auto ShiftAmt = MIRBuilder.buildConstant(DstTy, Offset);
881 auto Shl = MIRBuilder.buildShl(DstTy, ZextInput, ShiftAmt);
882 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
883 ResultReg = NextResult;
884 }
885
886 MI.eraseFromParent();
887 return Legalized;
888}
889
890LegalizerHelper::LegalizeResult
891LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
892 LLT WideTy) {
893 if (TypeIdx != 0)
894 return UnableToLegalize;
895
896 unsigned NumDst = MI.getNumOperands() - 1;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000897 Register SrcReg = MI.getOperand(NumDst).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000898 LLT SrcTy = MRI.getType(SrcReg);
899 if (!SrcTy.isScalar())
900 return UnableToLegalize;
901
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000902 Register Dst0Reg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000903 LLT DstTy = MRI.getType(Dst0Reg);
904 if (!DstTy.isScalar())
905 return UnableToLegalize;
906
907 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
908 LLT NewSrcTy = LLT::scalar(NewSrcSize);
909 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
910
911 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
912
913 for (unsigned I = 1; I != NumDst; ++I) {
914 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
915 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
916 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
917 }
918
919 Observer.changingInstr(MI);
920
921 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
922 for (unsigned I = 0; I != NumDst; ++I)
923 widenScalarDst(MI, WideTy, I);
924
925 Observer.changedInstr(MI);
926
927 return Legalized;
928}
929
930LegalizerHelper::LegalizeResult
Matt Arsenault1cf71362019-02-12 14:54:52 +0000931LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
932 LLT WideTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000933 Register DstReg = MI.getOperand(0).getReg();
934 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +0000935 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenaultfbe92a52019-02-18 22:39:27 +0000936
937 LLT DstTy = MRI.getType(DstReg);
938 unsigned Offset = MI.getOperand(2).getImm();
939
940 if (TypeIdx == 0) {
941 if (SrcTy.isVector() || DstTy.isVector())
942 return UnableToLegalize;
943
944 SrcOp Src(SrcReg);
945 if (SrcTy.isPointer()) {
946 // Extracts from pointers can be handled only if they are really just
947 // simple integers.
948 const DataLayout &DL = MIRBuilder.getDataLayout();
949 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
950 return UnableToLegalize;
951
952 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
953 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
954 SrcTy = SrcAsIntTy;
955 }
956
957 if (DstTy.isPointer())
958 return UnableToLegalize;
959
960 if (Offset == 0) {
961 // Avoid a shift in the degenerate case.
962 MIRBuilder.buildTrunc(DstReg,
963 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
964 MI.eraseFromParent();
965 return Legalized;
966 }
967
968 // Do a shift in the source type.
969 LLT ShiftTy = SrcTy;
970 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
971 Src = MIRBuilder.buildAnyExt(WideTy, Src);
972 ShiftTy = WideTy;
973 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits())
974 return UnableToLegalize;
975
976 auto LShr = MIRBuilder.buildLShr(
977 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
978 MIRBuilder.buildTrunc(DstReg, LShr);
979 MI.eraseFromParent();
980 return Legalized;
981 }
982
Matt Arsenault8f624ab2019-04-22 15:10:42 +0000983 if (SrcTy.isScalar()) {
984 Observer.changingInstr(MI);
985 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
986 Observer.changedInstr(MI);
987 return Legalized;
988 }
989
Matt Arsenault1cf71362019-02-12 14:54:52 +0000990 if (!SrcTy.isVector())
991 return UnableToLegalize;
992
Matt Arsenault1cf71362019-02-12 14:54:52 +0000993 if (DstTy != SrcTy.getElementType())
994 return UnableToLegalize;
995
Matt Arsenault1cf71362019-02-12 14:54:52 +0000996 if (Offset % SrcTy.getScalarSizeInBits() != 0)
997 return UnableToLegalize;
998
999 Observer.changingInstr(MI);
1000 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1001
1002 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
1003 Offset);
1004 widenScalarDst(MI, WideTy.getScalarType(), 0);
1005 Observer.changedInstr(MI);
1006 return Legalized;
1007}
1008
1009LegalizerHelper::LegalizeResult
1010LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
1011 LLT WideTy) {
1012 if (TypeIdx != 0)
1013 return UnableToLegalize;
1014 Observer.changingInstr(MI);
1015 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1016 widenScalarDst(MI, WideTy);
1017 Observer.changedInstr(MI);
1018 return Legalized;
1019}
1020
1021LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001022LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +00001023 MIRBuilder.setInstr(MI);
1024
Tim Northover32335812016-08-04 18:35:11 +00001025 switch (MI.getOpcode()) {
1026 default:
1027 return UnableToLegalize;
Matt Arsenault1cf71362019-02-12 14:54:52 +00001028 case TargetOpcode::G_EXTRACT:
1029 return widenScalarExtract(MI, TypeIdx, WideTy);
1030 case TargetOpcode::G_INSERT:
1031 return widenScalarInsert(MI, TypeIdx, WideTy);
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001032 case TargetOpcode::G_MERGE_VALUES:
1033 return widenScalarMergeValues(MI, TypeIdx, WideTy);
1034 case TargetOpcode::G_UNMERGE_VALUES:
1035 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001036 case TargetOpcode::G_UADDO:
1037 case TargetOpcode::G_USUBO: {
1038 if (TypeIdx == 1)
1039 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001040 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1041 {MI.getOperand(2).getReg()});
1042 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1043 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001044 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
1045 ? TargetOpcode::G_ADD
1046 : TargetOpcode::G_SUB;
1047 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001048 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001049 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
1050 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
1051 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001052 TargetOpcode::G_AND, {WideTy},
1053 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001054 // There is no overflow if the AndOp is the same as NewOp.
1055 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1056 AndOp);
1057 // Now trunc the NewOp to the original result.
1058 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1059 MI.eraseFromParent();
1060 return Legalized;
1061 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001062 case TargetOpcode::G_CTTZ:
1063 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1064 case TargetOpcode::G_CTLZ:
1065 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1066 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001067 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001068 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001069 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001070 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001071 return Legalized;
1072 }
1073
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001074 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001075
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001076 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001077 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1078 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001079 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1080 // The count is the same in the larger type except if the original
1081 // value was zero. This can be handled by setting the bit just off
1082 // the top of the original type.
1083 auto TopBit =
1084 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001085 MIBSrc = MIRBuilder.buildOr(
1086 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001087 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001088
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001089 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001090 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001091 // This is already the correct result for CTPOP and CTTZs
1092 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1093 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1094 // The correct result is NewOp - (Difference in widety and current ty).
1095 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001096 MIBNewOp = MIRBuilder.buildInstr(
1097 TargetOpcode::G_SUB, {WideTy},
1098 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001099 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001100
1101 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1102 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001103 return Legalized;
1104 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001105 case TargetOpcode::G_BSWAP: {
1106 Observer.changingInstr(MI);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001107 Register DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001108
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001109 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
1110 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
1111 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001112 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1113
1114 MI.getOperand(0).setReg(DstExt);
1115
1116 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1117
1118 LLT Ty = MRI.getType(DstReg);
1119 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1120 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1121 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1122 .addDef(ShrReg)
1123 .addUse(DstExt)
1124 .addUse(ShiftAmtReg);
1125
1126 MIRBuilder.buildTrunc(DstReg, ShrReg);
1127 Observer.changedInstr(MI);
1128 return Legalized;
1129 }
Tim Northover61c16142016-08-04 21:39:49 +00001130 case TargetOpcode::G_ADD:
1131 case TargetOpcode::G_AND:
1132 case TargetOpcode::G_MUL:
1133 case TargetOpcode::G_OR:
1134 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001135 case TargetOpcode::G_SUB:
Matt Arsenault1cf71362019-02-12 14:54:52 +00001136 // Perform operation at larger width (any extension is fines here, high bits
Tim Northover32335812016-08-04 18:35:11 +00001137 // don't affect the result) and then truncate the result back to the
1138 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001139 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001140 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1141 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1142 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001143 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001144 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001145
Roman Tereshin6d266382018-05-09 21:43:30 +00001146 case TargetOpcode::G_SHL:
Matt Arsenault012ecbb2019-05-16 04:08:46 +00001147 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001148
1149 if (TypeIdx == 0) {
1150 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1151 widenScalarDst(MI, WideTy);
1152 } else {
1153 assert(TypeIdx == 1);
1154 // The "number of bits to shift" operand must preserve its value as an
1155 // unsigned integer:
1156 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1157 }
1158
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001159 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001160 return Legalized;
1161
Tim Northover7a753d92016-08-26 17:46:06 +00001162 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001163 case TargetOpcode::G_SREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001164 case TargetOpcode::G_SMIN:
1165 case TargetOpcode::G_SMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001166 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001167 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1168 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1169 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001170 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001171 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001172
Roman Tereshin6d266382018-05-09 21:43:30 +00001173 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001174 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001175 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001176
1177 if (TypeIdx == 0) {
1178 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1179 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1180
1181 widenScalarSrc(MI, WideTy, 1, CvtOp);
1182 widenScalarDst(MI, WideTy);
1183 } else {
1184 assert(TypeIdx == 1);
1185 // The "number of bits to shift" operand must preserve its value as an
1186 // unsigned integer:
1187 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1188 }
1189
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001190 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001191 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001192 case TargetOpcode::G_UDIV:
1193 case TargetOpcode::G_UREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001194 case TargetOpcode::G_UMIN:
1195 case TargetOpcode::G_UMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001196 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001197 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1198 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1199 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001200 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001201 return Legalized;
1202
1203 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001204 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001205 if (TypeIdx == 0) {
1206 // Perform operation at larger width (any extension is fine here, high
1207 // bits don't affect the result) and then truncate the result back to the
1208 // original type.
1209 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1210 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1211 widenScalarDst(MI, WideTy);
1212 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001213 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001214 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001215 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001216 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001217 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001218 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001219
Ahmed Bougachab6137062017-01-23 21:10:14 +00001220 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001221 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001222 if (TypeIdx != 0)
1223 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001224 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001225 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001226 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001227 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001228
Ahmed Bougachad2948232017-01-20 01:37:24 +00001229 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001230 if (TypeIdx != 1)
1231 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001232 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001233 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001234 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001235 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001236
1237 case TargetOpcode::G_UITOFP:
1238 if (TypeIdx != 1)
1239 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001240 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001241 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001242 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001243 return Legalized;
1244
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001245 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001246 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001247 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001248 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001249 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001250 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001251 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001252
Tim Northover3c73e362016-08-23 18:20:09 +00001253 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001254 if (TypeIdx != 0)
1255 return UnableToLegalize;
1256
1257 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1258 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001259 return UnableToLegalize;
1260
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001261 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001262
1263 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1264 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1265 widenScalarSrc(MI, WideTy, 0, ExtType);
1266
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001267 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001268 return Legalized;
1269 }
Tim Northoverea904f92016-08-19 22:40:00 +00001270 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001271 MachineOperand &SrcMO = MI.getOperand(1);
1272 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1273 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001274 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001275 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1276
1277 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001278 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001279 return Legalized;
1280 }
Tim Northovera11be042016-08-19 22:40:08 +00001281 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001282 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001283 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001284 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001285 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001286 switch (WideTy.getSizeInBits()) {
1287 case 32:
Matt Arsenault996c6662019-02-12 14:54:54 +00001288 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
1289 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001290 break;
1291 case 64:
Matt Arsenault996c6662019-02-12 14:54:54 +00001292 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
1293 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001294 break;
1295 default:
Matt Arsenault996c6662019-02-12 14:54:54 +00001296 return UnableToLegalize;
Tim Northover6cd4b232016-08-23 21:01:26 +00001297 }
Matt Arsenault996c6662019-02-12 14:54:54 +00001298
1299 assert(!LosesInfo && "extend should always be lossless");
1300
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001301 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001302 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1303
1304 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001305 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001306 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001307 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001308 case TargetOpcode::G_IMPLICIT_DEF: {
1309 Observer.changingInstr(MI);
1310 widenScalarDst(MI, WideTy);
1311 Observer.changedInstr(MI);
1312 return Legalized;
1313 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001314 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001315 Observer.changingInstr(MI);
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +00001316 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001317 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001318 return Legalized;
1319
1320 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001321 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001322 if (TypeIdx == 0)
1323 widenScalarDst(MI, WideTy);
1324 else {
1325 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1326 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001327 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001328 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001329 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001330
1331 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001332 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001333 if (TypeIdx == 0)
1334 widenScalarDst(MI, WideTy);
1335 else {
1336 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1337 MI.getOperand(1).getPredicate()))
1338 ? TargetOpcode::G_SEXT
1339 : TargetOpcode::G_ZEXT;
1340 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1341 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1342 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001343 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001344 return Legalized;
1345
1346 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001347 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001348 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001349 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001350 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001351 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001352
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001353 case TargetOpcode::G_PHI: {
1354 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001355
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001356 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001357 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1358 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1359 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1360 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001361 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001362
1363 MachineBasicBlock &MBB = *MI.getParent();
1364 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1365 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001366 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001367 return Legalized;
1368 }
Matt Arsenault63786292019-01-22 20:38:15 +00001369 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1370 if (TypeIdx == 0) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001371 Register VecReg = MI.getOperand(1).getReg();
Matt Arsenault63786292019-01-22 20:38:15 +00001372 LLT VecTy = MRI.getType(VecReg);
1373 Observer.changingInstr(MI);
1374
1375 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1376 WideTy.getSizeInBits()),
1377 1, TargetOpcode::G_SEXT);
1378
1379 widenScalarDst(MI, WideTy, 0);
1380 Observer.changedInstr(MI);
1381 return Legalized;
1382 }
1383
Amara Emersoncbd86d82018-10-25 14:04:54 +00001384 if (TypeIdx != 2)
1385 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001386 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001387 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001388 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001389 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001390 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001391 case TargetOpcode::G_FADD:
1392 case TargetOpcode::G_FMUL:
1393 case TargetOpcode::G_FSUB:
1394 case TargetOpcode::G_FMA:
1395 case TargetOpcode::G_FNEG:
1396 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001397 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001398 case TargetOpcode::G_FMINNUM:
1399 case TargetOpcode::G_FMAXNUM:
1400 case TargetOpcode::G_FMINNUM_IEEE:
1401 case TargetOpcode::G_FMAXNUM_IEEE:
1402 case TargetOpcode::G_FMINIMUM:
1403 case TargetOpcode::G_FMAXIMUM:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001404 case TargetOpcode::G_FDIV:
1405 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001406 case TargetOpcode::G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00001407 case TargetOpcode::G_FFLOOR:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001408 case TargetOpcode::G_FCOS:
1409 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001410 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001411 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001412 case TargetOpcode::G_FLOG2:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00001413 case TargetOpcode::G_FRINT:
Jessica Paquetteba557672019-04-25 16:44:40 +00001414 case TargetOpcode::G_FNEARBYINT:
Jessica Paquette22457f82019-01-30 21:03:52 +00001415 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001416 case TargetOpcode::G_FEXP:
Jessica Paquettee7941212019-04-03 16:58:32 +00001417 case TargetOpcode::G_FEXP2:
Jessica Paquettedfd87f62019-04-19 16:28:08 +00001418 case TargetOpcode::G_FPOW:
Jessica Paquette56342642019-04-23 18:20:44 +00001419 case TargetOpcode::G_INTRINSIC_TRUNC:
Jessica Paquette3cc6d1f2019-04-23 21:11:57 +00001420 case TargetOpcode::G_INTRINSIC_ROUND:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001421 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001422 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001423
1424 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1425 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1426
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001427 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1428 Observer.changedInstr(MI);
1429 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001430 case TargetOpcode::G_INTTOPTR:
1431 if (TypeIdx != 1)
1432 return UnableToLegalize;
1433
1434 Observer.changingInstr(MI);
1435 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1436 Observer.changedInstr(MI);
1437 return Legalized;
1438 case TargetOpcode::G_PTRTOINT:
1439 if (TypeIdx != 0)
1440 return UnableToLegalize;
1441
1442 Observer.changingInstr(MI);
1443 widenScalarDst(MI, WideTy, 0);
1444 Observer.changedInstr(MI);
1445 return Legalized;
Matt Arsenaultbd791b52019-07-08 13:48:06 +00001446 case TargetOpcode::G_BUILD_VECTOR: {
1447 Observer.changingInstr(MI);
1448
1449 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType();
1450 for (int I = 1, E = MI.getNumOperands(); I != E; ++I)
1451 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT);
1452
1453 // Avoid changing the result vector type if the source element type was
1454 // requested.
1455 if (TypeIdx == 1) {
1456 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
1457 MI.setDesc(TII.get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
1458 } else {
1459 widenScalarDst(MI, WideTy, 0);
1460 }
1461
1462 Observer.changedInstr(MI);
1463 return Legalized;
1464 }
Tim Northover32335812016-08-04 18:35:11 +00001465 }
Tim Northover33b07d62016-07-22 20:03:43 +00001466}
1467
Tim Northover69fa84a2016-10-14 22:18:18 +00001468LegalizerHelper::LegalizeResult
1469LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001470 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001471 MIRBuilder.setInstr(MI);
1472
1473 switch(MI.getOpcode()) {
1474 default:
1475 return UnableToLegalize;
1476 case TargetOpcode::G_SREM:
1477 case TargetOpcode::G_UREM: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001478 Register QuotReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001479 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001480 .addDef(QuotReg)
1481 .addUse(MI.getOperand(1).getReg())
1482 .addUse(MI.getOperand(2).getReg());
1483
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001484 Register ProdReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001485 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1486 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1487 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001488 MI.eraseFromParent();
1489 return Legalized;
1490 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001491 case TargetOpcode::G_SMULO:
1492 case TargetOpcode::G_UMULO: {
1493 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1494 // result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001495 Register Res = MI.getOperand(0).getReg();
1496 Register Overflow = MI.getOperand(1).getReg();
1497 Register LHS = MI.getOperand(2).getReg();
1498 Register RHS = MI.getOperand(3).getReg();
Tim Northover0a9b2792017-02-08 21:22:15 +00001499
1500 MIRBuilder.buildMul(Res, LHS, RHS);
1501
1502 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1503 ? TargetOpcode::G_SMULH
1504 : TargetOpcode::G_UMULH;
1505
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001506 Register HiPart = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001507 MIRBuilder.buildInstr(Opcode)
1508 .addDef(HiPart)
1509 .addUse(LHS)
1510 .addUse(RHS);
1511
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001512 Register Zero = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001513 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001514
1515 // For *signed* multiply, overflow is detected by checking:
1516 // (hi != (lo >> bitwidth-1))
1517 if (Opcode == TargetOpcode::G_SMULH) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001518 Register Shifted = MRI.createGenericVirtualRegister(Ty);
1519 Register ShiftAmt = MRI.createGenericVirtualRegister(Ty);
Amara Emerson9de62132018-01-03 04:56:56 +00001520 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1521 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1522 .addDef(Shifted)
1523 .addUse(Res)
1524 .addUse(ShiftAmt);
1525 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1526 } else {
1527 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1528 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001529 MI.eraseFromParent();
1530 return Legalized;
1531 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001532 case TargetOpcode::G_FNEG: {
1533 // TODO: Handle vector types once we are able to
1534 // represent them.
1535 if (Ty.isVector())
1536 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001537 Register Res = MI.getOperand(0).getReg();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001538 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001539 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001540 switch (Ty.getSizeInBits()) {
1541 case 16:
1542 ZeroTy = Type::getHalfTy(Ctx);
1543 break;
1544 case 32:
1545 ZeroTy = Type::getFloatTy(Ctx);
1546 break;
1547 case 64:
1548 ZeroTy = Type::getDoubleTy(Ctx);
1549 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001550 case 128:
1551 ZeroTy = Type::getFP128Ty(Ctx);
1552 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001553 default:
1554 llvm_unreachable("unexpected floating-point type");
1555 }
1556 ConstantFP &ZeroForNegation =
1557 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001558 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001559 Register SubByReg = MI.getOperand(1).getReg();
1560 Register ZeroReg = Zero->getOperand(0).getReg();
Michael Bergd573aa02019-04-18 18:48:57 +00001561 MIRBuilder.buildInstr(TargetOpcode::G_FSUB, {Res}, {ZeroReg, SubByReg},
Matt Arsenault5a321b82019-06-17 23:48:43 +00001562 MI.getFlags());
Volkan Keles5698b2a2017-03-08 18:09:14 +00001563 MI.eraseFromParent();
1564 return Legalized;
1565 }
Volkan Keles225921a2017-03-10 21:25:09 +00001566 case TargetOpcode::G_FSUB: {
1567 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1568 // First, check if G_FNEG is marked as Lower. If so, we may
1569 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001570 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001571 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001572 Register Res = MI.getOperand(0).getReg();
1573 Register LHS = MI.getOperand(1).getReg();
1574 Register RHS = MI.getOperand(2).getReg();
1575 Register Neg = MRI.createGenericVirtualRegister(Ty);
Volkan Keles225921a2017-03-10 21:25:09 +00001576 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
Michael Bergd573aa02019-04-18 18:48:57 +00001577 MIRBuilder.buildInstr(TargetOpcode::G_FADD, {Res}, {LHS, Neg}, MI.getFlags());
Volkan Keles225921a2017-03-10 21:25:09 +00001578 MI.eraseFromParent();
1579 return Legalized;
1580 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001581 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001582 Register OldValRes = MI.getOperand(0).getReg();
1583 Register SuccessRes = MI.getOperand(1).getReg();
1584 Register Addr = MI.getOperand(2).getReg();
1585 Register CmpVal = MI.getOperand(3).getReg();
1586 Register NewVal = MI.getOperand(4).getReg();
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001587 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1588 **MI.memoperands_begin());
1589 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1590 MI.eraseFromParent();
1591 return Legalized;
1592 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001593 case TargetOpcode::G_LOAD:
1594 case TargetOpcode::G_SEXTLOAD:
1595 case TargetOpcode::G_ZEXTLOAD: {
1596 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001597 Register DstReg = MI.getOperand(0).getReg();
1598 Register PtrReg = MI.getOperand(1).getReg();
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001599 LLT DstTy = MRI.getType(DstReg);
1600 auto &MMO = **MI.memoperands_begin();
1601
Amara Emerson42866522019-04-20 21:25:00 +00001602 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
1603 // In the case of G_LOAD, this was a non-extending load already and we're
1604 // about to lower to the same instruction.
1605 if (MI.getOpcode() == TargetOpcode::G_LOAD)
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001606 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001607 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1608 MI.eraseFromParent();
1609 return Legalized;
1610 }
1611
1612 if (DstTy.isScalar()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001613 Register TmpReg =
Amara Emersond51adf02019-04-17 22:21:05 +00001614 MRI.createGenericVirtualRegister(LLT::scalar(MMO.getSizeInBits()));
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001615 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1616 switch (MI.getOpcode()) {
1617 default:
1618 llvm_unreachable("Unexpected opcode");
1619 case TargetOpcode::G_LOAD:
1620 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1621 break;
1622 case TargetOpcode::G_SEXTLOAD:
1623 MIRBuilder.buildSExt(DstReg, TmpReg);
1624 break;
1625 case TargetOpcode::G_ZEXTLOAD:
1626 MIRBuilder.buildZExt(DstReg, TmpReg);
1627 break;
1628 }
1629 MI.eraseFromParent();
1630 return Legalized;
1631 }
1632
1633 return UnableToLegalize;
1634 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001635 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1636 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1637 case TargetOpcode::G_CTLZ:
1638 case TargetOpcode::G_CTTZ:
1639 case TargetOpcode::G_CTPOP:
1640 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicbd395692019-02-26 17:22:42 +00001641 case G_UADDO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001642 Register Res = MI.getOperand(0).getReg();
1643 Register CarryOut = MI.getOperand(1).getReg();
1644 Register LHS = MI.getOperand(2).getReg();
1645 Register RHS = MI.getOperand(3).getReg();
Petar Avramovicbd395692019-02-26 17:22:42 +00001646
1647 MIRBuilder.buildAdd(Res, LHS, RHS);
1648 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS);
1649
1650 MI.eraseFromParent();
1651 return Legalized;
1652 }
Petar Avramovicb8276f22018-12-17 12:31:07 +00001653 case G_UADDE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001654 Register Res = MI.getOperand(0).getReg();
1655 Register CarryOut = MI.getOperand(1).getReg();
1656 Register LHS = MI.getOperand(2).getReg();
1657 Register RHS = MI.getOperand(3).getReg();
1658 Register CarryIn = MI.getOperand(4).getReg();
Petar Avramovicb8276f22018-12-17 12:31:07 +00001659
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001660 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1661 Register ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001662
1663 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1664 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1665 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1666 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1667
1668 MI.eraseFromParent();
1669 return Legalized;
1670 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001671 case G_USUBO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001672 Register Res = MI.getOperand(0).getReg();
1673 Register BorrowOut = MI.getOperand(1).getReg();
1674 Register LHS = MI.getOperand(2).getReg();
1675 Register RHS = MI.getOperand(3).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001676
1677 MIRBuilder.buildSub(Res, LHS, RHS);
1678 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1679
1680 MI.eraseFromParent();
1681 return Legalized;
1682 }
1683 case G_USUBE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001684 Register Res = MI.getOperand(0).getReg();
1685 Register BorrowOut = MI.getOperand(1).getReg();
1686 Register LHS = MI.getOperand(2).getReg();
1687 Register RHS = MI.getOperand(3).getReg();
1688 Register BorrowIn = MI.getOperand(4).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001689
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001690 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1691 Register ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1692 Register LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1693 Register LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001694
1695 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1696 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1697 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1698 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1699 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1700 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1701
1702 MI.eraseFromParent();
1703 return Legalized;
1704 }
Matt Arsenault02b5ca82019-05-17 23:05:13 +00001705 case G_UITOFP:
1706 return lowerUITOFP(MI, TypeIdx, Ty);
1707 case G_SITOFP:
1708 return lowerSITOFP(MI, TypeIdx, Ty);
Matt Arsenault6f74f552019-07-01 17:18:03 +00001709 case G_SMIN:
1710 case G_SMAX:
1711 case G_UMIN:
1712 case G_UMAX:
1713 return lowerMinMax(MI, TypeIdx, Ty);
Matt Arsenaultb1843e12019-07-09 23:34:29 +00001714 case G_FCOPYSIGN:
1715 return lowerFCopySign(MI, TypeIdx, Ty);
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001716 case G_FMINNUM:
1717 case G_FMAXNUM:
1718 return lowerFMinNumMaxNum(MI);
Tim Northovercecee562016-08-26 17:46:13 +00001719 }
1720}
1721
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001722LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1723 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001724 SmallVector<Register, 2> DstRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001725
1726 unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001727 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001728 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1729 int NumParts = Size / NarrowSize;
1730 // FIXME: Don't know how to handle the situation where the small vectors
1731 // aren't all the same size yet.
1732 if (Size % NarrowSize != 0)
1733 return UnableToLegalize;
1734
1735 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001736 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001737 MIRBuilder.buildUndef(TmpReg);
1738 DstRegs.push_back(TmpReg);
1739 }
1740
1741 if (NarrowTy.isVector())
1742 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1743 else
1744 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1745
1746 MI.eraseFromParent();
1747 return Legalized;
1748}
1749
1750LegalizerHelper::LegalizeResult
1751LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
1752 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001753 const unsigned Opc = MI.getOpcode();
1754 const unsigned NumOps = MI.getNumOperands() - 1;
1755 const unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenault3018d182019-06-28 01:47:44 +00001756 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001757 const unsigned Flags = MI.getFlags();
1758 const LLT DstTy = MRI.getType(DstReg);
1759 const unsigned Size = DstTy.getSizeInBits();
1760 const int NumParts = Size / NarrowSize;
1761 const LLT EltTy = DstTy.getElementType();
1762 const unsigned EltSize = EltTy.getSizeInBits();
1763 const unsigned BitsForNumParts = NarrowSize * NumParts;
1764
1765 // Check if we have any leftovers. If we do, then only handle the case where
1766 // the leftover is one element.
1767 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001768 return UnableToLegalize;
1769
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001770 if (BitsForNumParts != Size) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001771 Register AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001772 MIRBuilder.buildUndef(AccumDstReg);
1773
1774 // Handle the pieces which evenly divide into the requested type with
1775 // extract/op/insert sequence.
1776 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
1777 SmallVector<SrcOp, 4> SrcOps;
1778 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001779 Register PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001780 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
1781 SrcOps.push_back(PartOpReg);
1782 }
1783
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001784 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001785 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1786
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001787 Register PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001788 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
1789 AccumDstReg = PartInsertReg;
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001790 }
1791
1792 // Handle the remaining element sized leftover piece.
1793 SmallVector<SrcOp, 4> SrcOps;
1794 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001795 Register PartOpReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001796 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
1797 BitsForNumParts);
1798 SrcOps.push_back(PartOpReg);
1799 }
1800
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001801 Register PartDstReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001802 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1803 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
1804 MI.eraseFromParent();
1805
1806 return Legalized;
1807 }
1808
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001809 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001810
1811 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1812
1813 if (NumOps >= 2)
1814 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1815
1816 if (NumOps >= 3)
1817 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
1818
1819 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001820 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001821
1822 if (NumOps == 1)
1823 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1824 else if (NumOps == 2) {
1825 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1826 } else if (NumOps == 3) {
1827 MIRBuilder.buildInstr(Opc, {DstReg},
1828 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1829 }
1830
1831 DstRegs.push_back(DstReg);
1832 }
1833
1834 if (NarrowTy.isVector())
1835 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1836 else
1837 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1838
1839 MI.eraseFromParent();
1840 return Legalized;
1841}
1842
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001843// Handle splitting vector operations which need to have the same number of
1844// elements in each type index, but each type index may have a different element
1845// type.
1846//
1847// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
1848// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1849// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1850//
1851// Also handles some irregular breakdown cases, e.g.
1852// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
1853// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
1854// s64 = G_SHL s64, s32
1855LegalizerHelper::LegalizeResult
1856LegalizerHelper::fewerElementsVectorMultiEltType(
1857 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
1858 if (TypeIdx != 0)
1859 return UnableToLegalize;
1860
1861 const LLT NarrowTy0 = NarrowTyArg;
1862 const unsigned NewNumElts =
1863 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
1864
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001865 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001866 LLT DstTy = MRI.getType(DstReg);
1867 LLT LeftoverTy0;
1868
1869 // All of the operands need to have the same number of elements, so if we can
1870 // determine a type breakdown for the result type, we can for all of the
1871 // source types.
Fangrui Songb251cc02019-07-12 14:58:15 +00001872 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0).first;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001873 if (NumParts < 0)
1874 return UnableToLegalize;
1875
1876 SmallVector<MachineInstrBuilder, 4> NewInsts;
1877
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001878 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
1879 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001880
1881 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
1882 LLT LeftoverTy;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001883 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001884 LLT SrcTyI = MRI.getType(SrcReg);
1885 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
1886 LLT LeftoverTyI;
1887
1888 // Split this operand into the requested typed registers, and any leftover
1889 // required to reproduce the original type.
1890 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
1891 LeftoverRegs))
1892 return UnableToLegalize;
1893
1894 if (I == 1) {
1895 // For the first operand, create an instruction for each part and setup
1896 // the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001897 for (Register PartReg : PartRegs) {
1898 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001899 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
1900 .addDef(PartDstReg)
1901 .addUse(PartReg));
1902 DstRegs.push_back(PartDstReg);
1903 }
1904
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001905 for (Register LeftoverReg : LeftoverRegs) {
1906 Register PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00001907 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
1908 .addDef(PartDstReg)
1909 .addUse(LeftoverReg));
1910 LeftoverDstRegs.push_back(PartDstReg);
1911 }
1912 } else {
1913 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
1914
1915 // Add the newly created operand splits to the existing instructions. The
1916 // odd-sized pieces are ordered after the requested NarrowTyArg sized
1917 // pieces.
1918 unsigned InstCount = 0;
1919 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
1920 NewInsts[InstCount++].addUse(PartRegs[J]);
1921 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
1922 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
1923 }
1924
1925 PartRegs.clear();
1926 LeftoverRegs.clear();
1927 }
1928
1929 // Insert the newly built operations and rebuild the result register.
1930 for (auto &MIB : NewInsts)
1931 MIRBuilder.insertInstr(MIB);
1932
1933 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
1934
1935 MI.eraseFromParent();
1936 return Legalized;
1937}
1938
Tim Northover69fa84a2016-10-14 22:18:18 +00001939LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00001940LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
1941 LLT NarrowTy) {
1942 if (TypeIdx != 0)
1943 return UnableToLegalize;
1944
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001945 Register DstReg = MI.getOperand(0).getReg();
1946 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenaultca676342019-01-25 02:36:32 +00001947 LLT DstTy = MRI.getType(DstReg);
1948 LLT SrcTy = MRI.getType(SrcReg);
1949
1950 LLT NarrowTy0 = NarrowTy;
1951 LLT NarrowTy1;
1952 unsigned NumParts;
1953
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001954 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00001955 // Uneven breakdown not handled.
1956 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
1957 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
1958 return UnableToLegalize;
1959
1960 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001961 } else {
1962 NumParts = DstTy.getNumElements();
1963 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00001964 }
1965
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001966 SmallVector<Register, 4> SrcRegs, DstRegs;
Matt Arsenaultca676342019-01-25 02:36:32 +00001967 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
1968
1969 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001970 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultca676342019-01-25 02:36:32 +00001971 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
1972 .addDef(DstReg)
1973 .addUse(SrcRegs[I]);
1974
1975 NewInst->setFlags(MI.getFlags());
1976 DstRegs.push_back(DstReg);
1977 }
1978
1979 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001980 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001981 else
1982 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1983
1984 MI.eraseFromParent();
1985 return Legalized;
1986}
1987
1988LegalizerHelper::LegalizeResult
1989LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
1990 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001991 Register DstReg = MI.getOperand(0).getReg();
1992 Register Src0Reg = MI.getOperand(2).getReg();
Matt Arsenault1b1e6852019-01-25 02:59:34 +00001993 LLT DstTy = MRI.getType(DstReg);
1994 LLT SrcTy = MRI.getType(Src0Reg);
1995
1996 unsigned NumParts;
1997 LLT NarrowTy0, NarrowTy1;
1998
1999 if (TypeIdx == 0) {
2000 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2001 unsigned OldElts = DstTy.getNumElements();
2002
2003 NarrowTy0 = NarrowTy;
2004 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
2005 NarrowTy1 = NarrowTy.isVector() ?
2006 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
2007 SrcTy.getElementType();
2008
2009 } else {
2010 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2011 unsigned OldElts = SrcTy.getNumElements();
2012
2013 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
2014 NarrowTy.getNumElements();
2015 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
2016 DstTy.getScalarSizeInBits());
2017 NarrowTy1 = NarrowTy;
2018 }
2019
2020 // FIXME: Don't know how to handle the situation where the small vectors
2021 // aren't all the same size yet.
2022 if (NarrowTy1.isVector() &&
2023 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
2024 return UnableToLegalize;
2025
2026 CmpInst::Predicate Pred
2027 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
2028
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002029 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002030 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
2031 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
2032
2033 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002034 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002035 DstRegs.push_back(DstReg);
2036
2037 if (MI.getOpcode() == TargetOpcode::G_ICMP)
2038 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2039 else {
2040 MachineInstr *NewCmp
2041 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2042 NewCmp->setFlags(MI.getFlags());
2043 }
2044 }
2045
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002046 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00002047 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2048 else
2049 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2050
2051 MI.eraseFromParent();
2052 return Legalized;
2053}
2054
2055LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002056LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
2057 LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002058 Register DstReg = MI.getOperand(0).getReg();
2059 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002060
2061 unsigned NumParts = 0;
2062 LLT NarrowTy0, NarrowTy1;
2063
2064 LLT DstTy = MRI.getType(DstReg);
2065 LLT CondTy = MRI.getType(CondReg);
2066 unsigned Size = DstTy.getSizeInBits();
2067
2068 assert(TypeIdx == 0 || CondTy.isVector());
2069
2070 if (TypeIdx == 0) {
2071 NarrowTy0 = NarrowTy;
2072 NarrowTy1 = CondTy;
2073
2074 unsigned NarrowSize = NarrowTy0.getSizeInBits();
2075 // FIXME: Don't know how to handle the situation where the small vectors
2076 // aren't all the same size yet.
2077 if (Size % NarrowSize != 0)
2078 return UnableToLegalize;
2079
2080 NumParts = Size / NarrowSize;
2081
2082 // Need to break down the condition type
2083 if (CondTy.isVector()) {
2084 if (CondTy.getNumElements() == NumParts)
2085 NarrowTy1 = CondTy.getElementType();
2086 else
2087 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
2088 CondTy.getScalarSizeInBits());
2089 }
2090 } else {
2091 NumParts = CondTy.getNumElements();
2092 if (NarrowTy.isVector()) {
2093 // TODO: Handle uneven breakdown.
2094 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
2095 return UnableToLegalize;
2096
2097 return UnableToLegalize;
2098 } else {
2099 NarrowTy0 = DstTy.getElementType();
2100 NarrowTy1 = NarrowTy;
2101 }
2102 }
2103
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002104 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002105 if (CondTy.isVector())
2106 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2107
2108 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2109 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2110
2111 for (unsigned i = 0; i < NumParts; ++i) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002112 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002113 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2114 Src1Regs[i], Src2Regs[i]);
2115 DstRegs.push_back(DstReg);
2116 }
2117
2118 if (NarrowTy0.isVector())
2119 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2120 else
2121 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2122
2123 MI.eraseFromParent();
2124 return Legalized;
2125}
2126
2127LegalizerHelper::LegalizeResult
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002128LegalizerHelper::fewerElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2129 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002130 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002131 LLT PhiTy = MRI.getType(DstReg);
2132 LLT LeftoverTy;
2133
2134 // All of the operands need to have the same number of elements, so if we can
2135 // determine a type breakdown for the result type, we can for all of the
2136 // source types.
2137 int NumParts, NumLeftover;
2138 std::tie(NumParts, NumLeftover)
2139 = getNarrowTypeBreakDown(PhiTy, NarrowTy, LeftoverTy);
2140 if (NumParts < 0)
2141 return UnableToLegalize;
2142
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002143 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002144 SmallVector<MachineInstrBuilder, 4> NewInsts;
2145
2146 const int TotalNumParts = NumParts + NumLeftover;
2147
2148 // Insert the new phis in the result block first.
2149 for (int I = 0; I != TotalNumParts; ++I) {
2150 LLT Ty = I < NumParts ? NarrowTy : LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002151 Register PartDstReg = MRI.createGenericVirtualRegister(Ty);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002152 NewInsts.push_back(MIRBuilder.buildInstr(TargetOpcode::G_PHI)
2153 .addDef(PartDstReg));
2154 if (I < NumParts)
2155 DstRegs.push_back(PartDstReg);
2156 else
2157 LeftoverDstRegs.push_back(PartDstReg);
2158 }
2159
2160 MachineBasicBlock *MBB = MI.getParent();
2161 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
2162 insertParts(DstReg, PhiTy, NarrowTy, DstRegs, LeftoverTy, LeftoverDstRegs);
2163
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002164 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002165
2166 // Insert code to extract the incoming values in each predecessor block.
2167 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2168 PartRegs.clear();
2169 LeftoverRegs.clear();
2170
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002171 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002172 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2173 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2174
2175 LLT Unused;
2176 if (!extractParts(SrcReg, PhiTy, NarrowTy, Unused, PartRegs,
2177 LeftoverRegs))
2178 return UnableToLegalize;
2179
2180 // Add the newly created operand splits to the existing instructions. The
2181 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2182 // pieces.
2183 for (int J = 0; J != TotalNumParts; ++J) {
2184 MachineInstrBuilder MIB = NewInsts[J];
2185 MIB.addUse(J < NumParts ? PartRegs[J] : LeftoverRegs[J - NumParts]);
2186 MIB.addMBB(&OpMBB);
2187 }
2188 }
2189
2190 MI.eraseFromParent();
2191 return Legalized;
2192}
2193
2194LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002195LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2196 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002197 // FIXME: Don't know how to handle secondary types yet.
2198 if (TypeIdx != 0)
2199 return UnableToLegalize;
2200
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002201 MachineMemOperand *MMO = *MI.memoperands_begin();
2202
2203 // This implementation doesn't work for atomics. Give up instead of doing
2204 // something invalid.
2205 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2206 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2207 return UnableToLegalize;
2208
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002209 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002210 Register ValReg = MI.getOperand(0).getReg();
2211 Register AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002212 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002213
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002214 int NumParts = -1;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002215 int NumLeftover = -1;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002216 LLT LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002217 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002218 if (IsLoad) {
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002219 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002220 } else {
2221 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002222 NarrowLeftoverRegs)) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002223 NumParts = NarrowRegs.size();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002224 NumLeftover = NarrowLeftoverRegs.size();
2225 }
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002226 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002227
2228 if (NumParts == -1)
2229 return UnableToLegalize;
2230
2231 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2232
2233 unsigned TotalSize = ValTy.getSizeInBits();
2234
2235 // Split the load/store into PartTy sized pieces starting at Offset. If this
2236 // is a load, return the new registers in ValRegs. For a store, each elements
2237 // of ValRegs should be PartTy. Returns the next offset that needs to be
2238 // handled.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002239 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002240 unsigned Offset) -> unsigned {
2241 MachineFunction &MF = MIRBuilder.getMF();
2242 unsigned PartSize = PartTy.getSizeInBits();
2243 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2244 Offset += PartSize, ++Idx) {
2245 unsigned ByteSize = PartSize / 8;
2246 unsigned ByteOffset = Offset / 8;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002247 Register NewAddrReg;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002248
2249 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2250
2251 MachineMemOperand *NewMMO =
2252 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2253
2254 if (IsLoad) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002255 Register Dst = MRI.createGenericVirtualRegister(PartTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002256 ValRegs.push_back(Dst);
2257 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2258 } else {
2259 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2260 }
2261 }
2262
2263 return Offset;
2264 };
2265
2266 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2267
2268 // Handle the rest of the register if this isn't an even type breakdown.
2269 if (LeftoverTy.isValid())
2270 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2271
2272 if (IsLoad) {
2273 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2274 LeftoverTy, NarrowLeftoverRegs);
2275 }
2276
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002277 MI.eraseFromParent();
2278 return Legalized;
2279}
2280
2281LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002282LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2283 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002284 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002285
2286 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002287 switch (MI.getOpcode()) {
2288 case G_IMPLICIT_DEF:
2289 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2290 case G_AND:
2291 case G_OR:
2292 case G_XOR:
2293 case G_ADD:
2294 case G_SUB:
2295 case G_MUL:
2296 case G_SMULH:
2297 case G_UMULH:
2298 case G_FADD:
2299 case G_FMUL:
2300 case G_FSUB:
2301 case G_FNEG:
2302 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002303 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002304 case G_FDIV:
2305 case G_FREM:
2306 case G_FMA:
2307 case G_FPOW:
2308 case G_FEXP:
2309 case G_FEXP2:
2310 case G_FLOG:
2311 case G_FLOG2:
2312 case G_FLOG10:
Jessica Paquetteba557672019-04-25 16:44:40 +00002313 case G_FNEARBYINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002314 case G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00002315 case G_FFLOOR:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00002316 case G_FRINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002317 case G_INTRINSIC_ROUND:
2318 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002319 case G_FCOS:
2320 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002321 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002322 case G_BSWAP:
Amara Emersonae878da2019-04-10 23:06:08 +00002323 case G_SDIV:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002324 case G_SMIN:
2325 case G_SMAX:
2326 case G_UMIN:
2327 case G_UMAX:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00002328 case G_FMINNUM:
2329 case G_FMAXNUM:
2330 case G_FMINNUM_IEEE:
2331 case G_FMAXNUM_IEEE:
2332 case G_FMINIMUM:
2333 case G_FMAXIMUM:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002334 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002335 case G_SHL:
2336 case G_LSHR:
2337 case G_ASHR:
Matt Arsenault75e30c42019-02-20 16:42:52 +00002338 case G_CTLZ:
2339 case G_CTLZ_ZERO_UNDEF:
2340 case G_CTTZ:
2341 case G_CTTZ_ZERO_UNDEF:
2342 case G_CTPOP:
Matt Arsenault1448f562019-05-17 12:19:52 +00002343 case G_FCOPYSIGN:
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002344 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002345 case G_ZEXT:
2346 case G_SEXT:
2347 case G_ANYEXT:
2348 case G_FPEXT:
2349 case G_FPTRUNC:
2350 case G_SITOFP:
2351 case G_UITOFP:
2352 case G_FPTOSI:
2353 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002354 case G_INTTOPTR:
2355 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002356 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002357 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2358 case G_ICMP:
2359 case G_FCMP:
2360 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002361 case G_SELECT:
2362 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002363 case G_PHI:
2364 return fewerElementsVectorPhi(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002365 case G_LOAD:
2366 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002367 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002368 default:
2369 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002370 }
2371}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002372
2373LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002374LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2375 const LLT HalfTy, const LLT AmtTy) {
2376
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002377 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2378 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002379 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2380
2381 if (Amt.isNullValue()) {
2382 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2383 MI.eraseFromParent();
2384 return Legalized;
2385 }
2386
2387 LLT NVT = HalfTy;
2388 unsigned NVTBits = HalfTy.getSizeInBits();
2389 unsigned VTBits = 2 * NVTBits;
2390
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002391 SrcOp Lo(Register(0)), Hi(Register(0));
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002392 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2393 if (Amt.ugt(VTBits)) {
2394 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2395 } else if (Amt.ugt(NVTBits)) {
2396 Lo = MIRBuilder.buildConstant(NVT, 0);
2397 Hi = MIRBuilder.buildShl(NVT, InL,
2398 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2399 } else if (Amt == NVTBits) {
2400 Lo = MIRBuilder.buildConstant(NVT, 0);
2401 Hi = InL;
2402 } else {
2403 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002404 auto OrLHS =
2405 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2406 auto OrRHS = MIRBuilder.buildLShr(
2407 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2408 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002409 }
2410 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2411 if (Amt.ugt(VTBits)) {
2412 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2413 } else if (Amt.ugt(NVTBits)) {
2414 Lo = MIRBuilder.buildLShr(NVT, InH,
2415 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2416 Hi = MIRBuilder.buildConstant(NVT, 0);
2417 } else if (Amt == NVTBits) {
2418 Lo = InH;
2419 Hi = MIRBuilder.buildConstant(NVT, 0);
2420 } else {
2421 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2422
2423 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2424 auto OrRHS = MIRBuilder.buildShl(
2425 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2426
2427 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2428 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2429 }
2430 } else {
2431 if (Amt.ugt(VTBits)) {
2432 Hi = Lo = MIRBuilder.buildAShr(
2433 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2434 } else if (Amt.ugt(NVTBits)) {
2435 Lo = MIRBuilder.buildAShr(NVT, InH,
2436 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2437 Hi = MIRBuilder.buildAShr(NVT, InH,
2438 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2439 } else if (Amt == NVTBits) {
2440 Lo = InH;
2441 Hi = MIRBuilder.buildAShr(NVT, InH,
2442 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2443 } else {
2444 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2445
2446 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2447 auto OrRHS = MIRBuilder.buildShl(
2448 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2449
2450 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2451 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2452 }
2453 }
2454
2455 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2456 MI.eraseFromParent();
2457
2458 return Legalized;
2459}
2460
2461// TODO: Optimize if constant shift amount.
2462LegalizerHelper::LegalizeResult
2463LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2464 LLT RequestedTy) {
2465 if (TypeIdx == 1) {
2466 Observer.changingInstr(MI);
2467 narrowScalarSrc(MI, RequestedTy, 2);
2468 Observer.changedInstr(MI);
2469 return Legalized;
2470 }
2471
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002472 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002473 LLT DstTy = MRI.getType(DstReg);
2474 if (DstTy.isVector())
2475 return UnableToLegalize;
2476
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002477 Register Amt = MI.getOperand(2).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002478 LLT ShiftAmtTy = MRI.getType(Amt);
2479 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2480 if (DstEltSize % 2 != 0)
2481 return UnableToLegalize;
2482
2483 // Ignore the input type. We can only go to exactly half the size of the
2484 // input. If that isn't small enough, the resulting pieces will be further
2485 // legalized.
2486 const unsigned NewBitSize = DstEltSize / 2;
2487 const LLT HalfTy = LLT::scalar(NewBitSize);
2488 const LLT CondTy = LLT::scalar(1);
2489
2490 if (const MachineInstr *KShiftAmt =
2491 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2492 return narrowScalarShiftByConstant(
2493 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2494 }
2495
2496 // TODO: Expand with known bits.
2497
2498 // Handle the fully general expansion by an unknown amount.
2499 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2500
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002501 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2502 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002503 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2504
2505 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2506 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2507
2508 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2509 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2510 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2511
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002512 Register ResultRegs[2];
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002513 switch (MI.getOpcode()) {
2514 case TargetOpcode::G_SHL: {
2515 // Short: ShAmt < NewBitSize
2516 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2517
2518 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2519 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2520 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2521
2522 // Long: ShAmt >= NewBitSize
2523 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2524 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2525
2526 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2527 auto Hi = MIRBuilder.buildSelect(
2528 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2529
2530 ResultRegs[0] = Lo.getReg(0);
2531 ResultRegs[1] = Hi.getReg(0);
2532 break;
2533 }
2534 case TargetOpcode::G_LSHR: {
2535 // Short: ShAmt < NewBitSize
2536 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2537
2538 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2539 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2540 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2541
2542 // Long: ShAmt >= NewBitSize
2543 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2544 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2545
2546 auto Lo = MIRBuilder.buildSelect(
2547 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2548 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2549
2550 ResultRegs[0] = Lo.getReg(0);
2551 ResultRegs[1] = Hi.getReg(0);
2552 break;
2553 }
2554 case TargetOpcode::G_ASHR: {
2555 // Short: ShAmt < NewBitSize
2556 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2557
2558 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2559 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2560 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2561
2562 // Long: ShAmt >= NewBitSize
2563
2564 // Sign of Hi part.
2565 auto HiL = MIRBuilder.buildAShr(
2566 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2567
2568 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2569
2570 auto Lo = MIRBuilder.buildSelect(
2571 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2572
2573 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2574
2575 ResultRegs[0] = Lo.getReg(0);
2576 ResultRegs[1] = Hi.getReg(0);
2577 break;
2578 }
2579 default:
2580 llvm_unreachable("not a shift");
2581 }
2582
2583 MIRBuilder.buildMerge(DstReg, ResultRegs);
2584 MI.eraseFromParent();
2585 return Legalized;
2586}
2587
2588LegalizerHelper::LegalizeResult
Matt Arsenault72bcf152019-02-28 00:01:05 +00002589LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2590 LLT MoreTy) {
2591 assert(TypeIdx == 0 && "Expecting only Idx 0");
2592
2593 Observer.changingInstr(MI);
2594 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2595 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2596 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2597 moreElementsVectorSrc(MI, MoreTy, I);
2598 }
2599
2600 MachineBasicBlock &MBB = *MI.getParent();
2601 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
2602 moreElementsVectorDst(MI, MoreTy, 0);
2603 Observer.changedInstr(MI);
2604 return Legalized;
2605}
2606
2607LegalizerHelper::LegalizeResult
Matt Arsenault18ec3822019-02-11 22:00:39 +00002608LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
2609 LLT MoreTy) {
2610 MIRBuilder.setInstr(MI);
2611 unsigned Opc = MI.getOpcode();
2612 switch (Opc) {
2613 case TargetOpcode::G_IMPLICIT_DEF: {
2614 Observer.changingInstr(MI);
2615 moreElementsVectorDst(MI, MoreTy, 0);
2616 Observer.changedInstr(MI);
2617 return Legalized;
2618 }
Matt Arsenault26b7e852019-02-19 16:30:19 +00002619 case TargetOpcode::G_AND:
2620 case TargetOpcode::G_OR:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002621 case TargetOpcode::G_XOR:
2622 case TargetOpcode::G_SMIN:
2623 case TargetOpcode::G_SMAX:
2624 case TargetOpcode::G_UMIN:
2625 case TargetOpcode::G_UMAX: {
Matt Arsenault26b7e852019-02-19 16:30:19 +00002626 Observer.changingInstr(MI);
2627 moreElementsVectorSrc(MI, MoreTy, 1);
2628 moreElementsVectorSrc(MI, MoreTy, 2);
2629 moreElementsVectorDst(MI, MoreTy, 0);
2630 Observer.changedInstr(MI);
2631 return Legalized;
2632 }
Matt Arsenault4d884272019-02-19 16:44:22 +00002633 case TargetOpcode::G_EXTRACT:
2634 if (TypeIdx != 1)
2635 return UnableToLegalize;
2636 Observer.changingInstr(MI);
2637 moreElementsVectorSrc(MI, MoreTy, 1);
2638 Observer.changedInstr(MI);
2639 return Legalized;
Matt Arsenaultc4d07552019-02-20 16:11:22 +00002640 case TargetOpcode::G_INSERT:
2641 if (TypeIdx != 0)
2642 return UnableToLegalize;
2643 Observer.changingInstr(MI);
2644 moreElementsVectorSrc(MI, MoreTy, 1);
2645 moreElementsVectorDst(MI, MoreTy, 0);
2646 Observer.changedInstr(MI);
2647 return Legalized;
Matt Arsenaultb4c95b32019-02-19 17:03:09 +00002648 case TargetOpcode::G_SELECT:
2649 if (TypeIdx != 0)
2650 return UnableToLegalize;
2651 if (MRI.getType(MI.getOperand(1).getReg()).isVector())
2652 return UnableToLegalize;
2653
2654 Observer.changingInstr(MI);
2655 moreElementsVectorSrc(MI, MoreTy, 2);
2656 moreElementsVectorSrc(MI, MoreTy, 3);
2657 moreElementsVectorDst(MI, MoreTy, 0);
2658 Observer.changedInstr(MI);
2659 return Legalized;
Matt Arsenault72bcf152019-02-28 00:01:05 +00002660 case TargetOpcode::G_PHI:
2661 return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +00002662 default:
2663 return UnableToLegalize;
2664 }
2665}
2666
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002667void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
2668 ArrayRef<Register> Src1Regs,
2669 ArrayRef<Register> Src2Regs,
Petar Avramovic0b17e592019-03-11 10:00:17 +00002670 LLT NarrowTy) {
2671 MachineIRBuilder &B = MIRBuilder;
2672 unsigned SrcParts = Src1Regs.size();
2673 unsigned DstParts = DstRegs.size();
2674
2675 unsigned DstIdx = 0; // Low bits of the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002676 Register FactorSum =
Petar Avramovic0b17e592019-03-11 10:00:17 +00002677 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
2678 DstRegs[DstIdx] = FactorSum;
2679
2680 unsigned CarrySumPrevDstIdx;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002681 SmallVector<Register, 4> Factors;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002682
2683 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
2684 // Collect low parts of muls for DstIdx.
2685 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
2686 i <= std::min(DstIdx, SrcParts - 1); ++i) {
2687 MachineInstrBuilder Mul =
2688 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
2689 Factors.push_back(Mul.getReg(0));
2690 }
2691 // Collect high parts of muls from previous DstIdx.
2692 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
2693 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
2694 MachineInstrBuilder Umulh =
2695 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
2696 Factors.push_back(Umulh.getReg(0));
2697 }
2698 // Add CarrySum from additons calculated for previous DstIdx.
2699 if (DstIdx != 1) {
2700 Factors.push_back(CarrySumPrevDstIdx);
2701 }
2702
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002703 Register CarrySum;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002704 // Add all factors and accumulate all carries into CarrySum.
2705 if (DstIdx != DstParts - 1) {
2706 MachineInstrBuilder Uaddo =
2707 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]);
2708 FactorSum = Uaddo.getReg(0);
2709 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0);
2710 for (unsigned i = 2; i < Factors.size(); ++i) {
2711 MachineInstrBuilder Uaddo =
2712 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]);
2713 FactorSum = Uaddo.getReg(0);
2714 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1));
2715 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
2716 }
2717 } else {
2718 // Since value for the next index is not calculated, neither is CarrySum.
2719 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
2720 for (unsigned i = 2; i < Factors.size(); ++i)
2721 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
2722 }
2723
2724 CarrySumPrevDstIdx = CarrySum;
2725 DstRegs[DstIdx] = FactorSum;
2726 Factors.clear();
2727 }
2728}
2729
Matt Arsenault18ec3822019-02-11 22:00:39 +00002730LegalizerHelper::LegalizeResult
Petar Avramovic0b17e592019-03-11 10:00:17 +00002731LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002732 Register DstReg = MI.getOperand(0).getReg();
2733 Register Src1 = MI.getOperand(1).getReg();
2734 Register Src2 = MI.getOperand(2).getReg();
Petar Avramovic0b17e592019-03-11 10:00:17 +00002735
Matt Arsenault211e89d2019-01-27 00:52:51 +00002736 LLT Ty = MRI.getType(DstReg);
2737 if (Ty.isVector())
2738 return UnableToLegalize;
2739
Petar Avramovic0b17e592019-03-11 10:00:17 +00002740 unsigned SrcSize = MRI.getType(Src1).getSizeInBits();
2741 unsigned DstSize = Ty.getSizeInBits();
2742 unsigned NarrowSize = NarrowTy.getSizeInBits();
2743 if (DstSize % NarrowSize != 0 || SrcSize % NarrowSize != 0)
Matt Arsenault211e89d2019-01-27 00:52:51 +00002744 return UnableToLegalize;
2745
Petar Avramovic0b17e592019-03-11 10:00:17 +00002746 unsigned NumDstParts = DstSize / NarrowSize;
2747 unsigned NumSrcParts = SrcSize / NarrowSize;
Petar Avramovic5229f472019-03-11 10:08:44 +00002748 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH;
2749 unsigned DstTmpParts = NumDstParts * (IsMulHigh ? 2 : 1);
Matt Arsenault211e89d2019-01-27 00:52:51 +00002750
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002751 SmallVector<Register, 2> Src1Parts, Src2Parts, DstTmpRegs;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002752 extractParts(Src1, NarrowTy, NumSrcParts, Src1Parts);
2753 extractParts(Src2, NarrowTy, NumSrcParts, Src2Parts);
Petar Avramovic5229f472019-03-11 10:08:44 +00002754 DstTmpRegs.resize(DstTmpParts);
2755 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
Matt Arsenault211e89d2019-01-27 00:52:51 +00002756
Petar Avramovic5229f472019-03-11 10:08:44 +00002757 // Take only high half of registers if this is high mul.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002758 ArrayRef<Register> DstRegs(
Petar Avramovic5229f472019-03-11 10:08:44 +00002759 IsMulHigh ? &DstTmpRegs[DstTmpParts / 2] : &DstTmpRegs[0], NumDstParts);
Petar Avramovic0b17e592019-03-11 10:00:17 +00002760 MIRBuilder.buildMerge(DstReg, DstRegs);
Matt Arsenault211e89d2019-01-27 00:52:51 +00002761 MI.eraseFromParent();
2762 return Legalized;
2763}
2764
Matt Arsenault1cf71362019-02-12 14:54:52 +00002765LegalizerHelper::LegalizeResult
2766LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
2767 LLT NarrowTy) {
2768 if (TypeIdx != 1)
2769 return UnableToLegalize;
2770
2771 uint64_t NarrowSize = NarrowTy.getSizeInBits();
2772
2773 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
2774 // FIXME: add support for when SizeOp1 isn't an exact multiple of
2775 // NarrowSize.
2776 if (SizeOp1 % NarrowSize != 0)
2777 return UnableToLegalize;
2778 int NumParts = SizeOp1 / NarrowSize;
2779
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002780 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00002781 SmallVector<uint64_t, 2> Indexes;
2782 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
2783
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002784 Register OpReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00002785 uint64_t OpStart = MI.getOperand(2).getImm();
2786 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
2787 for (int i = 0; i < NumParts; ++i) {
2788 unsigned SrcStart = i * NarrowSize;
2789
2790 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
2791 // No part of the extract uses this subregister, ignore it.
2792 continue;
2793 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
2794 // The entire subregister is extracted, forward the value.
2795 DstRegs.push_back(SrcRegs[i]);
2796 continue;
2797 }
2798
2799 // OpSegStart is where this destination segment would start in OpReg if it
2800 // extended infinitely in both directions.
2801 int64_t ExtractOffset;
2802 uint64_t SegSize;
2803 if (OpStart < SrcStart) {
2804 ExtractOffset = 0;
2805 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
2806 } else {
2807 ExtractOffset = OpStart - SrcStart;
2808 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
2809 }
2810
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002811 Register SegReg = SrcRegs[i];
Matt Arsenault1cf71362019-02-12 14:54:52 +00002812 if (ExtractOffset != 0 || SegSize != NarrowSize) {
2813 // A genuine extract is needed.
2814 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
2815 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
2816 }
2817
2818 DstRegs.push_back(SegReg);
2819 }
2820
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002821 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00002822 if(MRI.getType(DstReg).isVector())
2823 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2824 else
2825 MIRBuilder.buildMerge(DstReg, DstRegs);
2826 MI.eraseFromParent();
2827 return Legalized;
2828}
2829
2830LegalizerHelper::LegalizeResult
2831LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
2832 LLT NarrowTy) {
2833 // FIXME: Don't know how to handle secondary types yet.
2834 if (TypeIdx != 0)
2835 return UnableToLegalize;
2836
2837 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
2838 uint64_t NarrowSize = NarrowTy.getSizeInBits();
2839
2840 // FIXME: add support for when SizeOp0 isn't an exact multiple of
2841 // NarrowSize.
2842 if (SizeOp0 % NarrowSize != 0)
2843 return UnableToLegalize;
2844
2845 int NumParts = SizeOp0 / NarrowSize;
2846
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002847 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00002848 SmallVector<uint64_t, 2> Indexes;
2849 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
2850
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002851 Register OpReg = MI.getOperand(2).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00002852 uint64_t OpStart = MI.getOperand(3).getImm();
2853 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
2854 for (int i = 0; i < NumParts; ++i) {
2855 unsigned DstStart = i * NarrowSize;
2856
2857 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
2858 // No part of the insert affects this subregister, forward the original.
2859 DstRegs.push_back(SrcRegs[i]);
2860 continue;
2861 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
2862 // The entire subregister is defined by this insert, forward the new
2863 // value.
2864 DstRegs.push_back(OpReg);
2865 continue;
2866 }
2867
2868 // OpSegStart is where this destination segment would start in OpReg if it
2869 // extended infinitely in both directions.
2870 int64_t ExtractOffset, InsertOffset;
2871 uint64_t SegSize;
2872 if (OpStart < DstStart) {
2873 InsertOffset = 0;
2874 ExtractOffset = DstStart - OpStart;
2875 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
2876 } else {
2877 InsertOffset = OpStart - DstStart;
2878 ExtractOffset = 0;
2879 SegSize =
2880 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
2881 }
2882
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002883 Register SegReg = OpReg;
Matt Arsenault1cf71362019-02-12 14:54:52 +00002884 if (ExtractOffset != 0 || SegSize != OpSize) {
2885 // A genuine extract is needed.
2886 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
2887 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
2888 }
2889
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002890 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +00002891 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
2892 DstRegs.push_back(DstReg);
2893 }
2894
2895 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002896 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00002897 if(MRI.getType(DstReg).isVector())
2898 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2899 else
2900 MIRBuilder.buildMerge(DstReg, DstRegs);
2901 MI.eraseFromParent();
2902 return Legalized;
2903}
2904
Matt Arsenault211e89d2019-01-27 00:52:51 +00002905LegalizerHelper::LegalizeResult
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00002906LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx,
2907 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002908 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00002909 LLT DstTy = MRI.getType(DstReg);
2910
2911 assert(MI.getNumOperands() == 3 && TypeIdx == 0);
2912
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002913 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
2914 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs;
2915 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00002916 LLT LeftoverTy;
2917 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
2918 Src0Regs, Src0LeftoverRegs))
2919 return UnableToLegalize;
2920
2921 LLT Unused;
2922 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
2923 Src1Regs, Src1LeftoverRegs))
2924 llvm_unreachable("inconsistent extractParts result");
2925
2926 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
2927 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
2928 {Src0Regs[I], Src1Regs[I]});
2929 DstRegs.push_back(Inst->getOperand(0).getReg());
2930 }
2931
2932 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
2933 auto Inst = MIRBuilder.buildInstr(
2934 MI.getOpcode(),
2935 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
2936 DstLeftoverRegs.push_back(Inst->getOperand(0).getReg());
2937 }
2938
2939 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
2940 LeftoverTy, DstLeftoverRegs);
2941
2942 MI.eraseFromParent();
2943 return Legalized;
2944}
2945
2946LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00002947LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
2948 LLT NarrowTy) {
2949 if (TypeIdx != 0)
2950 return UnableToLegalize;
2951
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002952 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00002953 LLT CondTy = MRI.getType(CondReg);
2954 if (CondTy.isVector()) // TODO: Handle vselect
2955 return UnableToLegalize;
2956
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002957 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00002958 LLT DstTy = MRI.getType(DstReg);
2959
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002960 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
2961 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
2962 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs;
Matt Arsenault81511e52019-02-05 00:13:44 +00002963 LLT LeftoverTy;
2964 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
2965 Src1Regs, Src1LeftoverRegs))
2966 return UnableToLegalize;
2967
2968 LLT Unused;
2969 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
2970 Src2Regs, Src2LeftoverRegs))
2971 llvm_unreachable("inconsistent extractParts result");
2972
2973 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
2974 auto Select = MIRBuilder.buildSelect(NarrowTy,
2975 CondReg, Src1Regs[I], Src2Regs[I]);
2976 DstRegs.push_back(Select->getOperand(0).getReg());
2977 }
2978
2979 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
2980 auto Select = MIRBuilder.buildSelect(
2981 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
2982 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
2983 }
2984
2985 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
2986 LeftoverTy, DstLeftoverRegs);
2987
2988 MI.eraseFromParent();
2989 return Legalized;
2990}
2991
2992LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002993LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
2994 unsigned Opc = MI.getOpcode();
2995 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00002996 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002997 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00002998 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002999 };
3000 switch (Opc) {
3001 default:
3002 return UnableToLegalize;
3003 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
3004 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003005 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003006 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003007 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003008 return Legalized;
3009 }
3010 case TargetOpcode::G_CTLZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003011 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003012 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003013 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00003014 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003015 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
3016 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003017 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3018 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3019 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3020 SrcReg, MIBZero);
3021 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3022 MIBCtlzZU);
3023 MI.eraseFromParent();
3024 return Legalized;
3025 }
3026 // for now, we do this:
3027 // NewLen = NextPowerOf2(Len);
3028 // x = x | (x >> 1);
3029 // x = x | (x >> 2);
3030 // ...
3031 // x = x | (x >>16);
3032 // x = x | (x >>32); // for 64-bit input
3033 // Upto NewLen/2
3034 // return Len - popcount(x);
3035 //
3036 // Ref: "Hacker's Delight" by Henry Warren
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003037 Register Op = SrcReg;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003038 unsigned NewLen = PowerOf2Ceil(Len);
3039 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
3040 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
3041 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003042 TargetOpcode::G_OR, {Ty},
3043 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
3044 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003045 Op = MIBOp->getOperand(0).getReg();
3046 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003047 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
3048 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3049 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003050 MI.eraseFromParent();
3051 return Legalized;
3052 }
3053 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
3054 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003055 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003056 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003057 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003058 return Legalized;
3059 }
3060 case TargetOpcode::G_CTTZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003061 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003062 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003063 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003064 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
3065 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003066 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
3067 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003068 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3069 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3070 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3071 SrcReg, MIBZero);
3072 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3073 MIBCttzZU);
3074 MI.eraseFromParent();
3075 return Legalized;
3076 }
3077 // for now, we use: { return popcount(~x & (x - 1)); }
3078 // unless the target has ctlz but not ctpop, in which case we use:
3079 // { return 32 - nlz(~x & (x-1)); }
3080 // Ref: "Hacker's Delight" by Henry Warren
3081 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
3082 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003083 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003084 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003085 TargetOpcode::G_AND, {Ty},
3086 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
3087 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003088 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
3089 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003090 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
3091 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003092 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3093 {MIBCstLen,
3094 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003095 MI.eraseFromParent();
3096 return Legalized;
3097 }
3098 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
3099 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
3100 return Legalized;
3101 }
3102 }
3103}
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003104
3105// Expand s32 = G_UITOFP s64 using bit operations to an IEEE float
3106// representation.
3107LegalizerHelper::LegalizeResult
3108LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003109 Register Dst = MI.getOperand(0).getReg();
3110 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003111 const LLT S64 = LLT::scalar(64);
3112 const LLT S32 = LLT::scalar(32);
3113 const LLT S1 = LLT::scalar(1);
3114
3115 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);
3116
3117 // unsigned cul2f(ulong u) {
3118 // uint lz = clz(u);
3119 // uint e = (u != 0) ? 127U + 63U - lz : 0;
3120 // u = (u << lz) & 0x7fffffffffffffffUL;
3121 // ulong t = u & 0xffffffffffUL;
3122 // uint v = (e << 23) | (uint)(u >> 40);
3123 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
3124 // return as_float(v + r);
3125 // }
3126
3127 auto Zero32 = MIRBuilder.buildConstant(S32, 0);
3128 auto Zero64 = MIRBuilder.buildConstant(S64, 0);
3129
3130 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src);
3131
3132 auto K = MIRBuilder.buildConstant(S32, 127U + 63U);
3133 auto Sub = MIRBuilder.buildSub(S32, K, LZ);
3134
3135 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64);
3136 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32);
3137
3138 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1);
3139 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ);
3140
3141 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0);
3142
3143 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL);
3144 auto T = MIRBuilder.buildAnd(S64, U, Mask1);
3145
3146 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40));
3147 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23));
3148 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl));
3149
3150 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL);
3151 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C);
3152 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C);
3153 auto One = MIRBuilder.buildConstant(S32, 1);
3154
3155 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One);
3156 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32);
3157 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0);
3158 MIRBuilder.buildAdd(Dst, V, R);
3159
3160 return Legalized;
3161}
3162
3163LegalizerHelper::LegalizeResult
3164LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003165 Register Dst = MI.getOperand(0).getReg();
3166 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003167 LLT DstTy = MRI.getType(Dst);
3168 LLT SrcTy = MRI.getType(Src);
3169
3170 if (SrcTy != LLT::scalar(64))
3171 return UnableToLegalize;
3172
3173 if (DstTy == LLT::scalar(32)) {
3174 // TODO: SelectionDAG has several alternative expansions to port which may
3175 // be more reasonble depending on the available instructions. If a target
3176 // has sitofp, does not have CTLZ, or can efficiently use f64 as an
3177 // intermediate type, this is probably worse.
3178 return lowerU64ToF32BitOps(MI);
3179 }
3180
3181 return UnableToLegalize;
3182}
3183
3184LegalizerHelper::LegalizeResult
3185LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003186 Register Dst = MI.getOperand(0).getReg();
3187 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003188 LLT DstTy = MRI.getType(Dst);
3189 LLT SrcTy = MRI.getType(Src);
3190
3191 const LLT S64 = LLT::scalar(64);
3192 const LLT S32 = LLT::scalar(32);
3193 const LLT S1 = LLT::scalar(1);
3194
3195 if (SrcTy != S64)
3196 return UnableToLegalize;
3197
3198 if (DstTy == S32) {
3199 // signed cl2f(long l) {
3200 // long s = l >> 63;
3201 // float r = cul2f((l + s) ^ s);
3202 // return s ? -r : r;
3203 // }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003204 Register L = Src;
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003205 auto SignBit = MIRBuilder.buildConstant(S64, 63);
3206 auto S = MIRBuilder.buildAShr(S64, L, SignBit);
3207
3208 auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
3209 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
3210 auto R = MIRBuilder.buildUITOFP(S32, Xor);
3211
3212 auto RNeg = MIRBuilder.buildFNeg(S32, R);
3213 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
3214 MIRBuilder.buildConstant(S64, 0));
3215 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
3216 return Legalized;
3217 }
3218
3219 return UnableToLegalize;
3220}
Matt Arsenault6f74f552019-07-01 17:18:03 +00003221
3222static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
3223 switch (Opc) {
3224 case TargetOpcode::G_SMIN:
3225 return CmpInst::ICMP_SLT;
3226 case TargetOpcode::G_SMAX:
3227 return CmpInst::ICMP_SGT;
3228 case TargetOpcode::G_UMIN:
3229 return CmpInst::ICMP_ULT;
3230 case TargetOpcode::G_UMAX:
3231 return CmpInst::ICMP_UGT;
3232 default:
3233 llvm_unreachable("not in integer min/max");
3234 }
3235}
3236
3237LegalizerHelper::LegalizeResult
3238LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3239 Register Dst = MI.getOperand(0).getReg();
3240 Register Src0 = MI.getOperand(1).getReg();
3241 Register Src1 = MI.getOperand(2).getReg();
3242
3243 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
3244 LLT CmpType = MRI.getType(Dst).changeElementSize(1);
3245
3246 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
3247 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
3248
3249 MI.eraseFromParent();
3250 return Legalized;
3251}
Matt Arsenaultb1843e12019-07-09 23:34:29 +00003252
3253LegalizerHelper::LegalizeResult
3254LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3255 Register Dst = MI.getOperand(0).getReg();
3256 Register Src0 = MI.getOperand(1).getReg();
3257 Register Src1 = MI.getOperand(2).getReg();
3258
3259 const LLT Src0Ty = MRI.getType(Src0);
3260 const LLT Src1Ty = MRI.getType(Src1);
3261
3262 const int Src0Size = Src0Ty.getScalarSizeInBits();
3263 const int Src1Size = Src1Ty.getScalarSizeInBits();
3264
3265 auto SignBitMask = MIRBuilder.buildConstant(
3266 Src0Ty, APInt::getSignMask(Src0Size));
3267
3268 auto NotSignBitMask = MIRBuilder.buildConstant(
3269 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
3270
3271 auto And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask);
3272 MachineInstr *Or;
3273
3274 if (Src0Ty == Src1Ty) {
3275 auto And1 = MIRBuilder.buildAnd(Src1Ty, Src0, SignBitMask);
3276 Or = MIRBuilder.buildOr(Dst, And0, And1);
3277 } else if (Src0Size > Src1Size) {
3278 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
3279 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
3280 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
3281 auto And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask);
3282 Or = MIRBuilder.buildOr(Dst, And0, And1);
3283 } else {
3284 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
3285 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
3286 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
3287 auto And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask);
3288 Or = MIRBuilder.buildOr(Dst, And0, And1);
3289 }
3290
3291 // Be careful about setting nsz/nnan/ninf on every instruction, since the
3292 // constants are a nan and -0.0, but the final result should preserve
3293 // everything.
3294 if (unsigned Flags = MI.getFlags())
3295 Or->setFlags(Flags);
3296
3297 MI.eraseFromParent();
3298 return Legalized;
3299}
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00003300
3301LegalizerHelper::LegalizeResult
3302LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
3303 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ?
3304 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE;
3305
3306 Register Dst = MI.getOperand(0).getReg();
3307 Register Src0 = MI.getOperand(1).getReg();
3308 Register Src1 = MI.getOperand(2).getReg();
3309 LLT Ty = MRI.getType(Dst);
3310
3311 if (!MI.getFlag(MachineInstr::FmNoNans)) {
3312 // Insert canonicalizes if it's possible we need to quiet to get correct
3313 // sNaN behavior.
3314
3315 // Note this must be done here, and not as an optimization combine in the
3316 // absence of a dedicate quiet-snan instruction as we're using an
3317 // omni-purpose G_FCANONICALIZE.
3318 if (!isKnownNeverSNaN(Src0, MRI))
3319 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);
3320
3321 if (!isKnownNeverSNaN(Src1, MRI))
3322 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
3323 }
3324
3325 // If there are no nans, it's safe to simply replace this with the non-IEEE
3326 // version.
3327 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags());
3328 MI.eraseFromParent();
3329 return Legalized;
3330}