blob: 500bae412d5ecdd96594a183ae3106f13ebe7e74 [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 Avramovicfaaa2b5d2019-06-06 09:02:24 +0000281 case TargetOpcode::G_FCEIL:
282 assert((Size == 32 || Size == 64) && "Unsupported size");
283 return Size == 64 ? RTLIB::CEIL_F64 : RTLIB::CEIL_F32;
284 case TargetOpcode::G_FFLOOR:
285 assert((Size == 32 || Size == 64) && "Unsupported size");
286 return Size == 64 ? RTLIB::FLOOR_F64 : RTLIB::FLOOR_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000287 }
288 llvm_unreachable("Unknown libcall function");
289}
290
Diana Picusfc1675e2017-07-05 12:57:24 +0000291LegalizerHelper::LegalizeResult
292llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
293 const CallLowering::ArgInfo &Result,
294 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000295 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
296 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000297 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000298
Diana Picuse97822e2017-04-24 07:22:31 +0000299 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northovere1a5f662019-08-09 08:26:38 +0000300
301 CallLowering::CallLoweringInfo Info;
302 Info.CallConv = TLI.getLibcallCallingConv(Libcall);
303 Info.Callee = MachineOperand::CreateES(Name);
304 Info.OrigRet = Result;
305 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs));
306 if (!CLI.lowerCall(MIRBuilder, Info))
Diana Picus02e11012017-06-15 10:53:31 +0000307 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000308
Diana Picuse97822e2017-04-24 07:22:31 +0000309 return LegalizerHelper::Legalized;
310}
311
Diana Picus65ed3642018-01-17 13:34:10 +0000312// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000313static LegalizerHelper::LegalizeResult
314simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
315 Type *OpType) {
316 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000317
318 SmallVector<CallLowering::ArgInfo, 3> Args;
319 for (unsigned i = 1; i < MI.getNumOperands(); i++)
320 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000321 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000322 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000323}
324
Amara Emersoncf12c782019-07-19 00:24:45 +0000325LegalizerHelper::LegalizeResult
326llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
327 MachineInstr &MI) {
328 assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
329 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
330
331 SmallVector<CallLowering::ArgInfo, 3> Args;
332 for (unsigned i = 1; i < MI.getNumOperands(); i++) {
333 Register Reg = MI.getOperand(i).getReg();
334
335 // Need derive an IR type for call lowering.
336 LLT OpLLT = MRI.getType(Reg);
337 Type *OpTy = nullptr;
338 if (OpLLT.isPointer())
339 OpTy = Type::getInt8PtrTy(Ctx, OpLLT.getAddressSpace());
340 else
341 OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits());
342 Args.push_back({Reg, OpTy});
343 }
344
345 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
346 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
347 Intrinsic::ID ID = MI.getOperand(0).getIntrinsicID();
348 RTLIB::Libcall RTLibcall;
349 switch (ID) {
350 case Intrinsic::memcpy:
351 RTLibcall = RTLIB::MEMCPY;
352 break;
353 case Intrinsic::memset:
354 RTLibcall = RTLIB::MEMSET;
355 break;
356 case Intrinsic::memmove:
357 RTLibcall = RTLIB::MEMMOVE;
358 break;
359 default:
360 return LegalizerHelper::UnableToLegalize;
361 }
362 const char *Name = TLI.getLibcallName(RTLibcall);
363
364 MIRBuilder.setInstr(MI);
365 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Tim Northovere1a5f662019-08-09 08:26:38 +0000366
367 CallLowering::CallLoweringInfo Info;
368 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
369 Info.Callee = MachineOperand::CreateES(Name);
370 Info.OrigRet = CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx));
371 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs));
372 if (!CLI.lowerCall(MIRBuilder, Info))
Amara Emersoncf12c782019-07-19 00:24:45 +0000373 return LegalizerHelper::UnableToLegalize;
374
375 return LegalizerHelper::Legalized;
376}
377
Diana Picus65ed3642018-01-17 13:34:10 +0000378static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
379 Type *FromType) {
380 auto ToMVT = MVT::getVT(ToType);
381 auto FromMVT = MVT::getVT(FromType);
382
383 switch (Opcode) {
384 case TargetOpcode::G_FPEXT:
385 return RTLIB::getFPEXT(FromMVT, ToMVT);
386 case TargetOpcode::G_FPTRUNC:
387 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000388 case TargetOpcode::G_FPTOSI:
389 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
390 case TargetOpcode::G_FPTOUI:
391 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000392 case TargetOpcode::G_SITOFP:
393 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
394 case TargetOpcode::G_UITOFP:
395 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000396 }
397 llvm_unreachable("Unsupported libcall function");
398}
399
400static LegalizerHelper::LegalizeResult
401conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
402 Type *FromType) {
403 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
404 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
405 {{MI.getOperand(1).getReg(), FromType}});
406}
407
Tim Northover69fa84a2016-10-14 22:18:18 +0000408LegalizerHelper::LegalizeResult
409LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000410 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
411 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000412 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000413
Diana Picusfc1675e2017-07-05 12:57:24 +0000414 MIRBuilder.setInstr(MI);
415
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000416 switch (MI.getOpcode()) {
417 default:
418 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000419 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000420 case TargetOpcode::G_UDIV:
421 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000422 case TargetOpcode::G_UREM:
423 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000424 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000425 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
426 if (Status != Legalized)
427 return Status;
428 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000429 }
Diana Picus1314a282017-04-11 10:52:34 +0000430 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000431 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000432 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000433 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000434 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000435 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000436 case TargetOpcode::G_FREM:
437 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000438 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000439 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000440 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000441 case TargetOpcode::G_FLOG2:
Jessica Paquettee7941212019-04-03 16:58:32 +0000442 case TargetOpcode::G_FEXP:
Petar Avramovicfaaa2b5d2019-06-06 09:02:24 +0000443 case TargetOpcode::G_FEXP2:
444 case TargetOpcode::G_FCEIL:
445 case TargetOpcode::G_FFLOOR: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000446 if (Size > 64) {
447 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
448 return UnableToLegalize;
449 }
Diana Picus02e11012017-06-15 10:53:31 +0000450 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000451 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
452 if (Status != Legalized)
453 return Status;
454 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000455 }
Diana Picus65ed3642018-01-17 13:34:10 +0000456 case TargetOpcode::G_FPEXT: {
457 // FIXME: Support other floating point types (half, fp128 etc)
458 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
459 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
460 if (ToSize != 64 || FromSize != 32)
461 return UnableToLegalize;
462 LegalizeResult Status = conversionLibcall(
463 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
464 if (Status != Legalized)
465 return Status;
466 break;
467 }
468 case TargetOpcode::G_FPTRUNC: {
469 // FIXME: Support other floating point types (half, fp128 etc)
470 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
471 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
472 if (ToSize != 32 || FromSize != 64)
473 return UnableToLegalize;
474 LegalizeResult Status = conversionLibcall(
475 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
476 if (Status != Legalized)
477 return Status;
478 break;
479 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000480 case TargetOpcode::G_FPTOSI:
481 case TargetOpcode::G_FPTOUI: {
482 // FIXME: Support other types
483 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
484 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000485 if ((ToSize != 32 && ToSize != 64) || (FromSize != 32 && FromSize != 64))
Diana Picus4ed0ee72018-01-30 07:54:52 +0000486 return UnableToLegalize;
487 LegalizeResult Status = conversionLibcall(
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000488 MI, MIRBuilder,
489 ToSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx),
Diana Picus4ed0ee72018-01-30 07:54:52 +0000490 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
491 if (Status != Legalized)
492 return Status;
493 break;
494 }
Diana Picus517531e2018-01-30 09:15:17 +0000495 case TargetOpcode::G_SITOFP:
496 case TargetOpcode::G_UITOFP: {
497 // FIXME: Support other types
498 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
499 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic153bd242019-06-20 09:05:02 +0000500 if ((FromSize != 32 && FromSize != 64) || (ToSize != 32 && ToSize != 64))
Diana Picus517531e2018-01-30 09:15:17 +0000501 return UnableToLegalize;
502 LegalizeResult Status = conversionLibcall(
503 MI, MIRBuilder,
504 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
Petar Avramovic153bd242019-06-20 09:05:02 +0000505 FromSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx));
Diana Picus517531e2018-01-30 09:15:17 +0000506 if (Status != Legalized)
507 return Status;
508 break;
509 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000510 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000511
512 MI.eraseFromParent();
513 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000514}
515
Tim Northover69fa84a2016-10-14 22:18:18 +0000516LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
517 unsigned TypeIdx,
518 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000519 MIRBuilder.setInstr(MI);
520
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000521 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
522 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000523
Tim Northover9656f142016-08-04 20:54:13 +0000524 switch (MI.getOpcode()) {
525 default:
526 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000527 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000528 // FIXME: add support for when SizeOp0 isn't an exact multiple of
529 // NarrowSize.
530 if (SizeOp0 % NarrowSize != 0)
531 return UnableToLegalize;
532 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000533
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000534 SmallVector<Register, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000535 for (int i = 0; i < NumParts; ++i)
536 DstRegs.push_back(
537 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec146042018-12-10 18:44:58 +0000538
Matt Arsenault3018d182019-06-28 01:47:44 +0000539 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec146042018-12-10 18:44:58 +0000540 if(MRI.getType(DstReg).isVector())
541 MIRBuilder.buildBuildVector(DstReg, DstRegs);
542 else
543 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000544 MI.eraseFromParent();
545 return Legalized;
546 }
Matt Arsenault71872722019-04-10 17:27:53 +0000547 case TargetOpcode::G_CONSTANT: {
548 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
549 const APInt &Val = MI.getOperand(1).getCImm()->getValue();
550 unsigned TotalSize = Ty.getSizeInBits();
551 unsigned NarrowSize = NarrowTy.getSizeInBits();
552 int NumParts = TotalSize / NarrowSize;
553
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000554 SmallVector<Register, 4> PartRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000555 for (int I = 0; I != NumParts; ++I) {
556 unsigned Offset = I * NarrowSize;
557 auto K = MIRBuilder.buildConstant(NarrowTy,
558 Val.lshr(Offset).trunc(NarrowSize));
559 PartRegs.push_back(K.getReg(0));
560 }
561
562 LLT LeftoverTy;
563 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000564 SmallVector<Register, 1> LeftoverRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000565 if (LeftoverBits != 0) {
566 LeftoverTy = LLT::scalar(LeftoverBits);
567 auto K = MIRBuilder.buildConstant(
568 LeftoverTy,
569 Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits));
570 LeftoverRegs.push_back(K.getReg(0));
571 }
572
573 insertParts(MI.getOperand(0).getReg(),
574 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
575
576 MI.eraseFromParent();
577 return Legalized;
578 }
Amara Emerson7bc4fad2019-07-26 23:46:38 +0000579 case TargetOpcode::G_SEXT: {
580 if (TypeIdx != 0)
581 return UnableToLegalize;
582
583 if (NarrowTy.getSizeInBits() != SizeOp0 / 2) {
584 LLVM_DEBUG(dbgs() << "Can't narrow sext to type " << NarrowTy << "\n");
585 return UnableToLegalize;
586 }
587
588 Register SrcReg = MI.getOperand(1).getReg();
589
590 // Shift the sign bit of the low register through the high register.
591 auto ShiftAmt =
592 MIRBuilder.buildConstant(LLT::scalar(64), NarrowTy.getSizeInBits() - 1);
593 auto Shift = MIRBuilder.buildAShr(NarrowTy, SrcReg, ShiftAmt);
594 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {SrcReg, Shift.getReg(0)});
595 MI.eraseFromParent();
596 return Legalized;
597 }
598
Tim Northover9656f142016-08-04 20:54:13 +0000599 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000600 // FIXME: add support for when SizeOp0 isn't an exact multiple of
601 // NarrowSize.
602 if (SizeOp0 % NarrowSize != 0)
603 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000604 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000605 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000606
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000607 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000608 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
609 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
610
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000611 Register CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover0f140c72016-09-09 11:46:34 +0000612 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000613
614 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000615 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
616 Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000617
Tim Northover0f140c72016-09-09 11:46:34 +0000618 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000619 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000620
621 DstRegs.push_back(DstReg);
622 CarryIn = CarryOut;
623 }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000624 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec146042018-12-10 18:44:58 +0000625 if(MRI.getType(DstReg).isVector())
626 MIRBuilder.buildBuildVector(DstReg, DstRegs);
627 else
628 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000629 MI.eraseFromParent();
630 return Legalized;
631 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000632 case TargetOpcode::G_SUB: {
633 // FIXME: add support for when SizeOp0 isn't an exact multiple of
634 // NarrowSize.
635 if (SizeOp0 % NarrowSize != 0)
636 return UnableToLegalize;
637
638 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
639
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000640 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000641 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
642 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
643
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000644 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
645 Register BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000646 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
647 {Src1Regs[0], Src2Regs[0]});
648 DstRegs.push_back(DstReg);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000649 Register BorrowIn = BorrowOut;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000650 for (int i = 1; i < NumParts; ++i) {
651 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
652 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
653
654 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
655 {Src1Regs[i], Src2Regs[i], BorrowIn});
656
657 DstRegs.push_back(DstReg);
658 BorrowIn = BorrowOut;
659 }
660 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
661 MI.eraseFromParent();
662 return Legalized;
663 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000664 case TargetOpcode::G_MUL:
Petar Avramovic5229f472019-03-11 10:08:44 +0000665 case TargetOpcode::G_UMULH:
Petar Avramovic0b17e592019-03-11 10:00:17 +0000666 return narrowScalarMul(MI, NarrowTy);
Matt Arsenault1cf713662019-02-12 14:54:52 +0000667 case TargetOpcode::G_EXTRACT:
668 return narrowScalarExtract(MI, TypeIdx, NarrowTy);
669 case TargetOpcode::G_INSERT:
670 return narrowScalarInsert(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000671 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000672 const auto &MMO = **MI.memoperands_begin();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000673 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000674 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000675 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000676 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000677
678 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000679 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000680 auto &MMO = **MI.memoperands_begin();
681 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
682 MIRBuilder.buildAnyExt(DstReg, TmpReg);
683 MI.eraseFromParent();
684 return Legalized;
685 }
686
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000687 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000688 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000689 case TargetOpcode::G_ZEXTLOAD:
690 case TargetOpcode::G_SEXTLOAD: {
691 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000692 Register DstReg = MI.getOperand(0).getReg();
693 Register PtrReg = MI.getOperand(1).getReg();
Matt Arsenault6614f852019-01-22 19:02:10 +0000694
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000695 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault6614f852019-01-22 19:02:10 +0000696 auto &MMO = **MI.memoperands_begin();
Amara Emersond51adf02019-04-17 22:21:05 +0000697 if (MMO.getSizeInBits() == NarrowSize) {
Matt Arsenault6614f852019-01-22 19:02:10 +0000698 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
699 } else {
700 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
701 : TargetOpcode::G_SEXTLOAD;
702 MIRBuilder.buildInstr(ExtLoad)
703 .addDef(TmpReg)
704 .addUse(PtrReg)
705 .addMemOperand(&MMO);
706 }
707
708 if (ZExt)
709 MIRBuilder.buildZExt(DstReg, TmpReg);
710 else
711 MIRBuilder.buildSExt(DstReg, TmpReg);
712
713 MI.eraseFromParent();
714 return Legalized;
715 }
Justin Bognerfde01042017-01-18 17:29:54 +0000716 case TargetOpcode::G_STORE: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000717 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000718
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000719 Register SrcReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000720 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000721 if (SrcTy.isVector())
722 return UnableToLegalize;
723
724 int NumParts = SizeOp0 / NarrowSize;
725 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
726 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
727 if (SrcTy.isVector() && LeftoverBits != 0)
728 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000729
730 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000731 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000732 auto &MMO = **MI.memoperands_begin();
733 MIRBuilder.buildTrunc(TmpReg, SrcReg);
734 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
735 MI.eraseFromParent();
736 return Legalized;
737 }
738
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000739 return reduceLoadStoreWidth(MI, 0, NarrowTy);
Justin Bognerfde01042017-01-18 17:29:54 +0000740 }
Matt Arsenault81511e52019-02-05 00:13:44 +0000741 case TargetOpcode::G_SELECT:
742 return narrowScalarSelect(MI, TypeIdx, NarrowTy);
Petar Avramovic150fd432018-12-18 11:36:14 +0000743 case TargetOpcode::G_AND:
744 case TargetOpcode::G_OR:
745 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000746 // Legalize bitwise operation:
747 // A = BinOp<Ty> B, C
748 // into:
749 // B1, ..., BN = G_UNMERGE_VALUES B
750 // C1, ..., CN = G_UNMERGE_VALUES C
751 // A1 = BinOp<Ty/N> B1, C2
752 // ...
753 // AN = BinOp<Ty/N> BN, CN
754 // A = G_MERGE_VALUES A1, ..., AN
Matt Arsenault9e0eeba2019-04-10 17:07:56 +0000755 return narrowScalarBasic(MI, TypeIdx, NarrowTy);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000756 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000757 case TargetOpcode::G_SHL:
758 case TargetOpcode::G_LSHR:
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +0000759 case TargetOpcode::G_ASHR:
760 return narrowScalarShift(MI, TypeIdx, NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000761 case TargetOpcode::G_CTLZ:
762 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
763 case TargetOpcode::G_CTTZ:
764 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
765 case TargetOpcode::G_CTPOP:
766 if (TypeIdx != 0)
767 return UnableToLegalize; // TODO
768
769 Observer.changingInstr(MI);
770 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
771 Observer.changedInstr(MI);
772 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000773 case TargetOpcode::G_INTTOPTR:
774 if (TypeIdx != 1)
775 return UnableToLegalize;
776
777 Observer.changingInstr(MI);
778 narrowScalarSrc(MI, NarrowTy, 1);
779 Observer.changedInstr(MI);
780 return Legalized;
781 case TargetOpcode::G_PTRTOINT:
782 if (TypeIdx != 0)
783 return UnableToLegalize;
784
785 Observer.changingInstr(MI);
786 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
787 Observer.changedInstr(MI);
788 return Legalized;
Petar Avramovicbe20e362019-07-09 14:36:17 +0000789 case TargetOpcode::G_PHI: {
790 unsigned NumParts = SizeOp0 / NarrowSize;
791 SmallVector<Register, 2> DstRegs;
792 SmallVector<SmallVector<Register, 2>, 2> SrcRegs;
793 DstRegs.resize(NumParts);
794 SrcRegs.resize(MI.getNumOperands() / 2);
795 Observer.changingInstr(MI);
796 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
797 MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB();
798 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
799 extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts,
800 SrcRegs[i / 2]);
801 }
802 MachineBasicBlock &MBB = *MI.getParent();
803 MIRBuilder.setInsertPt(MBB, MI);
804 for (unsigned i = 0; i < NumParts; ++i) {
805 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
806 MachineInstrBuilder MIB =
807 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
808 for (unsigned j = 1; j < MI.getNumOperands(); j += 2)
809 MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1));
810 }
811 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
812 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
813 Observer.changedInstr(MI);
814 MI.eraseFromParent();
815 return Legalized;
816 }
Matt Arsenault434d6642019-07-15 19:37:34 +0000817 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
818 case TargetOpcode::G_INSERT_VECTOR_ELT: {
819 if (TypeIdx != 2)
820 return UnableToLegalize;
821
822 int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
823 Observer.changingInstr(MI);
824 narrowScalarSrc(MI, NarrowTy, OpIdx);
825 Observer.changedInstr(MI);
826 return Legalized;
827 }
Petar Avramovic1e626352019-07-17 12:08:01 +0000828 case TargetOpcode::G_ICMP: {
829 uint64_t SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
830 if (NarrowSize * 2 != SrcSize)
831 return UnableToLegalize;
832
833 Observer.changingInstr(MI);
834 Register LHSL = MRI.createGenericVirtualRegister(NarrowTy);
835 Register LHSH = MRI.createGenericVirtualRegister(NarrowTy);
836 MIRBuilder.buildUnmerge({LHSL, LHSH}, MI.getOperand(2).getReg());
837
838 Register RHSL = MRI.createGenericVirtualRegister(NarrowTy);
839 Register RHSH = MRI.createGenericVirtualRegister(NarrowTy);
840 MIRBuilder.buildUnmerge({RHSL, RHSH}, MI.getOperand(3).getReg());
841
842 CmpInst::Predicate Pred =
843 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
Amara Emersona1997ce2019-07-24 20:46:42 +0000844 LLT ResTy = MRI.getType(MI.getOperand(0).getReg());
Petar Avramovic1e626352019-07-17 12:08:01 +0000845
846 if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) {
847 MachineInstrBuilder XorL = MIRBuilder.buildXor(NarrowTy, LHSL, RHSL);
848 MachineInstrBuilder XorH = MIRBuilder.buildXor(NarrowTy, LHSH, RHSH);
849 MachineInstrBuilder Or = MIRBuilder.buildOr(NarrowTy, XorL, XorH);
850 MachineInstrBuilder Zero = MIRBuilder.buildConstant(NarrowTy, 0);
851 MIRBuilder.buildICmp(Pred, MI.getOperand(0).getReg(), Or, Zero);
852 } else {
Amara Emersona1997ce2019-07-24 20:46:42 +0000853 MachineInstrBuilder CmpH = MIRBuilder.buildICmp(Pred, ResTy, LHSH, RHSH);
Petar Avramovic1e626352019-07-17 12:08:01 +0000854 MachineInstrBuilder CmpHEQ =
Amara Emersona1997ce2019-07-24 20:46:42 +0000855 MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy, LHSH, RHSH);
Petar Avramovic1e626352019-07-17 12:08:01 +0000856 MachineInstrBuilder CmpLU = MIRBuilder.buildICmp(
Amara Emersona1997ce2019-07-24 20:46:42 +0000857 ICmpInst::getUnsignedPredicate(Pred), ResTy, LHSL, RHSL);
Petar Avramovic1e626352019-07-17 12:08:01 +0000858 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), CmpHEQ, CmpLU, CmpH);
859 }
860 Observer.changedInstr(MI);
861 MI.eraseFromParent();
862 return Legalized;
863 }
Tim Northover9656f142016-08-04 20:54:13 +0000864 }
Tim Northover33b07d62016-07-22 20:03:43 +0000865}
866
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000867void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
868 unsigned OpIdx, unsigned ExtOpcode) {
869 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000870 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000871 MO.setReg(ExtB->getOperand(0).getReg());
872}
873
Matt Arsenault30989e42019-01-22 21:42:11 +0000874void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
875 unsigned OpIdx) {
876 MachineOperand &MO = MI.getOperand(OpIdx);
877 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
878 {MO.getReg()});
879 MO.setReg(ExtB->getOperand(0).getReg());
880}
881
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000882void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
883 unsigned OpIdx, unsigned TruncOpcode) {
884 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000885 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000886 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000887 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000888 MO.setReg(DstExt);
889}
890
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000891void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
892 unsigned OpIdx, unsigned ExtOpcode) {
893 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000894 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000895 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
896 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
897 MO.setReg(DstTrunc);
898}
899
Matt Arsenault18ec3822019-02-11 22:00:39 +0000900void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy,
901 unsigned OpIdx) {
902 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000903 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000904 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
905 MIRBuilder.buildExtract(MO.getReg(), DstExt, 0);
906 MO.setReg(DstExt);
907}
908
Matt Arsenault26b7e852019-02-19 16:30:19 +0000909void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy,
910 unsigned OpIdx) {
911 MachineOperand &MO = MI.getOperand(OpIdx);
912
913 LLT OldTy = MRI.getType(MO.getReg());
914 unsigned OldElts = OldTy.getNumElements();
915 unsigned NewElts = MoreTy.getNumElements();
916
917 unsigned NumParts = NewElts / OldElts;
918
919 // Use concat_vectors if the result is a multiple of the number of elements.
920 if (NumParts * OldElts == NewElts) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000921 SmallVector<Register, 8> Parts;
Matt Arsenault26b7e852019-02-19 16:30:19 +0000922 Parts.push_back(MO.getReg());
923
Matt Arsenault3018d182019-06-28 01:47:44 +0000924 Register ImpDef = MIRBuilder.buildUndef(OldTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +0000925 for (unsigned I = 1; I != NumParts; ++I)
926 Parts.push_back(ImpDef);
927
928 auto Concat = MIRBuilder.buildConcatVectors(MoreTy, Parts);
929 MO.setReg(Concat.getReg(0));
930 return;
931 }
932
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000933 Register MoreReg = MRI.createGenericVirtualRegister(MoreTy);
934 Register ImpDef = MIRBuilder.buildUndef(MoreTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +0000935 MIRBuilder.buildInsert(MoreReg, ImpDef, MO.getReg(), 0);
936 MO.setReg(MoreReg);
937}
938
Tim Northover69fa84a2016-10-14 22:18:18 +0000939LegalizerHelper::LegalizeResult
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000940LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
941 LLT WideTy) {
942 if (TypeIdx != 1)
943 return UnableToLegalize;
944
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000945 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000946 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault43cbca52019-07-03 23:08:06 +0000947 if (DstTy.isVector())
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000948 return UnableToLegalize;
949
Matt Arsenaultc9f14f22019-07-01 19:36:10 +0000950 Register Src1 = MI.getOperand(1).getReg();
951 LLT SrcTy = MRI.getType(Src1);
Matt Arsenault0966dd02019-07-17 20:22:44 +0000952 const int DstSize = DstTy.getSizeInBits();
953 const int SrcSize = SrcTy.getSizeInBits();
954 const int WideSize = WideTy.getSizeInBits();
955 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
Matt Arsenaultc9f14f22019-07-01 19:36:10 +0000956
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000957 unsigned NumOps = MI.getNumOperands();
958 unsigned NumSrc = MI.getNumOperands() - 1;
959 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
960
Matt Arsenault0966dd02019-07-17 20:22:44 +0000961 if (WideSize >= DstSize) {
962 // Directly pack the bits in the target type.
963 Register ResultReg = MIRBuilder.buildZExt(WideTy, Src1).getReg(0);
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000964
Matt Arsenault0966dd02019-07-17 20:22:44 +0000965 for (unsigned I = 2; I != NumOps; ++I) {
966 const unsigned Offset = (I - 1) * PartSize;
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000967
Matt Arsenault0966dd02019-07-17 20:22:44 +0000968 Register SrcReg = MI.getOperand(I).getReg();
969 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
970
971 auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg);
972
Matt Arsenault5faa5332019-08-01 18:13:16 +0000973 Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg :
Matt Arsenault0966dd02019-07-17 20:22:44 +0000974 MRI.createGenericVirtualRegister(WideTy);
975
976 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset);
977 auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
978 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
979 ResultReg = NextResult;
980 }
981
982 if (WideSize > DstSize)
983 MIRBuilder.buildTrunc(DstReg, ResultReg);
Matt Arsenault5faa5332019-08-01 18:13:16 +0000984 else if (DstTy.isPointer())
985 MIRBuilder.buildIntToPtr(DstReg, ResultReg);
Matt Arsenault0966dd02019-07-17 20:22:44 +0000986
987 MI.eraseFromParent();
988 return Legalized;
989 }
990
991 // Unmerge the original values to the GCD type, and recombine to the next
992 // multiple greater than the original type.
993 //
994 // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6
995 // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0
996 // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1
997 // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2
998 // %10:_(s6) = G_MERGE_VALUES %4, %5, %6
999 // %11:_(s6) = G_MERGE_VALUES %7, %8, %9
1000 // %12:_(s12) = G_MERGE_VALUES %10, %11
1001 //
1002 // Padding with undef if necessary:
1003 //
1004 // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6
1005 // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0
1006 // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1
1007 // %7:_(s2) = G_IMPLICIT_DEF
1008 // %8:_(s6) = G_MERGE_VALUES %3, %4, %5
1009 // %9:_(s6) = G_MERGE_VALUES %6, %7, %7
1010 // %10:_(s12) = G_MERGE_VALUES %8, %9
1011
1012 const int GCD = greatestCommonDivisor(SrcSize, WideSize);
1013 LLT GCDTy = LLT::scalar(GCD);
1014
1015 SmallVector<Register, 8> Parts;
1016 SmallVector<Register, 8> NewMergeRegs;
1017 SmallVector<Register, 8> Unmerges;
1018 LLT WideDstTy = LLT::scalar(NumMerge * WideSize);
1019
1020 // Decompose the original operands if they don't evenly divide.
1021 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001022 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenault0966dd02019-07-17 20:22:44 +00001023 if (GCD == SrcSize) {
1024 Unmerges.push_back(SrcReg);
1025 } else {
1026 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg);
1027 for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
1028 Unmerges.push_back(Unmerge.getReg(J));
1029 }
1030 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001031
Matt Arsenault0966dd02019-07-17 20:22:44 +00001032 // Pad with undef to the next size that is a multiple of the requested size.
1033 if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) {
1034 Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0);
1035 for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I)
1036 Unmerges.push_back(UndefReg);
1037 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001038
Matt Arsenault0966dd02019-07-17 20:22:44 +00001039 const int PartsPerGCD = WideSize / GCD;
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001040
Matt Arsenault0966dd02019-07-17 20:22:44 +00001041 // Build merges of each piece.
1042 ArrayRef<Register> Slicer(Unmerges);
1043 for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) {
1044 auto Merge = MIRBuilder.buildMerge(WideTy, Slicer.take_front(PartsPerGCD));
1045 NewMergeRegs.push_back(Merge.getReg(0));
1046 }
1047
1048 // A truncate may be necessary if the requested type doesn't evenly divide the
1049 // original result type.
1050 if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) {
1051 MIRBuilder.buildMerge(DstReg, NewMergeRegs);
1052 } else {
1053 auto FinalMerge = MIRBuilder.buildMerge(WideDstTy, NewMergeRegs);
1054 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001055 }
1056
1057 MI.eraseFromParent();
1058 return Legalized;
1059}
1060
1061LegalizerHelper::LegalizeResult
1062LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
1063 LLT WideTy) {
1064 if (TypeIdx != 0)
1065 return UnableToLegalize;
1066
1067 unsigned NumDst = MI.getNumOperands() - 1;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001068 Register SrcReg = MI.getOperand(NumDst).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001069 LLT SrcTy = MRI.getType(SrcReg);
1070 if (!SrcTy.isScalar())
1071 return UnableToLegalize;
1072
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001073 Register Dst0Reg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001074 LLT DstTy = MRI.getType(Dst0Reg);
1075 if (!DstTy.isScalar())
1076 return UnableToLegalize;
1077
1078 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
1079 LLT NewSrcTy = LLT::scalar(NewSrcSize);
1080 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
1081
1082 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
1083
1084 for (unsigned I = 1; I != NumDst; ++I) {
1085 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
1086 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
1087 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
1088 }
1089
1090 Observer.changingInstr(MI);
1091
1092 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
1093 for (unsigned I = 0; I != NumDst; ++I)
1094 widenScalarDst(MI, WideTy, I);
1095
1096 Observer.changedInstr(MI);
1097
1098 return Legalized;
1099}
1100
1101LegalizerHelper::LegalizeResult
Matt Arsenault1cf713662019-02-12 14:54:52 +00001102LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
1103 LLT WideTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001104 Register DstReg = MI.getOperand(0).getReg();
1105 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault1cf713662019-02-12 14:54:52 +00001106 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenaultfbe92a52019-02-18 22:39:27 +00001107
1108 LLT DstTy = MRI.getType(DstReg);
1109 unsigned Offset = MI.getOperand(2).getImm();
1110
1111 if (TypeIdx == 0) {
1112 if (SrcTy.isVector() || DstTy.isVector())
1113 return UnableToLegalize;
1114
1115 SrcOp Src(SrcReg);
1116 if (SrcTy.isPointer()) {
1117 // Extracts from pointers can be handled only if they are really just
1118 // simple integers.
1119 const DataLayout &DL = MIRBuilder.getDataLayout();
1120 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
1121 return UnableToLegalize;
1122
1123 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
1124 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
1125 SrcTy = SrcAsIntTy;
1126 }
1127
1128 if (DstTy.isPointer())
1129 return UnableToLegalize;
1130
1131 if (Offset == 0) {
1132 // Avoid a shift in the degenerate case.
1133 MIRBuilder.buildTrunc(DstReg,
1134 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
1135 MI.eraseFromParent();
1136 return Legalized;
1137 }
1138
1139 // Do a shift in the source type.
1140 LLT ShiftTy = SrcTy;
1141 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
1142 Src = MIRBuilder.buildAnyExt(WideTy, Src);
1143 ShiftTy = WideTy;
1144 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits())
1145 return UnableToLegalize;
1146
1147 auto LShr = MIRBuilder.buildLShr(
1148 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
1149 MIRBuilder.buildTrunc(DstReg, LShr);
1150 MI.eraseFromParent();
1151 return Legalized;
1152 }
1153
Matt Arsenault8f624ab2019-04-22 15:10:42 +00001154 if (SrcTy.isScalar()) {
1155 Observer.changingInstr(MI);
1156 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1157 Observer.changedInstr(MI);
1158 return Legalized;
1159 }
1160
Matt Arsenault1cf713662019-02-12 14:54:52 +00001161 if (!SrcTy.isVector())
1162 return UnableToLegalize;
1163
Matt Arsenault1cf713662019-02-12 14:54:52 +00001164 if (DstTy != SrcTy.getElementType())
1165 return UnableToLegalize;
1166
Matt Arsenault1cf713662019-02-12 14:54:52 +00001167 if (Offset % SrcTy.getScalarSizeInBits() != 0)
1168 return UnableToLegalize;
1169
1170 Observer.changingInstr(MI);
1171 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1172
1173 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
1174 Offset);
1175 widenScalarDst(MI, WideTy.getScalarType(), 0);
1176 Observer.changedInstr(MI);
1177 return Legalized;
1178}
1179
1180LegalizerHelper::LegalizeResult
1181LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
1182 LLT WideTy) {
1183 if (TypeIdx != 0)
1184 return UnableToLegalize;
1185 Observer.changingInstr(MI);
1186 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1187 widenScalarDst(MI, WideTy);
1188 Observer.changedInstr(MI);
1189 return Legalized;
1190}
1191
1192LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001193LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +00001194 MIRBuilder.setInstr(MI);
1195
Tim Northover32335812016-08-04 18:35:11 +00001196 switch (MI.getOpcode()) {
1197 default:
1198 return UnableToLegalize;
Matt Arsenault1cf713662019-02-12 14:54:52 +00001199 case TargetOpcode::G_EXTRACT:
1200 return widenScalarExtract(MI, TypeIdx, WideTy);
1201 case TargetOpcode::G_INSERT:
1202 return widenScalarInsert(MI, TypeIdx, WideTy);
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001203 case TargetOpcode::G_MERGE_VALUES:
1204 return widenScalarMergeValues(MI, TypeIdx, WideTy);
1205 case TargetOpcode::G_UNMERGE_VALUES:
1206 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001207 case TargetOpcode::G_UADDO:
1208 case TargetOpcode::G_USUBO: {
1209 if (TypeIdx == 1)
1210 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001211 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1212 {MI.getOperand(2).getReg()});
1213 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1214 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001215 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
1216 ? TargetOpcode::G_ADD
1217 : TargetOpcode::G_SUB;
1218 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001219 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001220 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
1221 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
1222 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001223 TargetOpcode::G_AND, {WideTy},
1224 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001225 // There is no overflow if the AndOp is the same as NewOp.
1226 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1227 AndOp);
1228 // Now trunc the NewOp to the original result.
1229 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1230 MI.eraseFromParent();
1231 return Legalized;
1232 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001233 case TargetOpcode::G_CTTZ:
1234 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1235 case TargetOpcode::G_CTLZ:
1236 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1237 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001238 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001239 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001240 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001241 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001242 return Legalized;
1243 }
1244
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001245 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001246
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001247 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001248 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1249 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001250 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1251 // The count is the same in the larger type except if the original
1252 // value was zero. This can be handled by setting the bit just off
1253 // the top of the original type.
1254 auto TopBit =
1255 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001256 MIBSrc = MIRBuilder.buildOr(
1257 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001258 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001259
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001260 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001261 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001262 // This is already the correct result for CTPOP and CTTZs
1263 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1264 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1265 // The correct result is NewOp - (Difference in widety and current ty).
1266 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001267 MIBNewOp = MIRBuilder.buildInstr(
1268 TargetOpcode::G_SUB, {WideTy},
1269 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001270 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001271
1272 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1273 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001274 return Legalized;
1275 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001276 case TargetOpcode::G_BSWAP: {
1277 Observer.changingInstr(MI);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001278 Register DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001279
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001280 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
1281 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
1282 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001283 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1284
1285 MI.getOperand(0).setReg(DstExt);
1286
1287 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1288
1289 LLT Ty = MRI.getType(DstReg);
1290 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1291 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1292 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1293 .addDef(ShrReg)
1294 .addUse(DstExt)
1295 .addUse(ShiftAmtReg);
1296
1297 MIRBuilder.buildTrunc(DstReg, ShrReg);
1298 Observer.changedInstr(MI);
1299 return Legalized;
1300 }
Tim Northover61c16142016-08-04 21:39:49 +00001301 case TargetOpcode::G_ADD:
1302 case TargetOpcode::G_AND:
1303 case TargetOpcode::G_MUL:
1304 case TargetOpcode::G_OR:
1305 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001306 case TargetOpcode::G_SUB:
Matt Arsenault1cf713662019-02-12 14:54:52 +00001307 // Perform operation at larger width (any extension is fines here, high bits
Tim Northover32335812016-08-04 18:35:11 +00001308 // don't affect the result) and then truncate the result back to the
1309 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001310 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001311 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1312 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1313 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001314 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001315 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001316
Roman Tereshin6d266382018-05-09 21:43:30 +00001317 case TargetOpcode::G_SHL:
Matt Arsenault012ecbb2019-05-16 04:08:46 +00001318 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001319
1320 if (TypeIdx == 0) {
1321 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1322 widenScalarDst(MI, WideTy);
1323 } else {
1324 assert(TypeIdx == 1);
1325 // The "number of bits to shift" operand must preserve its value as an
1326 // unsigned integer:
1327 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1328 }
1329
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001330 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001331 return Legalized;
1332
Tim Northover7a753d92016-08-26 17:46:06 +00001333 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001334 case TargetOpcode::G_SREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001335 case TargetOpcode::G_SMIN:
1336 case TargetOpcode::G_SMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001337 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001338 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1339 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1340 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001341 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001342 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001343
Roman Tereshin6d266382018-05-09 21:43:30 +00001344 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001345 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001346 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001347
1348 if (TypeIdx == 0) {
1349 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1350 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1351
1352 widenScalarSrc(MI, WideTy, 1, CvtOp);
1353 widenScalarDst(MI, WideTy);
1354 } else {
1355 assert(TypeIdx == 1);
1356 // The "number of bits to shift" operand must preserve its value as an
1357 // unsigned integer:
1358 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1359 }
1360
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001361 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001362 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001363 case TargetOpcode::G_UDIV:
1364 case TargetOpcode::G_UREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001365 case TargetOpcode::G_UMIN:
1366 case TargetOpcode::G_UMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001367 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001368 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1369 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1370 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001371 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001372 return Legalized;
1373
1374 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001375 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001376 if (TypeIdx == 0) {
1377 // Perform operation at larger width (any extension is fine here, high
1378 // bits don't affect the result) and then truncate the result back to the
1379 // original type.
1380 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1381 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1382 widenScalarDst(MI, WideTy);
1383 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001384 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001385 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001386 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001387 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001388 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001389 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001390
Ahmed Bougachab6137062017-01-23 21:10:14 +00001391 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001392 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001393 if (TypeIdx != 0)
1394 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001395 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001396 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001397 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001398 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001399
Ahmed Bougachad2948232017-01-20 01:37:24 +00001400 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001401 if (TypeIdx != 1)
1402 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001403 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001404 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001405 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001406 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001407
1408 case TargetOpcode::G_UITOFP:
1409 if (TypeIdx != 1)
1410 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001411 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001412 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001413 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001414 return Legalized;
1415
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001416 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001417 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001418 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001419 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001420 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001421 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001422 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001423
Tim Northover3c73e362016-08-23 18:20:09 +00001424 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001425 if (TypeIdx != 0)
1426 return UnableToLegalize;
1427
1428 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1429 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001430 return UnableToLegalize;
1431
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001432 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001433
1434 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1435 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1436 widenScalarSrc(MI, WideTy, 0, ExtType);
1437
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001438 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001439 return Legalized;
1440 }
Tim Northoverea904f92016-08-19 22:40:00 +00001441 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001442 MachineOperand &SrcMO = MI.getOperand(1);
1443 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1444 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001445 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001446 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1447
1448 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001449 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001450 return Legalized;
1451 }
Tim Northovera11be042016-08-19 22:40:08 +00001452 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001453 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001454 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001455 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001456 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001457 switch (WideTy.getSizeInBits()) {
1458 case 32:
Matt Arsenault996c6662019-02-12 14:54:54 +00001459 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
1460 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001461 break;
1462 case 64:
Matt Arsenault996c6662019-02-12 14:54:54 +00001463 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
1464 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001465 break;
1466 default:
Matt Arsenault996c6662019-02-12 14:54:54 +00001467 return UnableToLegalize;
Tim Northover6cd4b232016-08-23 21:01:26 +00001468 }
Matt Arsenault996c6662019-02-12 14:54:54 +00001469
1470 assert(!LosesInfo && "extend should always be lossless");
1471
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001472 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001473 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1474
1475 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001476 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001477 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001478 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001479 case TargetOpcode::G_IMPLICIT_DEF: {
1480 Observer.changingInstr(MI);
1481 widenScalarDst(MI, WideTy);
1482 Observer.changedInstr(MI);
1483 return Legalized;
1484 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001485 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001486 Observer.changingInstr(MI);
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +00001487 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001488 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001489 return Legalized;
1490
1491 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001492 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001493 if (TypeIdx == 0)
1494 widenScalarDst(MI, WideTy);
1495 else {
1496 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1497 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001498 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001499 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001500 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001501
1502 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001503 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001504 if (TypeIdx == 0)
1505 widenScalarDst(MI, WideTy);
1506 else {
1507 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1508 MI.getOperand(1).getPredicate()))
1509 ? TargetOpcode::G_SEXT
1510 : TargetOpcode::G_ZEXT;
1511 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1512 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1513 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001514 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001515 return Legalized;
1516
1517 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001518 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001519 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001520 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001521 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001522 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001523
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001524 case TargetOpcode::G_PHI: {
1525 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001526
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001527 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001528 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1529 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1530 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1531 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001532 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001533
1534 MachineBasicBlock &MBB = *MI.getParent();
1535 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1536 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001537 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001538 return Legalized;
1539 }
Matt Arsenault63786292019-01-22 20:38:15 +00001540 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1541 if (TypeIdx == 0) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001542 Register VecReg = MI.getOperand(1).getReg();
Matt Arsenault63786292019-01-22 20:38:15 +00001543 LLT VecTy = MRI.getType(VecReg);
1544 Observer.changingInstr(MI);
1545
1546 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1547 WideTy.getSizeInBits()),
1548 1, TargetOpcode::G_SEXT);
1549
1550 widenScalarDst(MI, WideTy, 0);
1551 Observer.changedInstr(MI);
1552 return Legalized;
1553 }
1554
Amara Emersoncbd86d82018-10-25 14:04:54 +00001555 if (TypeIdx != 2)
1556 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001557 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001558 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001559 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001560 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001561 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001562 case TargetOpcode::G_FADD:
1563 case TargetOpcode::G_FMUL:
1564 case TargetOpcode::G_FSUB:
1565 case TargetOpcode::G_FMA:
1566 case TargetOpcode::G_FNEG:
1567 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001568 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001569 case TargetOpcode::G_FMINNUM:
1570 case TargetOpcode::G_FMAXNUM:
1571 case TargetOpcode::G_FMINNUM_IEEE:
1572 case TargetOpcode::G_FMAXNUM_IEEE:
1573 case TargetOpcode::G_FMINIMUM:
1574 case TargetOpcode::G_FMAXIMUM:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001575 case TargetOpcode::G_FDIV:
1576 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001577 case TargetOpcode::G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00001578 case TargetOpcode::G_FFLOOR:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001579 case TargetOpcode::G_FCOS:
1580 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001581 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001582 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001583 case TargetOpcode::G_FLOG2:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00001584 case TargetOpcode::G_FRINT:
Jessica Paquetteba557672019-04-25 16:44:40 +00001585 case TargetOpcode::G_FNEARBYINT:
Jessica Paquette22457f82019-01-30 21:03:52 +00001586 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001587 case TargetOpcode::G_FEXP:
Jessica Paquettee7941212019-04-03 16:58:32 +00001588 case TargetOpcode::G_FEXP2:
Jessica Paquettedfd87f62019-04-19 16:28:08 +00001589 case TargetOpcode::G_FPOW:
Jessica Paquette56342642019-04-23 18:20:44 +00001590 case TargetOpcode::G_INTRINSIC_TRUNC:
Jessica Paquette3cc6d1f2019-04-23 21:11:57 +00001591 case TargetOpcode::G_INTRINSIC_ROUND:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001592 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001593 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001594
1595 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1596 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1597
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001598 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1599 Observer.changedInstr(MI);
1600 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001601 case TargetOpcode::G_INTTOPTR:
1602 if (TypeIdx != 1)
1603 return UnableToLegalize;
1604
1605 Observer.changingInstr(MI);
1606 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1607 Observer.changedInstr(MI);
1608 return Legalized;
1609 case TargetOpcode::G_PTRTOINT:
1610 if (TypeIdx != 0)
1611 return UnableToLegalize;
1612
1613 Observer.changingInstr(MI);
1614 widenScalarDst(MI, WideTy, 0);
1615 Observer.changedInstr(MI);
1616 return Legalized;
Matt Arsenaultbd791b52019-07-08 13:48:06 +00001617 case TargetOpcode::G_BUILD_VECTOR: {
1618 Observer.changingInstr(MI);
1619
1620 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType();
1621 for (int I = 1, E = MI.getNumOperands(); I != E; ++I)
1622 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT);
1623
1624 // Avoid changing the result vector type if the source element type was
1625 // requested.
1626 if (TypeIdx == 1) {
1627 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
1628 MI.setDesc(TII.get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
1629 } else {
1630 widenScalarDst(MI, WideTy, 0);
1631 }
1632
1633 Observer.changedInstr(MI);
1634 return Legalized;
1635 }
Tim Northover32335812016-08-04 18:35:11 +00001636 }
Tim Northover33b07d62016-07-22 20:03:43 +00001637}
1638
Tim Northover69fa84a2016-10-14 22:18:18 +00001639LegalizerHelper::LegalizeResult
1640LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001641 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001642 MIRBuilder.setInstr(MI);
1643
1644 switch(MI.getOpcode()) {
1645 default:
1646 return UnableToLegalize;
1647 case TargetOpcode::G_SREM:
1648 case TargetOpcode::G_UREM: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001649 Register QuotReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001650 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001651 .addDef(QuotReg)
1652 .addUse(MI.getOperand(1).getReg())
1653 .addUse(MI.getOperand(2).getReg());
1654
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001655 Register ProdReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001656 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1657 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1658 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001659 MI.eraseFromParent();
1660 return Legalized;
1661 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001662 case TargetOpcode::G_SMULO:
1663 case TargetOpcode::G_UMULO: {
1664 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1665 // result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001666 Register Res = MI.getOperand(0).getReg();
1667 Register Overflow = MI.getOperand(1).getReg();
1668 Register LHS = MI.getOperand(2).getReg();
1669 Register RHS = MI.getOperand(3).getReg();
Tim Northover0a9b2792017-02-08 21:22:15 +00001670
1671 MIRBuilder.buildMul(Res, LHS, RHS);
1672
1673 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1674 ? TargetOpcode::G_SMULH
1675 : TargetOpcode::G_UMULH;
1676
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001677 Register HiPart = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001678 MIRBuilder.buildInstr(Opcode)
1679 .addDef(HiPart)
1680 .addUse(LHS)
1681 .addUse(RHS);
1682
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001683 Register Zero = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001684 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001685
1686 // For *signed* multiply, overflow is detected by checking:
1687 // (hi != (lo >> bitwidth-1))
1688 if (Opcode == TargetOpcode::G_SMULH) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001689 Register Shifted = MRI.createGenericVirtualRegister(Ty);
1690 Register ShiftAmt = MRI.createGenericVirtualRegister(Ty);
Amara Emerson9de62132018-01-03 04:56:56 +00001691 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1692 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1693 .addDef(Shifted)
1694 .addUse(Res)
1695 .addUse(ShiftAmt);
1696 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1697 } else {
1698 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1699 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001700 MI.eraseFromParent();
1701 return Legalized;
1702 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001703 case TargetOpcode::G_FNEG: {
1704 // TODO: Handle vector types once we are able to
1705 // represent them.
1706 if (Ty.isVector())
1707 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001708 Register Res = MI.getOperand(0).getReg();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001709 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001710 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001711 switch (Ty.getSizeInBits()) {
1712 case 16:
1713 ZeroTy = Type::getHalfTy(Ctx);
1714 break;
1715 case 32:
1716 ZeroTy = Type::getFloatTy(Ctx);
1717 break;
1718 case 64:
1719 ZeroTy = Type::getDoubleTy(Ctx);
1720 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001721 case 128:
1722 ZeroTy = Type::getFP128Ty(Ctx);
1723 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001724 default:
1725 llvm_unreachable("unexpected floating-point type");
1726 }
1727 ConstantFP &ZeroForNegation =
1728 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001729 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001730 Register SubByReg = MI.getOperand(1).getReg();
1731 Register ZeroReg = Zero->getOperand(0).getReg();
Michael Bergd573aa02019-04-18 18:48:57 +00001732 MIRBuilder.buildInstr(TargetOpcode::G_FSUB, {Res}, {ZeroReg, SubByReg},
Matt Arsenault5a321b82019-06-17 23:48:43 +00001733 MI.getFlags());
Volkan Keles5698b2a2017-03-08 18:09:14 +00001734 MI.eraseFromParent();
1735 return Legalized;
1736 }
Volkan Keles225921a2017-03-10 21:25:09 +00001737 case TargetOpcode::G_FSUB: {
1738 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1739 // First, check if G_FNEG is marked as Lower. If so, we may
1740 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001741 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001742 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001743 Register Res = MI.getOperand(0).getReg();
1744 Register LHS = MI.getOperand(1).getReg();
1745 Register RHS = MI.getOperand(2).getReg();
1746 Register Neg = MRI.createGenericVirtualRegister(Ty);
Volkan Keles225921a2017-03-10 21:25:09 +00001747 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
Michael Bergd573aa02019-04-18 18:48:57 +00001748 MIRBuilder.buildInstr(TargetOpcode::G_FADD, {Res}, {LHS, Neg}, MI.getFlags());
Volkan Keles225921a2017-03-10 21:25:09 +00001749 MI.eraseFromParent();
1750 return Legalized;
1751 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001752 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001753 Register OldValRes = MI.getOperand(0).getReg();
1754 Register SuccessRes = MI.getOperand(1).getReg();
1755 Register Addr = MI.getOperand(2).getReg();
1756 Register CmpVal = MI.getOperand(3).getReg();
1757 Register NewVal = MI.getOperand(4).getReg();
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001758 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1759 **MI.memoperands_begin());
1760 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1761 MI.eraseFromParent();
1762 return Legalized;
1763 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001764 case TargetOpcode::G_LOAD:
1765 case TargetOpcode::G_SEXTLOAD:
1766 case TargetOpcode::G_ZEXTLOAD: {
1767 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001768 Register DstReg = MI.getOperand(0).getReg();
1769 Register PtrReg = MI.getOperand(1).getReg();
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001770 LLT DstTy = MRI.getType(DstReg);
1771 auto &MMO = **MI.memoperands_begin();
1772
Amara Emersonc8351642019-08-02 23:44:24 +00001773 if (DstTy.getSizeInBits() == MMO.getSizeInBits()) {
1774 if (MI.getOpcode() == TargetOpcode::G_LOAD) {
1775 // This load needs splitting into power of 2 sized loads.
1776 if (DstTy.isVector())
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001777 return UnableToLegalize;
Amara Emersonc8351642019-08-02 23:44:24 +00001778 if (isPowerOf2_32(DstTy.getSizeInBits()))
1779 return UnableToLegalize; // Don't know what we're being asked to do.
1780
1781 // Our strategy here is to generate anyextending loads for the smaller
1782 // types up to next power-2 result type, and then combine the two larger
1783 // result values together, before truncating back down to the non-pow-2
1784 // type.
1785 // E.g. v1 = i24 load =>
1786 // v2 = i32 load (2 byte)
1787 // v3 = i32 load (1 byte)
1788 // v4 = i32 shl v3, 16
1789 // v5 = i32 or v4, v2
1790 // v1 = i24 trunc v5
1791 // By doing this we generate the correct truncate which should get
1792 // combined away as an artifact with a matching extend.
1793 uint64_t LargeSplitSize = PowerOf2Floor(DstTy.getSizeInBits());
1794 uint64_t SmallSplitSize = DstTy.getSizeInBits() - LargeSplitSize;
1795
1796 MachineFunction &MF = MIRBuilder.getMF();
1797 MachineMemOperand *LargeMMO =
1798 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
1799 MachineMemOperand *SmallMMO = MF.getMachineMemOperand(
1800 &MMO, LargeSplitSize / 8, SmallSplitSize / 8);
1801
1802 LLT PtrTy = MRI.getType(PtrReg);
1803 unsigned AnyExtSize = NextPowerOf2(DstTy.getSizeInBits());
1804 LLT AnyExtTy = LLT::scalar(AnyExtSize);
1805 Register LargeLdReg = MRI.createGenericVirtualRegister(AnyExtTy);
1806 Register SmallLdReg = MRI.createGenericVirtualRegister(AnyExtTy);
1807 auto LargeLoad =
1808 MIRBuilder.buildLoad(LargeLdReg, PtrReg, *LargeMMO);
1809
1810 auto OffsetCst =
1811 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8);
1812 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy);
1813 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0));
1814 auto SmallLoad = MIRBuilder.buildLoad(SmallLdReg, SmallPtr.getReg(0),
1815 *SmallMMO);
1816
1817 auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
1818 auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
1819 auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
1820 MIRBuilder.buildTrunc(DstReg, {Or.getReg(0)});
1821 MI.eraseFromParent();
1822 return Legalized;
1823 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001824 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1825 MI.eraseFromParent();
1826 return Legalized;
1827 }
1828
1829 if (DstTy.isScalar()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001830 Register TmpReg =
Amara Emersond51adf02019-04-17 22:21:05 +00001831 MRI.createGenericVirtualRegister(LLT::scalar(MMO.getSizeInBits()));
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001832 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1833 switch (MI.getOpcode()) {
1834 default:
1835 llvm_unreachable("Unexpected opcode");
1836 case TargetOpcode::G_LOAD:
1837 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1838 break;
1839 case TargetOpcode::G_SEXTLOAD:
1840 MIRBuilder.buildSExt(DstReg, TmpReg);
1841 break;
1842 case TargetOpcode::G_ZEXTLOAD:
1843 MIRBuilder.buildZExt(DstReg, TmpReg);
1844 break;
1845 }
1846 MI.eraseFromParent();
1847 return Legalized;
1848 }
1849
1850 return UnableToLegalize;
1851 }
Amara Emersonc8351642019-08-02 23:44:24 +00001852 case TargetOpcode::G_STORE: {
1853 // Lower a non-power of 2 store into multiple pow-2 stores.
1854 // E.g. split an i24 store into an i16 store + i8 store.
1855 // We do this by first extending the stored value to the next largest power
1856 // of 2 type, and then using truncating stores to store the components.
1857 // By doing this, likewise with G_LOAD, generate an extend that can be
1858 // artifact-combined away instead of leaving behind extracts.
1859 Register SrcReg = MI.getOperand(0).getReg();
1860 Register PtrReg = MI.getOperand(1).getReg();
1861 LLT SrcTy = MRI.getType(SrcReg);
1862 MachineMemOperand &MMO = **MI.memoperands_begin();
1863 if (SrcTy.getSizeInBits() != MMO.getSizeInBits())
1864 return UnableToLegalize;
1865 if (SrcTy.isVector())
1866 return UnableToLegalize;
1867 if (isPowerOf2_32(SrcTy.getSizeInBits()))
1868 return UnableToLegalize; // Don't know what we're being asked to do.
1869
1870 // Extend to the next pow-2.
1871 const LLT ExtendTy = LLT::scalar(NextPowerOf2(SrcTy.getSizeInBits()));
1872 auto ExtVal = MIRBuilder.buildAnyExt(ExtendTy, SrcReg);
1873
1874 // Obtain the smaller value by shifting away the larger value.
1875 uint64_t LargeSplitSize = PowerOf2Floor(SrcTy.getSizeInBits());
1876 uint64_t SmallSplitSize = SrcTy.getSizeInBits() - LargeSplitSize;
1877 auto ShiftAmt = MIRBuilder.buildConstant(ExtendTy, LargeSplitSize);
1878 auto SmallVal = MIRBuilder.buildLShr(ExtendTy, ExtVal, ShiftAmt);
1879
1880 // Generate the GEP and truncating stores.
1881 LLT PtrTy = MRI.getType(PtrReg);
1882 auto OffsetCst =
1883 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8);
1884 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy);
1885 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0));
1886
1887 MachineFunction &MF = MIRBuilder.getMF();
1888 MachineMemOperand *LargeMMO =
1889 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
1890 MachineMemOperand *SmallMMO =
1891 MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8);
1892 MIRBuilder.buildStore(ExtVal.getReg(0), PtrReg, *LargeMMO);
1893 MIRBuilder.buildStore(SmallVal.getReg(0), SmallPtr.getReg(0), *SmallMMO);
1894 MI.eraseFromParent();
1895 return Legalized;
1896 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001897 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1898 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1899 case TargetOpcode::G_CTLZ:
1900 case TargetOpcode::G_CTTZ:
1901 case TargetOpcode::G_CTPOP:
1902 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicbd395692019-02-26 17:22:42 +00001903 case G_UADDO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001904 Register Res = MI.getOperand(0).getReg();
1905 Register CarryOut = MI.getOperand(1).getReg();
1906 Register LHS = MI.getOperand(2).getReg();
1907 Register RHS = MI.getOperand(3).getReg();
Petar Avramovicbd395692019-02-26 17:22:42 +00001908
1909 MIRBuilder.buildAdd(Res, LHS, RHS);
1910 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS);
1911
1912 MI.eraseFromParent();
1913 return Legalized;
1914 }
Petar Avramovicb8276f22018-12-17 12:31:07 +00001915 case G_UADDE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001916 Register Res = MI.getOperand(0).getReg();
1917 Register CarryOut = MI.getOperand(1).getReg();
1918 Register LHS = MI.getOperand(2).getReg();
1919 Register RHS = MI.getOperand(3).getReg();
1920 Register CarryIn = MI.getOperand(4).getReg();
Petar Avramovicb8276f22018-12-17 12:31:07 +00001921
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001922 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1923 Register ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001924
1925 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1926 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1927 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1928 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1929
1930 MI.eraseFromParent();
1931 return Legalized;
1932 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001933 case G_USUBO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001934 Register Res = MI.getOperand(0).getReg();
1935 Register BorrowOut = MI.getOperand(1).getReg();
1936 Register LHS = MI.getOperand(2).getReg();
1937 Register RHS = MI.getOperand(3).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001938
1939 MIRBuilder.buildSub(Res, LHS, RHS);
1940 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1941
1942 MI.eraseFromParent();
1943 return Legalized;
1944 }
1945 case G_USUBE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001946 Register Res = MI.getOperand(0).getReg();
1947 Register BorrowOut = MI.getOperand(1).getReg();
1948 Register LHS = MI.getOperand(2).getReg();
1949 Register RHS = MI.getOperand(3).getReg();
1950 Register BorrowIn = MI.getOperand(4).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001951
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001952 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1953 Register ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1954 Register LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1955 Register LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001956
1957 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1958 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1959 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1960 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1961 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1962 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1963
1964 MI.eraseFromParent();
1965 return Legalized;
1966 }
Matt Arsenault02b5ca82019-05-17 23:05:13 +00001967 case G_UITOFP:
1968 return lowerUITOFP(MI, TypeIdx, Ty);
1969 case G_SITOFP:
1970 return lowerSITOFP(MI, TypeIdx, Ty);
Matt Arsenault6f74f552019-07-01 17:18:03 +00001971 case G_SMIN:
1972 case G_SMAX:
1973 case G_UMIN:
1974 case G_UMAX:
1975 return lowerMinMax(MI, TypeIdx, Ty);
Matt Arsenaultb1843e12019-07-09 23:34:29 +00001976 case G_FCOPYSIGN:
1977 return lowerFCopySign(MI, TypeIdx, Ty);
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001978 case G_FMINNUM:
1979 case G_FMAXNUM:
1980 return lowerFMinNumMaxNum(MI);
Matt Arsenaultd9d30a42019-08-01 19:10:05 +00001981 case G_UNMERGE_VALUES:
1982 return lowerUnmergeValues(MI);
Tim Northovercecee562016-08-26 17:46:13 +00001983 }
1984}
1985
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001986LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1987 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001988 SmallVector<Register, 2> DstRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001989
1990 unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001991 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001992 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1993 int NumParts = Size / NarrowSize;
1994 // FIXME: Don't know how to handle the situation where the small vectors
1995 // aren't all the same size yet.
1996 if (Size % NarrowSize != 0)
1997 return UnableToLegalize;
1998
1999 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002000 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002001 MIRBuilder.buildUndef(TmpReg);
2002 DstRegs.push_back(TmpReg);
2003 }
2004
2005 if (NarrowTy.isVector())
2006 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2007 else
2008 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2009
2010 MI.eraseFromParent();
2011 return Legalized;
2012}
2013
2014LegalizerHelper::LegalizeResult
2015LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
2016 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002017 const unsigned Opc = MI.getOpcode();
2018 const unsigned NumOps = MI.getNumOperands() - 1;
2019 const unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenault3018d182019-06-28 01:47:44 +00002020 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002021 const unsigned Flags = MI.getFlags();
2022 const LLT DstTy = MRI.getType(DstReg);
2023 const unsigned Size = DstTy.getSizeInBits();
2024 const int NumParts = Size / NarrowSize;
2025 const LLT EltTy = DstTy.getElementType();
2026 const unsigned EltSize = EltTy.getSizeInBits();
2027 const unsigned BitsForNumParts = NarrowSize * NumParts;
2028
2029 // Check if we have any leftovers. If we do, then only handle the case where
2030 // the leftover is one element.
2031 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002032 return UnableToLegalize;
2033
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002034 if (BitsForNumParts != Size) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002035 Register AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002036 MIRBuilder.buildUndef(AccumDstReg);
2037
2038 // Handle the pieces which evenly divide into the requested type with
2039 // extract/op/insert sequence.
2040 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
2041 SmallVector<SrcOp, 4> SrcOps;
2042 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002043 Register PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002044 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
2045 SrcOps.push_back(PartOpReg);
2046 }
2047
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002048 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002049 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
2050
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002051 Register PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002052 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
2053 AccumDstReg = PartInsertReg;
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002054 }
2055
2056 // Handle the remaining element sized leftover piece.
2057 SmallVector<SrcOp, 4> SrcOps;
2058 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002059 Register PartOpReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002060 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
2061 BitsForNumParts);
2062 SrcOps.push_back(PartOpReg);
2063 }
2064
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002065 Register PartDstReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002066 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
2067 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
2068 MI.eraseFromParent();
2069
2070 return Legalized;
2071 }
2072
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002073 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002074
2075 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
2076
2077 if (NumOps >= 2)
2078 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
2079
2080 if (NumOps >= 3)
2081 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
2082
2083 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002084 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002085
2086 if (NumOps == 1)
2087 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
2088 else if (NumOps == 2) {
2089 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
2090 } else if (NumOps == 3) {
2091 MIRBuilder.buildInstr(Opc, {DstReg},
2092 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
2093 }
2094
2095 DstRegs.push_back(DstReg);
2096 }
2097
2098 if (NarrowTy.isVector())
2099 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2100 else
2101 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2102
2103 MI.eraseFromParent();
2104 return Legalized;
2105}
2106
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002107// Handle splitting vector operations which need to have the same number of
2108// elements in each type index, but each type index may have a different element
2109// type.
2110//
2111// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
2112// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2113// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2114//
2115// Also handles some irregular breakdown cases, e.g.
2116// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
2117// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2118// s64 = G_SHL s64, s32
2119LegalizerHelper::LegalizeResult
2120LegalizerHelper::fewerElementsVectorMultiEltType(
2121 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
2122 if (TypeIdx != 0)
2123 return UnableToLegalize;
2124
2125 const LLT NarrowTy0 = NarrowTyArg;
2126 const unsigned NewNumElts =
2127 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
2128
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002129 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002130 LLT DstTy = MRI.getType(DstReg);
2131 LLT LeftoverTy0;
2132
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002133 // All of the operands need to have the same number of elements, so if we can
2134 // determine a type breakdown for the result type, we can for all of the
2135 // source types.
Fangrui Songb251cc02019-07-12 14:58:15 +00002136 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0).first;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002137 if (NumParts < 0)
2138 return UnableToLegalize;
2139
2140 SmallVector<MachineInstrBuilder, 4> NewInsts;
2141
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002142 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
2143 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002144
2145 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
2146 LLT LeftoverTy;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002147 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002148 LLT SrcTyI = MRI.getType(SrcReg);
2149 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
2150 LLT LeftoverTyI;
2151
2152 // Split this operand into the requested typed registers, and any leftover
2153 // required to reproduce the original type.
2154 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
2155 LeftoverRegs))
2156 return UnableToLegalize;
2157
2158 if (I == 1) {
2159 // For the first operand, create an instruction for each part and setup
2160 // the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002161 for (Register PartReg : PartRegs) {
2162 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002163 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2164 .addDef(PartDstReg)
2165 .addUse(PartReg));
2166 DstRegs.push_back(PartDstReg);
2167 }
2168
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002169 for (Register LeftoverReg : LeftoverRegs) {
2170 Register PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002171 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2172 .addDef(PartDstReg)
2173 .addUse(LeftoverReg));
2174 LeftoverDstRegs.push_back(PartDstReg);
2175 }
2176 } else {
2177 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
2178
2179 // Add the newly created operand splits to the existing instructions. The
2180 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2181 // pieces.
2182 unsigned InstCount = 0;
2183 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
2184 NewInsts[InstCount++].addUse(PartRegs[J]);
2185 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
2186 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
2187 }
2188
2189 PartRegs.clear();
2190 LeftoverRegs.clear();
2191 }
2192
2193 // Insert the newly built operations and rebuild the result register.
2194 for (auto &MIB : NewInsts)
2195 MIRBuilder.insertInstr(MIB);
2196
2197 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
2198
2199 MI.eraseFromParent();
2200 return Legalized;
2201}
2202
Tim Northover69fa84a2016-10-14 22:18:18 +00002203LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00002204LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
2205 LLT NarrowTy) {
2206 if (TypeIdx != 0)
2207 return UnableToLegalize;
2208
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002209 Register DstReg = MI.getOperand(0).getReg();
2210 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenaultca676342019-01-25 02:36:32 +00002211 LLT DstTy = MRI.getType(DstReg);
2212 LLT SrcTy = MRI.getType(SrcReg);
2213
2214 LLT NarrowTy0 = NarrowTy;
2215 LLT NarrowTy1;
2216 unsigned NumParts;
2217
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002218 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00002219 // Uneven breakdown not handled.
2220 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
2221 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
2222 return UnableToLegalize;
2223
2224 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002225 } else {
2226 NumParts = DstTy.getNumElements();
2227 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00002228 }
2229
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002230 SmallVector<Register, 4> SrcRegs, DstRegs;
Matt Arsenaultca676342019-01-25 02:36:32 +00002231 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
2232
2233 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002234 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultca676342019-01-25 02:36:32 +00002235 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
2236 .addDef(DstReg)
2237 .addUse(SrcRegs[I]);
2238
2239 NewInst->setFlags(MI.getFlags());
2240 DstRegs.push_back(DstReg);
2241 }
2242
2243 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002244 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002245 else
2246 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2247
2248 MI.eraseFromParent();
2249 return Legalized;
2250}
2251
2252LegalizerHelper::LegalizeResult
2253LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
2254 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002255 Register DstReg = MI.getOperand(0).getReg();
2256 Register Src0Reg = MI.getOperand(2).getReg();
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002257 LLT DstTy = MRI.getType(DstReg);
2258 LLT SrcTy = MRI.getType(Src0Reg);
2259
2260 unsigned NumParts;
2261 LLT NarrowTy0, NarrowTy1;
2262
2263 if (TypeIdx == 0) {
2264 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2265 unsigned OldElts = DstTy.getNumElements();
2266
2267 NarrowTy0 = NarrowTy;
2268 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
2269 NarrowTy1 = NarrowTy.isVector() ?
2270 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
2271 SrcTy.getElementType();
2272
2273 } else {
2274 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2275 unsigned OldElts = SrcTy.getNumElements();
2276
2277 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
2278 NarrowTy.getNumElements();
2279 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
2280 DstTy.getScalarSizeInBits());
2281 NarrowTy1 = NarrowTy;
2282 }
2283
2284 // FIXME: Don't know how to handle the situation where the small vectors
2285 // aren't all the same size yet.
2286 if (NarrowTy1.isVector() &&
2287 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
2288 return UnableToLegalize;
2289
2290 CmpInst::Predicate Pred
2291 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
2292
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002293 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002294 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
2295 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
2296
2297 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002298 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002299 DstRegs.push_back(DstReg);
2300
2301 if (MI.getOpcode() == TargetOpcode::G_ICMP)
2302 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2303 else {
2304 MachineInstr *NewCmp
2305 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2306 NewCmp->setFlags(MI.getFlags());
2307 }
2308 }
2309
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002310 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00002311 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2312 else
2313 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2314
2315 MI.eraseFromParent();
2316 return Legalized;
2317}
2318
2319LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002320LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
2321 LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002322 Register DstReg = MI.getOperand(0).getReg();
2323 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002324
2325 unsigned NumParts = 0;
2326 LLT NarrowTy0, NarrowTy1;
2327
2328 LLT DstTy = MRI.getType(DstReg);
2329 LLT CondTy = MRI.getType(CondReg);
2330 unsigned Size = DstTy.getSizeInBits();
2331
2332 assert(TypeIdx == 0 || CondTy.isVector());
2333
2334 if (TypeIdx == 0) {
2335 NarrowTy0 = NarrowTy;
2336 NarrowTy1 = CondTy;
2337
2338 unsigned NarrowSize = NarrowTy0.getSizeInBits();
2339 // FIXME: Don't know how to handle the situation where the small vectors
2340 // aren't all the same size yet.
2341 if (Size % NarrowSize != 0)
2342 return UnableToLegalize;
2343
2344 NumParts = Size / NarrowSize;
2345
2346 // Need to break down the condition type
2347 if (CondTy.isVector()) {
2348 if (CondTy.getNumElements() == NumParts)
2349 NarrowTy1 = CondTy.getElementType();
2350 else
2351 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
2352 CondTy.getScalarSizeInBits());
2353 }
2354 } else {
2355 NumParts = CondTy.getNumElements();
2356 if (NarrowTy.isVector()) {
2357 // TODO: Handle uneven breakdown.
2358 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
2359 return UnableToLegalize;
2360
2361 return UnableToLegalize;
2362 } else {
2363 NarrowTy0 = DstTy.getElementType();
2364 NarrowTy1 = NarrowTy;
2365 }
2366 }
2367
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002368 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002369 if (CondTy.isVector())
2370 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2371
2372 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2373 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2374
2375 for (unsigned i = 0; i < NumParts; ++i) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002376 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002377 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2378 Src1Regs[i], Src2Regs[i]);
2379 DstRegs.push_back(DstReg);
2380 }
2381
2382 if (NarrowTy0.isVector())
2383 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2384 else
2385 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2386
2387 MI.eraseFromParent();
2388 return Legalized;
2389}
2390
2391LegalizerHelper::LegalizeResult
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002392LegalizerHelper::fewerElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2393 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002394 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002395 LLT PhiTy = MRI.getType(DstReg);
2396 LLT LeftoverTy;
2397
2398 // All of the operands need to have the same number of elements, so if we can
2399 // determine a type breakdown for the result type, we can for all of the
2400 // source types.
2401 int NumParts, NumLeftover;
2402 std::tie(NumParts, NumLeftover)
2403 = getNarrowTypeBreakDown(PhiTy, NarrowTy, LeftoverTy);
2404 if (NumParts < 0)
2405 return UnableToLegalize;
2406
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002407 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002408 SmallVector<MachineInstrBuilder, 4> NewInsts;
2409
2410 const int TotalNumParts = NumParts + NumLeftover;
2411
2412 // Insert the new phis in the result block first.
2413 for (int I = 0; I != TotalNumParts; ++I) {
2414 LLT Ty = I < NumParts ? NarrowTy : LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002415 Register PartDstReg = MRI.createGenericVirtualRegister(Ty);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002416 NewInsts.push_back(MIRBuilder.buildInstr(TargetOpcode::G_PHI)
2417 .addDef(PartDstReg));
2418 if (I < NumParts)
2419 DstRegs.push_back(PartDstReg);
2420 else
2421 LeftoverDstRegs.push_back(PartDstReg);
2422 }
2423
2424 MachineBasicBlock *MBB = MI.getParent();
2425 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
2426 insertParts(DstReg, PhiTy, NarrowTy, DstRegs, LeftoverTy, LeftoverDstRegs);
2427
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002428 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002429
2430 // Insert code to extract the incoming values in each predecessor block.
2431 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2432 PartRegs.clear();
2433 LeftoverRegs.clear();
2434
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002435 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002436 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2437 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2438
2439 LLT Unused;
2440 if (!extractParts(SrcReg, PhiTy, NarrowTy, Unused, PartRegs,
2441 LeftoverRegs))
2442 return UnableToLegalize;
2443
2444 // Add the newly created operand splits to the existing instructions. The
2445 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2446 // pieces.
2447 for (int J = 0; J != TotalNumParts; ++J) {
2448 MachineInstrBuilder MIB = NewInsts[J];
2449 MIB.addUse(J < NumParts ? PartRegs[J] : LeftoverRegs[J - NumParts]);
2450 MIB.addMBB(&OpMBB);
2451 }
2452 }
2453
2454 MI.eraseFromParent();
2455 return Legalized;
2456}
2457
2458LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002459LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2460 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002461 // FIXME: Don't know how to handle secondary types yet.
2462 if (TypeIdx != 0)
2463 return UnableToLegalize;
2464
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002465 MachineMemOperand *MMO = *MI.memoperands_begin();
2466
2467 // This implementation doesn't work for atomics. Give up instead of doing
2468 // something invalid.
2469 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2470 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2471 return UnableToLegalize;
2472
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002473 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002474 Register ValReg = MI.getOperand(0).getReg();
2475 Register AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002476 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002477
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002478 int NumParts = -1;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002479 int NumLeftover = -1;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002480 LLT LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002481 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002482 if (IsLoad) {
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002483 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002484 } else {
2485 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002486 NarrowLeftoverRegs)) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002487 NumParts = NarrowRegs.size();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002488 NumLeftover = NarrowLeftoverRegs.size();
2489 }
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002490 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002491
2492 if (NumParts == -1)
2493 return UnableToLegalize;
2494
2495 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2496
2497 unsigned TotalSize = ValTy.getSizeInBits();
2498
2499 // Split the load/store into PartTy sized pieces starting at Offset. If this
2500 // is a load, return the new registers in ValRegs. For a store, each elements
2501 // of ValRegs should be PartTy. Returns the next offset that needs to be
2502 // handled.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002503 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002504 unsigned Offset) -> unsigned {
2505 MachineFunction &MF = MIRBuilder.getMF();
2506 unsigned PartSize = PartTy.getSizeInBits();
2507 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2508 Offset += PartSize, ++Idx) {
2509 unsigned ByteSize = PartSize / 8;
2510 unsigned ByteOffset = Offset / 8;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002511 Register NewAddrReg;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002512
2513 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2514
2515 MachineMemOperand *NewMMO =
2516 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2517
2518 if (IsLoad) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002519 Register Dst = MRI.createGenericVirtualRegister(PartTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002520 ValRegs.push_back(Dst);
2521 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2522 } else {
2523 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2524 }
2525 }
2526
2527 return Offset;
2528 };
2529
2530 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2531
2532 // Handle the rest of the register if this isn't an even type breakdown.
2533 if (LeftoverTy.isValid())
2534 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2535
2536 if (IsLoad) {
2537 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2538 LeftoverTy, NarrowLeftoverRegs);
2539 }
2540
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002541 MI.eraseFromParent();
2542 return Legalized;
2543}
2544
2545LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002546LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2547 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002548 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002549
2550 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002551 switch (MI.getOpcode()) {
2552 case G_IMPLICIT_DEF:
2553 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2554 case G_AND:
2555 case G_OR:
2556 case G_XOR:
2557 case G_ADD:
2558 case G_SUB:
2559 case G_MUL:
2560 case G_SMULH:
2561 case G_UMULH:
2562 case G_FADD:
2563 case G_FMUL:
2564 case G_FSUB:
2565 case G_FNEG:
2566 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002567 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002568 case G_FDIV:
2569 case G_FREM:
2570 case G_FMA:
2571 case G_FPOW:
2572 case G_FEXP:
2573 case G_FEXP2:
2574 case G_FLOG:
2575 case G_FLOG2:
2576 case G_FLOG10:
Jessica Paquetteba557672019-04-25 16:44:40 +00002577 case G_FNEARBYINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002578 case G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00002579 case G_FFLOOR:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00002580 case G_FRINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002581 case G_INTRINSIC_ROUND:
2582 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002583 case G_FCOS:
2584 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002585 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002586 case G_BSWAP:
Amara Emersonae878da2019-04-10 23:06:08 +00002587 case G_SDIV:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002588 case G_SMIN:
2589 case G_SMAX:
2590 case G_UMIN:
2591 case G_UMAX:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00002592 case G_FMINNUM:
2593 case G_FMAXNUM:
2594 case G_FMINNUM_IEEE:
2595 case G_FMAXNUM_IEEE:
2596 case G_FMINIMUM:
2597 case G_FMAXIMUM:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002598 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002599 case G_SHL:
2600 case G_LSHR:
2601 case G_ASHR:
Matt Arsenault75e30c42019-02-20 16:42:52 +00002602 case G_CTLZ:
2603 case G_CTLZ_ZERO_UNDEF:
2604 case G_CTTZ:
2605 case G_CTTZ_ZERO_UNDEF:
2606 case G_CTPOP:
Matt Arsenault1448f562019-05-17 12:19:52 +00002607 case G_FCOPYSIGN:
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002608 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002609 case G_ZEXT:
2610 case G_SEXT:
2611 case G_ANYEXT:
2612 case G_FPEXT:
2613 case G_FPTRUNC:
2614 case G_SITOFP:
2615 case G_UITOFP:
2616 case G_FPTOSI:
2617 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002618 case G_INTTOPTR:
2619 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002620 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002621 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2622 case G_ICMP:
2623 case G_FCMP:
2624 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002625 case G_SELECT:
2626 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002627 case G_PHI:
2628 return fewerElementsVectorPhi(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002629 case G_LOAD:
2630 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002631 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002632 default:
2633 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002634 }
2635}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002636
2637LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002638LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2639 const LLT HalfTy, const LLT AmtTy) {
2640
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002641 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2642 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002643 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2644
2645 if (Amt.isNullValue()) {
2646 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2647 MI.eraseFromParent();
2648 return Legalized;
2649 }
2650
2651 LLT NVT = HalfTy;
2652 unsigned NVTBits = HalfTy.getSizeInBits();
2653 unsigned VTBits = 2 * NVTBits;
2654
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002655 SrcOp Lo(Register(0)), Hi(Register(0));
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002656 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2657 if (Amt.ugt(VTBits)) {
2658 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2659 } else if (Amt.ugt(NVTBits)) {
2660 Lo = MIRBuilder.buildConstant(NVT, 0);
2661 Hi = MIRBuilder.buildShl(NVT, InL,
2662 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2663 } else if (Amt == NVTBits) {
2664 Lo = MIRBuilder.buildConstant(NVT, 0);
2665 Hi = InL;
2666 } else {
2667 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002668 auto OrLHS =
2669 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2670 auto OrRHS = MIRBuilder.buildLShr(
2671 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2672 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002673 }
2674 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2675 if (Amt.ugt(VTBits)) {
2676 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2677 } else if (Amt.ugt(NVTBits)) {
2678 Lo = MIRBuilder.buildLShr(NVT, InH,
2679 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2680 Hi = MIRBuilder.buildConstant(NVT, 0);
2681 } else if (Amt == NVTBits) {
2682 Lo = InH;
2683 Hi = MIRBuilder.buildConstant(NVT, 0);
2684 } else {
2685 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2686
2687 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2688 auto OrRHS = MIRBuilder.buildShl(
2689 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2690
2691 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2692 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2693 }
2694 } else {
2695 if (Amt.ugt(VTBits)) {
2696 Hi = Lo = MIRBuilder.buildAShr(
2697 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2698 } else if (Amt.ugt(NVTBits)) {
2699 Lo = MIRBuilder.buildAShr(NVT, InH,
2700 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2701 Hi = MIRBuilder.buildAShr(NVT, InH,
2702 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2703 } else if (Amt == NVTBits) {
2704 Lo = InH;
2705 Hi = MIRBuilder.buildAShr(NVT, InH,
2706 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2707 } else {
2708 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2709
2710 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2711 auto OrRHS = MIRBuilder.buildShl(
2712 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2713
2714 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2715 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2716 }
2717 }
2718
2719 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2720 MI.eraseFromParent();
2721
2722 return Legalized;
2723}
2724
2725// TODO: Optimize if constant shift amount.
2726LegalizerHelper::LegalizeResult
2727LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2728 LLT RequestedTy) {
2729 if (TypeIdx == 1) {
2730 Observer.changingInstr(MI);
2731 narrowScalarSrc(MI, RequestedTy, 2);
2732 Observer.changedInstr(MI);
2733 return Legalized;
2734 }
2735
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002736 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002737 LLT DstTy = MRI.getType(DstReg);
2738 if (DstTy.isVector())
2739 return UnableToLegalize;
2740
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002741 Register Amt = MI.getOperand(2).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002742 LLT ShiftAmtTy = MRI.getType(Amt);
2743 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2744 if (DstEltSize % 2 != 0)
2745 return UnableToLegalize;
2746
2747 // Ignore the input type. We can only go to exactly half the size of the
2748 // input. If that isn't small enough, the resulting pieces will be further
2749 // legalized.
2750 const unsigned NewBitSize = DstEltSize / 2;
2751 const LLT HalfTy = LLT::scalar(NewBitSize);
2752 const LLT CondTy = LLT::scalar(1);
2753
2754 if (const MachineInstr *KShiftAmt =
2755 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2756 return narrowScalarShiftByConstant(
2757 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2758 }
2759
2760 // TODO: Expand with known bits.
2761
2762 // Handle the fully general expansion by an unknown amount.
2763 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2764
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002765 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2766 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002767 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2768
2769 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2770 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2771
2772 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2773 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2774 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2775
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002776 Register ResultRegs[2];
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002777 switch (MI.getOpcode()) {
2778 case TargetOpcode::G_SHL: {
2779 // Short: ShAmt < NewBitSize
2780 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2781
2782 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2783 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2784 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2785
2786 // Long: ShAmt >= NewBitSize
2787 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2788 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2789
2790 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2791 auto Hi = MIRBuilder.buildSelect(
2792 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2793
2794 ResultRegs[0] = Lo.getReg(0);
2795 ResultRegs[1] = Hi.getReg(0);
2796 break;
2797 }
2798 case TargetOpcode::G_LSHR: {
2799 // Short: ShAmt < NewBitSize
2800 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2801
2802 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2803 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2804 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2805
2806 // Long: ShAmt >= NewBitSize
2807 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2808 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2809
2810 auto Lo = MIRBuilder.buildSelect(
2811 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2812 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2813
2814 ResultRegs[0] = Lo.getReg(0);
2815 ResultRegs[1] = Hi.getReg(0);
2816 break;
2817 }
2818 case TargetOpcode::G_ASHR: {
2819 // Short: ShAmt < NewBitSize
2820 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2821
2822 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2823 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2824 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2825
2826 // Long: ShAmt >= NewBitSize
2827
2828 // Sign of Hi part.
2829 auto HiL = MIRBuilder.buildAShr(
2830 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2831
2832 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2833
2834 auto Lo = MIRBuilder.buildSelect(
2835 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2836
2837 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2838
2839 ResultRegs[0] = Lo.getReg(0);
2840 ResultRegs[1] = Hi.getReg(0);
2841 break;
2842 }
2843 default:
2844 llvm_unreachable("not a shift");
2845 }
2846
2847 MIRBuilder.buildMerge(DstReg, ResultRegs);
2848 MI.eraseFromParent();
2849 return Legalized;
2850}
2851
2852LegalizerHelper::LegalizeResult
Matt Arsenault72bcf152019-02-28 00:01:05 +00002853LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2854 LLT MoreTy) {
2855 assert(TypeIdx == 0 && "Expecting only Idx 0");
2856
2857 Observer.changingInstr(MI);
2858 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2859 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2860 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2861 moreElementsVectorSrc(MI, MoreTy, I);
2862 }
2863
2864 MachineBasicBlock &MBB = *MI.getParent();
2865 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
2866 moreElementsVectorDst(MI, MoreTy, 0);
2867 Observer.changedInstr(MI);
2868 return Legalized;
2869}
2870
2871LegalizerHelper::LegalizeResult
Matt Arsenault18ec3822019-02-11 22:00:39 +00002872LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
2873 LLT MoreTy) {
2874 MIRBuilder.setInstr(MI);
2875 unsigned Opc = MI.getOpcode();
2876 switch (Opc) {
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002877 case TargetOpcode::G_IMPLICIT_DEF:
2878 case TargetOpcode::G_LOAD: {
2879 if (TypeIdx != 0)
2880 return UnableToLegalize;
Matt Arsenault18ec3822019-02-11 22:00:39 +00002881 Observer.changingInstr(MI);
2882 moreElementsVectorDst(MI, MoreTy, 0);
2883 Observer.changedInstr(MI);
2884 return Legalized;
2885 }
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002886 case TargetOpcode::G_STORE:
2887 if (TypeIdx != 0)
2888 return UnableToLegalize;
2889 Observer.changingInstr(MI);
2890 moreElementsVectorSrc(MI, MoreTy, 0);
2891 Observer.changedInstr(MI);
2892 return Legalized;
Matt Arsenault26b7e852019-02-19 16:30:19 +00002893 case TargetOpcode::G_AND:
2894 case TargetOpcode::G_OR:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002895 case TargetOpcode::G_XOR:
2896 case TargetOpcode::G_SMIN:
2897 case TargetOpcode::G_SMAX:
2898 case TargetOpcode::G_UMIN:
2899 case TargetOpcode::G_UMAX: {
Matt Arsenault26b7e852019-02-19 16:30:19 +00002900 Observer.changingInstr(MI);
2901 moreElementsVectorSrc(MI, MoreTy, 1);
2902 moreElementsVectorSrc(MI, MoreTy, 2);
2903 moreElementsVectorDst(MI, MoreTy, 0);
2904 Observer.changedInstr(MI);
2905 return Legalized;
2906 }
Matt Arsenault4d884272019-02-19 16:44:22 +00002907 case TargetOpcode::G_EXTRACT:
2908 if (TypeIdx != 1)
2909 return UnableToLegalize;
2910 Observer.changingInstr(MI);
2911 moreElementsVectorSrc(MI, MoreTy, 1);
2912 Observer.changedInstr(MI);
2913 return Legalized;
Matt Arsenaultc4d07552019-02-20 16:11:22 +00002914 case TargetOpcode::G_INSERT:
2915 if (TypeIdx != 0)
2916 return UnableToLegalize;
2917 Observer.changingInstr(MI);
2918 moreElementsVectorSrc(MI, MoreTy, 1);
2919 moreElementsVectorDst(MI, MoreTy, 0);
2920 Observer.changedInstr(MI);
2921 return Legalized;
Matt Arsenaultb4c95b32019-02-19 17:03:09 +00002922 case TargetOpcode::G_SELECT:
2923 if (TypeIdx != 0)
2924 return UnableToLegalize;
2925 if (MRI.getType(MI.getOperand(1).getReg()).isVector())
2926 return UnableToLegalize;
2927
2928 Observer.changingInstr(MI);
2929 moreElementsVectorSrc(MI, MoreTy, 2);
2930 moreElementsVectorSrc(MI, MoreTy, 3);
2931 moreElementsVectorDst(MI, MoreTy, 0);
2932 Observer.changedInstr(MI);
2933 return Legalized;
Matt Arsenault72bcf152019-02-28 00:01:05 +00002934 case TargetOpcode::G_PHI:
2935 return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +00002936 default:
2937 return UnableToLegalize;
2938 }
2939}
2940
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002941void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
2942 ArrayRef<Register> Src1Regs,
2943 ArrayRef<Register> Src2Regs,
Petar Avramovic0b17e592019-03-11 10:00:17 +00002944 LLT NarrowTy) {
2945 MachineIRBuilder &B = MIRBuilder;
2946 unsigned SrcParts = Src1Regs.size();
2947 unsigned DstParts = DstRegs.size();
2948
2949 unsigned DstIdx = 0; // Low bits of the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002950 Register FactorSum =
Petar Avramovic0b17e592019-03-11 10:00:17 +00002951 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
2952 DstRegs[DstIdx] = FactorSum;
2953
2954 unsigned CarrySumPrevDstIdx;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002955 SmallVector<Register, 4> Factors;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002956
2957 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
2958 // Collect low parts of muls for DstIdx.
2959 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
2960 i <= std::min(DstIdx, SrcParts - 1); ++i) {
2961 MachineInstrBuilder Mul =
2962 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
2963 Factors.push_back(Mul.getReg(0));
2964 }
2965 // Collect high parts of muls from previous DstIdx.
2966 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
2967 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
2968 MachineInstrBuilder Umulh =
2969 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
2970 Factors.push_back(Umulh.getReg(0));
2971 }
2972 // Add CarrySum from additons calculated for previous DstIdx.
2973 if (DstIdx != 1) {
2974 Factors.push_back(CarrySumPrevDstIdx);
2975 }
2976
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002977 Register CarrySum;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002978 // Add all factors and accumulate all carries into CarrySum.
2979 if (DstIdx != DstParts - 1) {
2980 MachineInstrBuilder Uaddo =
2981 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]);
2982 FactorSum = Uaddo.getReg(0);
2983 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0);
2984 for (unsigned i = 2; i < Factors.size(); ++i) {
2985 MachineInstrBuilder Uaddo =
2986 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]);
2987 FactorSum = Uaddo.getReg(0);
2988 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1));
2989 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
2990 }
2991 } else {
2992 // Since value for the next index is not calculated, neither is CarrySum.
2993 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
2994 for (unsigned i = 2; i < Factors.size(); ++i)
2995 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
2996 }
2997
2998 CarrySumPrevDstIdx = CarrySum;
2999 DstRegs[DstIdx] = FactorSum;
3000 Factors.clear();
3001 }
3002}
3003
Matt Arsenault18ec3822019-02-11 22:00:39 +00003004LegalizerHelper::LegalizeResult
Petar Avramovic0b17e592019-03-11 10:00:17 +00003005LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003006 Register DstReg = MI.getOperand(0).getReg();
3007 Register Src1 = MI.getOperand(1).getReg();
3008 Register Src2 = MI.getOperand(2).getReg();
Petar Avramovic0b17e592019-03-11 10:00:17 +00003009
Matt Arsenault211e89d2019-01-27 00:52:51 +00003010 LLT Ty = MRI.getType(DstReg);
3011 if (Ty.isVector())
3012 return UnableToLegalize;
3013
Petar Avramovic0b17e592019-03-11 10:00:17 +00003014 unsigned SrcSize = MRI.getType(Src1).getSizeInBits();
3015 unsigned DstSize = Ty.getSizeInBits();
3016 unsigned NarrowSize = NarrowTy.getSizeInBits();
3017 if (DstSize % NarrowSize != 0 || SrcSize % NarrowSize != 0)
Matt Arsenault211e89d2019-01-27 00:52:51 +00003018 return UnableToLegalize;
3019
Petar Avramovic0b17e592019-03-11 10:00:17 +00003020 unsigned NumDstParts = DstSize / NarrowSize;
3021 unsigned NumSrcParts = SrcSize / NarrowSize;
Petar Avramovic5229f472019-03-11 10:08:44 +00003022 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH;
3023 unsigned DstTmpParts = NumDstParts * (IsMulHigh ? 2 : 1);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003024
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003025 SmallVector<Register, 2> Src1Parts, Src2Parts, DstTmpRegs;
Petar Avramovic0b17e592019-03-11 10:00:17 +00003026 extractParts(Src1, NarrowTy, NumSrcParts, Src1Parts);
3027 extractParts(Src2, NarrowTy, NumSrcParts, Src2Parts);
Petar Avramovic5229f472019-03-11 10:08:44 +00003028 DstTmpRegs.resize(DstTmpParts);
3029 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003030
Petar Avramovic5229f472019-03-11 10:08:44 +00003031 // Take only high half of registers if this is high mul.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003032 ArrayRef<Register> DstRegs(
Petar Avramovic5229f472019-03-11 10:08:44 +00003033 IsMulHigh ? &DstTmpRegs[DstTmpParts / 2] : &DstTmpRegs[0], NumDstParts);
Petar Avramovic0b17e592019-03-11 10:00:17 +00003034 MIRBuilder.buildMerge(DstReg, DstRegs);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003035 MI.eraseFromParent();
3036 return Legalized;
3037}
3038
Matt Arsenault1cf713662019-02-12 14:54:52 +00003039LegalizerHelper::LegalizeResult
3040LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
3041 LLT NarrowTy) {
3042 if (TypeIdx != 1)
3043 return UnableToLegalize;
3044
3045 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3046
3047 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
3048 // FIXME: add support for when SizeOp1 isn't an exact multiple of
3049 // NarrowSize.
3050 if (SizeOp1 % NarrowSize != 0)
3051 return UnableToLegalize;
3052 int NumParts = SizeOp1 / NarrowSize;
3053
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003054 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf713662019-02-12 14:54:52 +00003055 SmallVector<uint64_t, 2> Indexes;
3056 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3057
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003058 Register OpReg = MI.getOperand(0).getReg();
Matt Arsenault1cf713662019-02-12 14:54:52 +00003059 uint64_t OpStart = MI.getOperand(2).getImm();
3060 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3061 for (int i = 0; i < NumParts; ++i) {
3062 unsigned SrcStart = i * NarrowSize;
3063
3064 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
3065 // No part of the extract uses this subregister, ignore it.
3066 continue;
3067 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3068 // The entire subregister is extracted, forward the value.
3069 DstRegs.push_back(SrcRegs[i]);
3070 continue;
3071 }
3072
3073 // OpSegStart is where this destination segment would start in OpReg if it
3074 // extended infinitely in both directions.
3075 int64_t ExtractOffset;
3076 uint64_t SegSize;
3077 if (OpStart < SrcStart) {
3078 ExtractOffset = 0;
3079 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
3080 } else {
3081 ExtractOffset = OpStart - SrcStart;
3082 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
3083 }
3084
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003085 Register SegReg = SrcRegs[i];
Matt Arsenault1cf713662019-02-12 14:54:52 +00003086 if (ExtractOffset != 0 || SegSize != NarrowSize) {
3087 // A genuine extract is needed.
3088 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3089 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
3090 }
3091
3092 DstRegs.push_back(SegReg);
3093 }
3094
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003095 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf713662019-02-12 14:54:52 +00003096 if(MRI.getType(DstReg).isVector())
3097 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3098 else
3099 MIRBuilder.buildMerge(DstReg, DstRegs);
3100 MI.eraseFromParent();
3101 return Legalized;
3102}
3103
3104LegalizerHelper::LegalizeResult
3105LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
3106 LLT NarrowTy) {
3107 // FIXME: Don't know how to handle secondary types yet.
3108 if (TypeIdx != 0)
3109 return UnableToLegalize;
3110
3111 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
3112 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3113
3114 // FIXME: add support for when SizeOp0 isn't an exact multiple of
3115 // NarrowSize.
3116 if (SizeOp0 % NarrowSize != 0)
3117 return UnableToLegalize;
3118
3119 int NumParts = SizeOp0 / NarrowSize;
3120
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003121 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf713662019-02-12 14:54:52 +00003122 SmallVector<uint64_t, 2> Indexes;
3123 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3124
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003125 Register OpReg = MI.getOperand(2).getReg();
Matt Arsenault1cf713662019-02-12 14:54:52 +00003126 uint64_t OpStart = MI.getOperand(3).getImm();
3127 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3128 for (int i = 0; i < NumParts; ++i) {
3129 unsigned DstStart = i * NarrowSize;
3130
3131 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
3132 // No part of the insert affects this subregister, forward the original.
3133 DstRegs.push_back(SrcRegs[i]);
3134 continue;
3135 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3136 // The entire subregister is defined by this insert, forward the new
3137 // value.
3138 DstRegs.push_back(OpReg);
3139 continue;
3140 }
3141
3142 // OpSegStart is where this destination segment would start in OpReg if it
3143 // extended infinitely in both directions.
3144 int64_t ExtractOffset, InsertOffset;
3145 uint64_t SegSize;
3146 if (OpStart < DstStart) {
3147 InsertOffset = 0;
3148 ExtractOffset = DstStart - OpStart;
3149 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
3150 } else {
3151 InsertOffset = OpStart - DstStart;
3152 ExtractOffset = 0;
3153 SegSize =
3154 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
3155 }
3156
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003157 Register SegReg = OpReg;
Matt Arsenault1cf713662019-02-12 14:54:52 +00003158 if (ExtractOffset != 0 || SegSize != OpSize) {
3159 // A genuine extract is needed.
3160 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3161 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
3162 }
3163
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003164 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault1cf713662019-02-12 14:54:52 +00003165 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
3166 DstRegs.push_back(DstReg);
3167 }
3168
3169 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003170 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf713662019-02-12 14:54:52 +00003171 if(MRI.getType(DstReg).isVector())
3172 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3173 else
3174 MIRBuilder.buildMerge(DstReg, DstRegs);
3175 MI.eraseFromParent();
3176 return Legalized;
3177}
3178
Matt Arsenault211e89d2019-01-27 00:52:51 +00003179LegalizerHelper::LegalizeResult
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003180LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx,
3181 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003182 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003183 LLT DstTy = MRI.getType(DstReg);
3184
3185 assert(MI.getNumOperands() == 3 && TypeIdx == 0);
3186
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003187 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3188 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs;
3189 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003190 LLT LeftoverTy;
3191 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
3192 Src0Regs, Src0LeftoverRegs))
3193 return UnableToLegalize;
3194
3195 LLT Unused;
3196 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
3197 Src1Regs, Src1LeftoverRegs))
3198 llvm_unreachable("inconsistent extractParts result");
3199
3200 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3201 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
3202 {Src0Regs[I], Src1Regs[I]});
3203 DstRegs.push_back(Inst->getOperand(0).getReg());
3204 }
3205
3206 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3207 auto Inst = MIRBuilder.buildInstr(
3208 MI.getOpcode(),
3209 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
3210 DstLeftoverRegs.push_back(Inst->getOperand(0).getReg());
3211 }
3212
3213 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3214 LeftoverTy, DstLeftoverRegs);
3215
3216 MI.eraseFromParent();
3217 return Legalized;
3218}
3219
3220LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00003221LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
3222 LLT NarrowTy) {
3223 if (TypeIdx != 0)
3224 return UnableToLegalize;
3225
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003226 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003227 LLT CondTy = MRI.getType(CondReg);
3228 if (CondTy.isVector()) // TODO: Handle vselect
3229 return UnableToLegalize;
3230
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003231 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003232 LLT DstTy = MRI.getType(DstReg);
3233
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003234 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3235 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
3236 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs;
Matt Arsenault81511e52019-02-05 00:13:44 +00003237 LLT LeftoverTy;
3238 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
3239 Src1Regs, Src1LeftoverRegs))
3240 return UnableToLegalize;
3241
3242 LLT Unused;
3243 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
3244 Src2Regs, Src2LeftoverRegs))
3245 llvm_unreachable("inconsistent extractParts result");
3246
3247 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3248 auto Select = MIRBuilder.buildSelect(NarrowTy,
3249 CondReg, Src1Regs[I], Src2Regs[I]);
3250 DstRegs.push_back(Select->getOperand(0).getReg());
3251 }
3252
3253 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3254 auto Select = MIRBuilder.buildSelect(
3255 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
3256 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
3257 }
3258
3259 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3260 LeftoverTy, DstLeftoverRegs);
3261
3262 MI.eraseFromParent();
3263 return Legalized;
3264}
3265
3266LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003267LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3268 unsigned Opc = MI.getOpcode();
3269 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00003270 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003271 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00003272 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003273 };
3274 switch (Opc) {
3275 default:
3276 return UnableToLegalize;
3277 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
3278 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003279 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003280 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003281 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003282 return Legalized;
3283 }
3284 case TargetOpcode::G_CTLZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003285 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003286 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003287 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00003288 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003289 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
3290 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003291 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3292 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3293 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3294 SrcReg, MIBZero);
3295 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3296 MIBCtlzZU);
3297 MI.eraseFromParent();
3298 return Legalized;
3299 }
3300 // for now, we do this:
3301 // NewLen = NextPowerOf2(Len);
3302 // x = x | (x >> 1);
3303 // x = x | (x >> 2);
3304 // ...
3305 // x = x | (x >>16);
3306 // x = x | (x >>32); // for 64-bit input
3307 // Upto NewLen/2
3308 // return Len - popcount(x);
3309 //
3310 // Ref: "Hacker's Delight" by Henry Warren
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003311 Register Op = SrcReg;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003312 unsigned NewLen = PowerOf2Ceil(Len);
3313 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
3314 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
3315 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003316 TargetOpcode::G_OR, {Ty},
3317 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
3318 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003319 Op = MIBOp->getOperand(0).getReg();
3320 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003321 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
3322 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3323 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003324 MI.eraseFromParent();
3325 return Legalized;
3326 }
3327 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
3328 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003329 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003330 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003331 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003332 return Legalized;
3333 }
3334 case TargetOpcode::G_CTTZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003335 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003336 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003337 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003338 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
3339 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003340 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
3341 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003342 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3343 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3344 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3345 SrcReg, MIBZero);
3346 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3347 MIBCttzZU);
3348 MI.eraseFromParent();
3349 return Legalized;
3350 }
3351 // for now, we use: { return popcount(~x & (x - 1)); }
3352 // unless the target has ctlz but not ctpop, in which case we use:
3353 // { return 32 - nlz(~x & (x-1)); }
3354 // Ref: "Hacker's Delight" by Henry Warren
3355 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
3356 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003357 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003358 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003359 TargetOpcode::G_AND, {Ty},
3360 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
3361 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003362 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
3363 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003364 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
3365 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003366 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3367 {MIBCstLen,
3368 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003369 MI.eraseFromParent();
3370 return Legalized;
3371 }
3372 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
3373 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
3374 return Legalized;
3375 }
3376 }
3377}
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003378
3379// Expand s32 = G_UITOFP s64 using bit operations to an IEEE float
3380// representation.
3381LegalizerHelper::LegalizeResult
3382LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003383 Register Dst = MI.getOperand(0).getReg();
3384 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003385 const LLT S64 = LLT::scalar(64);
3386 const LLT S32 = LLT::scalar(32);
3387 const LLT S1 = LLT::scalar(1);
3388
3389 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);
3390
3391 // unsigned cul2f(ulong u) {
3392 // uint lz = clz(u);
3393 // uint e = (u != 0) ? 127U + 63U - lz : 0;
3394 // u = (u << lz) & 0x7fffffffffffffffUL;
3395 // ulong t = u & 0xffffffffffUL;
3396 // uint v = (e << 23) | (uint)(u >> 40);
3397 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
3398 // return as_float(v + r);
3399 // }
3400
3401 auto Zero32 = MIRBuilder.buildConstant(S32, 0);
3402 auto Zero64 = MIRBuilder.buildConstant(S64, 0);
3403
3404 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src);
3405
3406 auto K = MIRBuilder.buildConstant(S32, 127U + 63U);
3407 auto Sub = MIRBuilder.buildSub(S32, K, LZ);
3408
3409 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64);
3410 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32);
3411
3412 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1);
3413 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ);
3414
3415 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0);
3416
3417 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL);
3418 auto T = MIRBuilder.buildAnd(S64, U, Mask1);
3419
3420 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40));
3421 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23));
3422 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl));
3423
3424 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL);
3425 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C);
3426 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C);
3427 auto One = MIRBuilder.buildConstant(S32, 1);
3428
3429 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One);
3430 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32);
3431 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0);
3432 MIRBuilder.buildAdd(Dst, V, R);
3433
3434 return Legalized;
3435}
3436
3437LegalizerHelper::LegalizeResult
3438LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003439 Register Dst = MI.getOperand(0).getReg();
3440 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003441 LLT DstTy = MRI.getType(Dst);
3442 LLT SrcTy = MRI.getType(Src);
3443
3444 if (SrcTy != LLT::scalar(64))
3445 return UnableToLegalize;
3446
3447 if (DstTy == LLT::scalar(32)) {
3448 // TODO: SelectionDAG has several alternative expansions to port which may
3449 // be more reasonble depending on the available instructions. If a target
3450 // has sitofp, does not have CTLZ, or can efficiently use f64 as an
3451 // intermediate type, this is probably worse.
3452 return lowerU64ToF32BitOps(MI);
3453 }
3454
3455 return UnableToLegalize;
3456}
3457
3458LegalizerHelper::LegalizeResult
3459LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003460 Register Dst = MI.getOperand(0).getReg();
3461 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003462 LLT DstTy = MRI.getType(Dst);
3463 LLT SrcTy = MRI.getType(Src);
3464
3465 const LLT S64 = LLT::scalar(64);
3466 const LLT S32 = LLT::scalar(32);
3467 const LLT S1 = LLT::scalar(1);
3468
3469 if (SrcTy != S64)
3470 return UnableToLegalize;
3471
3472 if (DstTy == S32) {
3473 // signed cl2f(long l) {
3474 // long s = l >> 63;
3475 // float r = cul2f((l + s) ^ s);
3476 // return s ? -r : r;
3477 // }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003478 Register L = Src;
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003479 auto SignBit = MIRBuilder.buildConstant(S64, 63);
3480 auto S = MIRBuilder.buildAShr(S64, L, SignBit);
3481
3482 auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
3483 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
3484 auto R = MIRBuilder.buildUITOFP(S32, Xor);
3485
3486 auto RNeg = MIRBuilder.buildFNeg(S32, R);
3487 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
3488 MIRBuilder.buildConstant(S64, 0));
3489 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
3490 return Legalized;
3491 }
3492
3493 return UnableToLegalize;
3494}
Matt Arsenault6f74f552019-07-01 17:18:03 +00003495
3496static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
3497 switch (Opc) {
3498 case TargetOpcode::G_SMIN:
3499 return CmpInst::ICMP_SLT;
3500 case TargetOpcode::G_SMAX:
3501 return CmpInst::ICMP_SGT;
3502 case TargetOpcode::G_UMIN:
3503 return CmpInst::ICMP_ULT;
3504 case TargetOpcode::G_UMAX:
3505 return CmpInst::ICMP_UGT;
3506 default:
3507 llvm_unreachable("not in integer min/max");
3508 }
3509}
3510
3511LegalizerHelper::LegalizeResult
3512LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3513 Register Dst = MI.getOperand(0).getReg();
3514 Register Src0 = MI.getOperand(1).getReg();
3515 Register Src1 = MI.getOperand(2).getReg();
3516
3517 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
3518 LLT CmpType = MRI.getType(Dst).changeElementSize(1);
3519
3520 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
3521 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
3522
3523 MI.eraseFromParent();
3524 return Legalized;
3525}
Matt Arsenaultb1843e12019-07-09 23:34:29 +00003526
3527LegalizerHelper::LegalizeResult
3528LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3529 Register Dst = MI.getOperand(0).getReg();
3530 Register Src0 = MI.getOperand(1).getReg();
3531 Register Src1 = MI.getOperand(2).getReg();
3532
3533 const LLT Src0Ty = MRI.getType(Src0);
3534 const LLT Src1Ty = MRI.getType(Src1);
3535
3536 const int Src0Size = Src0Ty.getScalarSizeInBits();
3537 const int Src1Size = Src1Ty.getScalarSizeInBits();
3538
3539 auto SignBitMask = MIRBuilder.buildConstant(
3540 Src0Ty, APInt::getSignMask(Src0Size));
3541
3542 auto NotSignBitMask = MIRBuilder.buildConstant(
3543 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
3544
3545 auto And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask);
3546 MachineInstr *Or;
3547
3548 if (Src0Ty == Src1Ty) {
3549 auto And1 = MIRBuilder.buildAnd(Src1Ty, Src0, SignBitMask);
3550 Or = MIRBuilder.buildOr(Dst, And0, And1);
3551 } else if (Src0Size > Src1Size) {
3552 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
3553 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
3554 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
3555 auto And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask);
3556 Or = MIRBuilder.buildOr(Dst, And0, And1);
3557 } else {
3558 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
3559 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
3560 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
3561 auto And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask);
3562 Or = MIRBuilder.buildOr(Dst, And0, And1);
3563 }
3564
3565 // Be careful about setting nsz/nnan/ninf on every instruction, since the
3566 // constants are a nan and -0.0, but the final result should preserve
3567 // everything.
3568 if (unsigned Flags = MI.getFlags())
3569 Or->setFlags(Flags);
3570
3571 MI.eraseFromParent();
3572 return Legalized;
3573}
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00003574
3575LegalizerHelper::LegalizeResult
3576LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
3577 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ?
3578 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE;
3579
3580 Register Dst = MI.getOperand(0).getReg();
3581 Register Src0 = MI.getOperand(1).getReg();
3582 Register Src1 = MI.getOperand(2).getReg();
3583 LLT Ty = MRI.getType(Dst);
3584
3585 if (!MI.getFlag(MachineInstr::FmNoNans)) {
3586 // Insert canonicalizes if it's possible we need to quiet to get correct
3587 // sNaN behavior.
3588
3589 // Note this must be done here, and not as an optimization combine in the
3590 // absence of a dedicate quiet-snan instruction as we're using an
3591 // omni-purpose G_FCANONICALIZE.
3592 if (!isKnownNeverSNaN(Src0, MRI))
3593 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);
3594
3595 if (!isKnownNeverSNaN(Src1, MRI))
3596 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
3597 }
3598
3599 // If there are no nans, it's safe to simply replace this with the non-IEEE
3600 // version.
3601 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags());
3602 MI.eraseFromParent();
3603 return Legalized;
3604}
Matt Arsenaultd9d30a42019-08-01 19:10:05 +00003605
3606LegalizerHelper::LegalizeResult
3607LegalizerHelper::lowerUnmergeValues(MachineInstr &MI) {
3608 const unsigned NumDst = MI.getNumOperands() - 1;
3609 const Register SrcReg = MI.getOperand(NumDst).getReg();
3610 LLT SrcTy = MRI.getType(SrcReg);
3611
3612 Register Dst0Reg = MI.getOperand(0).getReg();
3613 LLT DstTy = MRI.getType(Dst0Reg);
3614
3615
3616 // Expand scalarizing unmerge as bitcast to integer and shift.
3617 if (!DstTy.isVector() && SrcTy.isVector() &&
3618 SrcTy.getElementType() == DstTy) {
3619 LLT IntTy = LLT::scalar(SrcTy.getSizeInBits());
3620 Register Cast = MIRBuilder.buildBitcast(IntTy, SrcReg).getReg(0);
3621
3622 MIRBuilder.buildTrunc(Dst0Reg, Cast);
3623
3624 const unsigned DstSize = DstTy.getSizeInBits();
3625 unsigned Offset = DstSize;
3626 for (unsigned I = 1; I != NumDst; ++I, Offset += DstSize) {
3627 auto ShiftAmt = MIRBuilder.buildConstant(IntTy, Offset);
3628 auto Shift = MIRBuilder.buildLShr(IntTy, Cast, ShiftAmt);
3629 MIRBuilder.buildTrunc(MI.getOperand(I), Shift);
3630 }
3631
3632 MI.eraseFromParent();
3633 return Legalized;
3634 }
3635
3636 return UnableToLegalize;
3637}