blob: 73d461f69053495d6888092345a3f3e6f42e81c6 [file] [log] [blame]
Tim Northover69fa84a2016-10-14 22:18:18 +00001//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
Tim Northover33b07d62016-07-22 20:03:43 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tim Northover33b07d62016-07-22 20:03:43 +00006//
7//===----------------------------------------------------------------------===//
8//
Tim Northover69fa84a2016-10-14 22:18:18 +00009/// \file This file implements the LegalizerHelper class to legalize
Tim Northover33b07d62016-07-22 20:03:43 +000010/// individual instructions and the LegalizeMachineIR wrapper pass for the
11/// primary legalization.
12//
13//===----------------------------------------------------------------------===//
14
Tim Northover69fa84a2016-10-14 22:18:18 +000015#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Tim Northoveredb3c8c2016-08-29 19:07:16 +000016#include "llvm/CodeGen/GlobalISel/CallLowering.h"
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000017#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
Tim Northover69fa84a2016-10-14 22:18:18 +000018#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000020#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000021#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/CodeGen/TargetSubtargetInfo.h"
Tim Northover33b07d62016-07-22 20:03:43 +000023#include "llvm/Support/Debug.h"
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000024#include "llvm/Support/MathExtras.h"
Tim Northover33b07d62016-07-22 20:03:43 +000025#include "llvm/Support/raw_ostream.h"
Tim Northover33b07d62016-07-22 20:03:43 +000026
Daniel Sanders5377fb32017-04-20 15:46:12 +000027#define DEBUG_TYPE "legalizer"
Tim Northover33b07d62016-07-22 20:03:43 +000028
29using namespace llvm;
Daniel Sanders9ade5592018-01-29 17:37:29 +000030using namespace LegalizeActions;
Tim Northover33b07d62016-07-22 20:03:43 +000031
Matt Arsenaultc83b8232019-02-07 17:38:00 +000032/// Try to break down \p OrigTy into \p NarrowTy sized pieces.
33///
34/// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy,
35/// with any leftover piece as type \p LeftoverTy
36///
Matt Arsenaultd3093c22019-02-28 00:16:32 +000037/// Returns -1 in the first element of the pair if the breakdown is not
38/// satisfiable.
39static std::pair<int, int>
40getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) {
Matt Arsenaultc83b8232019-02-07 17:38:00 +000041 assert(!LeftoverTy.isValid() && "this is an out argument");
42
43 unsigned Size = OrigTy.getSizeInBits();
44 unsigned NarrowSize = NarrowTy.getSizeInBits();
45 unsigned NumParts = Size / NarrowSize;
46 unsigned LeftoverSize = Size - NumParts * NarrowSize;
47 assert(Size > NarrowSize);
48
49 if (LeftoverSize == 0)
Matt Arsenaultd3093c22019-02-28 00:16:32 +000050 return {NumParts, 0};
Matt Arsenaultc83b8232019-02-07 17:38:00 +000051
52 if (NarrowTy.isVector()) {
53 unsigned EltSize = OrigTy.getScalarSizeInBits();
54 if (LeftoverSize % EltSize != 0)
Matt Arsenaultd3093c22019-02-28 00:16:32 +000055 return {-1, -1};
Matt Arsenaultc83b8232019-02-07 17:38:00 +000056 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
57 } else {
58 LeftoverTy = LLT::scalar(LeftoverSize);
59 }
60
Matt Arsenaultd3093c22019-02-28 00:16:32 +000061 int NumLeftover = LeftoverSize / LeftoverTy.getSizeInBits();
62 return std::make_pair(NumParts, NumLeftover);
Matt Arsenaultc83b8232019-02-07 17:38:00 +000063}
64
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000065LegalizerHelper::LegalizerHelper(MachineFunction &MF,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000066 GISelChangeObserver &Observer,
67 MachineIRBuilder &Builder)
68 : MIRBuilder(Builder), MRI(MF.getRegInfo()),
69 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) {
Tim Northover33b07d62016-07-22 20:03:43 +000070 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000071 MIRBuilder.setChangeObserver(Observer);
Tim Northover33b07d62016-07-22 20:03:43 +000072}
73
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000074LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
Aditya Nandakumar500e3ea2019-01-16 00:40:37 +000075 GISelChangeObserver &Observer,
76 MachineIRBuilder &B)
77 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000078 MIRBuilder.setMF(MF);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +000079 MIRBuilder.setChangeObserver(Observer);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +000080}
Tim Northover69fa84a2016-10-14 22:18:18 +000081LegalizerHelper::LegalizeResult
Volkan Keles685fbda2017-03-10 18:34:57 +000082LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000083 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
Daniel Sanders5377fb32017-04-20 15:46:12 +000084
Aditya Nandakumar1023a2e2019-07-01 17:53:50 +000085 if (MI.getOpcode() == TargetOpcode::G_INTRINSIC ||
86 MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS)
87 return LI.legalizeIntrinsic(MI, MRI, MIRBuilder) ? Legalized
88 : UnableToLegalize;
Daniel Sanders262ed0e2018-01-24 17:17:46 +000089 auto Step = LI.getAction(MI, MRI);
90 switch (Step.Action) {
Daniel Sanders9ade5592018-01-29 17:37:29 +000091 case Legal:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000092 LLVM_DEBUG(dbgs() << ".. Already legal\n");
Tim Northover33b07d62016-07-22 20:03:43 +000093 return AlreadyLegal;
Daniel Sanders9ade5592018-01-29 17:37:29 +000094 case Libcall:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000095 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
Tim Northoveredb3c8c2016-08-29 19:07:16 +000096 return libcall(MI);
Daniel Sanders9ade5592018-01-29 17:37:29 +000097 case NarrowScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +000098 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +000099 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000100 case WidenScalar:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000101 LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000102 return widenScalar(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000103 case Lower:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000104 LLVM_DEBUG(dbgs() << ".. Lower\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000105 return lower(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000106 case FewerElements:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000107 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
Daniel Sanders262ed0e2018-01-24 17:17:46 +0000108 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000109 case MoreElements:
110 LLVM_DEBUG(dbgs() << ".. Increase number of elements\n");
111 return moreElementsVector(MI, Step.TypeIdx, Step.NewType);
Daniel Sanders9ade5592018-01-29 17:37:29 +0000112 case Custom:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000113 LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000114 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized
115 : UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +0000116 default:
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000117 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
Tim Northover33b07d62016-07-22 20:03:43 +0000118 return UnableToLegalize;
119 }
120}
121
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000122void LegalizerHelper::extractParts(Register Reg, LLT Ty, int NumParts,
123 SmallVectorImpl<Register> &VRegs) {
Tim Northoverbf017292017-03-03 22:46:09 +0000124 for (int i = 0; i < NumParts; ++i)
Tim Northover0f140c72016-09-09 11:46:34 +0000125 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
Tim Northoverbf017292017-03-03 22:46:09 +0000126 MIRBuilder.buildUnmerge(VRegs, Reg);
Tim Northover33b07d62016-07-22 20:03:43 +0000127}
128
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000129bool LegalizerHelper::extractParts(Register Reg, LLT RegTy,
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000130 LLT MainTy, LLT &LeftoverTy,
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000131 SmallVectorImpl<Register> &VRegs,
132 SmallVectorImpl<Register> &LeftoverRegs) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000133 assert(!LeftoverTy.isValid() && "this is an out argument");
134
135 unsigned RegSize = RegTy.getSizeInBits();
136 unsigned MainSize = MainTy.getSizeInBits();
137 unsigned NumParts = RegSize / MainSize;
138 unsigned LeftoverSize = RegSize - NumParts * MainSize;
139
140 // Use an unmerge when possible.
141 if (LeftoverSize == 0) {
142 for (unsigned I = 0; I < NumParts; ++I)
143 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy));
144 MIRBuilder.buildUnmerge(VRegs, Reg);
145 return true;
146 }
147
148 if (MainTy.isVector()) {
149 unsigned EltSize = MainTy.getScalarSizeInBits();
150 if (LeftoverSize % EltSize != 0)
151 return false;
152 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize);
153 } else {
154 LeftoverTy = LLT::scalar(LeftoverSize);
155 }
156
157 // For irregular sizes, extract the individual parts.
158 for (unsigned I = 0; I != NumParts; ++I) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000159 Register NewReg = MRI.createGenericVirtualRegister(MainTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000160 VRegs.push_back(NewReg);
161 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I);
162 }
163
164 for (unsigned Offset = MainSize * NumParts; Offset < RegSize;
165 Offset += LeftoverSize) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000166 Register NewReg = MRI.createGenericVirtualRegister(LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000167 LeftoverRegs.push_back(NewReg);
168 MIRBuilder.buildExtract(NewReg, Reg, Offset);
169 }
170
171 return true;
172}
173
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000174void LegalizerHelper::insertParts(Register DstReg,
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000175 LLT ResultTy, LLT PartTy,
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000176 ArrayRef<Register> PartRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000177 LLT LeftoverTy,
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000178 ArrayRef<Register> LeftoverRegs) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000179 if (!LeftoverTy.isValid()) {
180 assert(LeftoverRegs.empty());
181
Matt Arsenault81511e52019-02-05 00:13:44 +0000182 if (!ResultTy.isVector()) {
183 MIRBuilder.buildMerge(DstReg, PartRegs);
184 return;
185 }
186
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000187 if (PartTy.isVector())
188 MIRBuilder.buildConcatVectors(DstReg, PartRegs);
189 else
190 MIRBuilder.buildBuildVector(DstReg, PartRegs);
191 return;
192 }
193
194 unsigned PartSize = PartTy.getSizeInBits();
195 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits();
196
Matt Arsenault3018d182019-06-28 01:47:44 +0000197 Register CurResultReg = MRI.createGenericVirtualRegister(ResultTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000198 MIRBuilder.buildUndef(CurResultReg);
199
200 unsigned Offset = 0;
Matt Arsenault3018d182019-06-28 01:47:44 +0000201 for (Register PartReg : PartRegs) {
202 Register NewResultReg = MRI.createGenericVirtualRegister(ResultTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000203 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset);
204 CurResultReg = NewResultReg;
205 Offset += PartSize;
206 }
207
208 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) {
209 // Use the original output register for the final insert to avoid a copy.
Matt Arsenault3018d182019-06-28 01:47:44 +0000210 Register NewResultReg = (I + 1 == E) ?
Matt Arsenaultc7bce732019-01-31 02:46:05 +0000211 DstReg : MRI.createGenericVirtualRegister(ResultTy);
212
213 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset);
214 CurResultReg = NewResultReg;
215 Offset += LeftoverPartSize;
216 }
217}
218
Tim Northovere0418412017-02-08 23:23:39 +0000219static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
220 switch (Opcode) {
Diana Picuse97822e2017-04-24 07:22:31 +0000221 case TargetOpcode::G_SDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000222 assert((Size == 32 || Size == 64) && "Unsupported size");
223 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32;
Diana Picuse97822e2017-04-24 07:22:31 +0000224 case TargetOpcode::G_UDIV:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000225 assert((Size == 32 || Size == 64) && "Unsupported size");
226 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000227 case TargetOpcode::G_SREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000228 assert((Size == 32 || Size == 64) && "Unsupported size");
229 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32;
Diana Picus02e11012017-06-15 10:53:31 +0000230 case TargetOpcode::G_UREM:
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000231 assert((Size == 32 || Size == 64) && "Unsupported size");
232 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32;
Diana Picus0528e2c2018-11-26 11:07:02 +0000233 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
234 assert(Size == 32 && "Unsupported size");
235 return RTLIB::CTLZ_I32;
Diana Picus1314a282017-04-11 10:52:34 +0000236 case TargetOpcode::G_FADD:
237 assert((Size == 32 || Size == 64) && "Unsupported size");
238 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
Javed Absar5cde1cc2017-10-30 13:51:56 +0000239 case TargetOpcode::G_FSUB:
240 assert((Size == 32 || Size == 64) && "Unsupported size");
241 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
Diana Picus9faa09b2017-11-23 12:44:20 +0000242 case TargetOpcode::G_FMUL:
243 assert((Size == 32 || Size == 64) && "Unsupported size");
244 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
Diana Picusc01f7f12017-11-23 13:26:07 +0000245 case TargetOpcode::G_FDIV:
246 assert((Size == 32 || Size == 64) && "Unsupported size");
247 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
Jessica Paquette84bedac2019-01-30 23:46:15 +0000248 case TargetOpcode::G_FEXP:
249 assert((Size == 32 || Size == 64) && "Unsupported size");
250 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32;
Jessica Paquettee7941212019-04-03 16:58:32 +0000251 case TargetOpcode::G_FEXP2:
252 assert((Size == 32 || Size == 64) && "Unsupported size");
253 return Size == 64 ? RTLIB::EXP2_F64 : RTLIB::EXP2_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000254 case TargetOpcode::G_FREM:
255 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
256 case TargetOpcode::G_FPOW:
257 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
Diana Picuse74243d2018-01-12 11:30:45 +0000258 case TargetOpcode::G_FMA:
259 assert((Size == 32 || Size == 64) && "Unsupported size");
260 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
Jessica Paquette7db82d72019-01-28 18:34:18 +0000261 case TargetOpcode::G_FSIN:
262 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
263 return Size == 128 ? RTLIB::SIN_F128
264 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32;
265 case TargetOpcode::G_FCOS:
266 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
267 return Size == 128 ? RTLIB::COS_F128
268 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32;
Jessica Paquettec49428a2019-01-28 19:53:14 +0000269 case TargetOpcode::G_FLOG10:
270 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
271 return Size == 128 ? RTLIB::LOG10_F128
272 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32;
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000273 case TargetOpcode::G_FLOG:
274 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
275 return Size == 128 ? RTLIB::LOG_F128
276 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32;
Jessica Paquette0154bd12019-01-30 21:16:04 +0000277 case TargetOpcode::G_FLOG2:
278 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size");
279 return Size == 128 ? RTLIB::LOG2_F128
280 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32;
Petar Avramovicfaaa2b52019-06-06 09:02:24 +0000281 case TargetOpcode::G_FCEIL:
282 assert((Size == 32 || Size == 64) && "Unsupported size");
283 return Size == 64 ? RTLIB::CEIL_F64 : RTLIB::CEIL_F32;
284 case TargetOpcode::G_FFLOOR:
285 assert((Size == 32 || Size == 64) && "Unsupported size");
286 return Size == 64 ? RTLIB::FLOOR_F64 : RTLIB::FLOOR_F32;
Tim Northovere0418412017-02-08 23:23:39 +0000287 }
288 llvm_unreachable("Unknown libcall function");
289}
290
Diana Picusfc1675e2017-07-05 12:57:24 +0000291LegalizerHelper::LegalizeResult
292llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
293 const CallLowering::ArgInfo &Result,
294 ArrayRef<CallLowering::ArgInfo> Args) {
Diana Picuse97822e2017-04-24 07:22:31 +0000295 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
296 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
Diana Picuse97822e2017-04-24 07:22:31 +0000297 const char *Name = TLI.getLibcallName(Libcall);
Diana Picusd0104ea2017-07-06 09:09:33 +0000298
Diana Picuse97822e2017-04-24 07:22:31 +0000299 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
Diana Picus02e11012017-06-15 10:53:31 +0000300 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
301 MachineOperand::CreateES(Name), Result, Args))
302 return LegalizerHelper::UnableToLegalize;
Diana Picusd0104ea2017-07-06 09:09:33 +0000303
Diana Picuse97822e2017-04-24 07:22:31 +0000304 return LegalizerHelper::Legalized;
305}
306
Diana Picus65ed3642018-01-17 13:34:10 +0000307// Useful for libcalls where all operands have the same type.
Diana Picus02e11012017-06-15 10:53:31 +0000308static LegalizerHelper::LegalizeResult
309simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
310 Type *OpType) {
311 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
Diana Picuse74243d2018-01-12 11:30:45 +0000312
313 SmallVector<CallLowering::ArgInfo, 3> Args;
314 for (unsigned i = 1; i < MI.getNumOperands(); i++)
315 Args.push_back({MI.getOperand(i).getReg(), OpType});
Diana Picusfc1675e2017-07-05 12:57:24 +0000316 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
Diana Picuse74243d2018-01-12 11:30:45 +0000317 Args);
Diana Picus02e11012017-06-15 10:53:31 +0000318}
319
Amara Emersoncf12c782019-07-19 00:24:45 +0000320LegalizerHelper::LegalizeResult
321llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
322 MachineInstr &MI) {
323 assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
324 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
325
326 SmallVector<CallLowering::ArgInfo, 3> Args;
327 for (unsigned i = 1; i < MI.getNumOperands(); i++) {
328 Register Reg = MI.getOperand(i).getReg();
329
330 // Need derive an IR type for call lowering.
331 LLT OpLLT = MRI.getType(Reg);
332 Type *OpTy = nullptr;
333 if (OpLLT.isPointer())
334 OpTy = Type::getInt8PtrTy(Ctx, OpLLT.getAddressSpace());
335 else
336 OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits());
337 Args.push_back({Reg, OpTy});
338 }
339
340 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
341 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
342 Intrinsic::ID ID = MI.getOperand(0).getIntrinsicID();
343 RTLIB::Libcall RTLibcall;
344 switch (ID) {
345 case Intrinsic::memcpy:
346 RTLibcall = RTLIB::MEMCPY;
347 break;
348 case Intrinsic::memset:
349 RTLibcall = RTLIB::MEMSET;
350 break;
351 case Intrinsic::memmove:
352 RTLibcall = RTLIB::MEMMOVE;
353 break;
354 default:
355 return LegalizerHelper::UnableToLegalize;
356 }
357 const char *Name = TLI.getLibcallName(RTLibcall);
358
359 MIRBuilder.setInstr(MI);
360 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
361 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(RTLibcall),
362 MachineOperand::CreateES(Name),
363 CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx)), Args))
364 return LegalizerHelper::UnableToLegalize;
365
366 return LegalizerHelper::Legalized;
367}
368
Diana Picus65ed3642018-01-17 13:34:10 +0000369static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
370 Type *FromType) {
371 auto ToMVT = MVT::getVT(ToType);
372 auto FromMVT = MVT::getVT(FromType);
373
374 switch (Opcode) {
375 case TargetOpcode::G_FPEXT:
376 return RTLIB::getFPEXT(FromMVT, ToMVT);
377 case TargetOpcode::G_FPTRUNC:
378 return RTLIB::getFPROUND(FromMVT, ToMVT);
Diana Picus4ed0ee72018-01-30 07:54:52 +0000379 case TargetOpcode::G_FPTOSI:
380 return RTLIB::getFPTOSINT(FromMVT, ToMVT);
381 case TargetOpcode::G_FPTOUI:
382 return RTLIB::getFPTOUINT(FromMVT, ToMVT);
Diana Picus517531e2018-01-30 09:15:17 +0000383 case TargetOpcode::G_SITOFP:
384 return RTLIB::getSINTTOFP(FromMVT, ToMVT);
385 case TargetOpcode::G_UITOFP:
386 return RTLIB::getUINTTOFP(FromMVT, ToMVT);
Diana Picus65ed3642018-01-17 13:34:10 +0000387 }
388 llvm_unreachable("Unsupported libcall function");
389}
390
391static LegalizerHelper::LegalizeResult
392conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
393 Type *FromType) {
394 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
395 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
396 {{MI.getOperand(1).getReg(), FromType}});
397}
398
Tim Northover69fa84a2016-10-14 22:18:18 +0000399LegalizerHelper::LegalizeResult
400LegalizerHelper::libcall(MachineInstr &MI) {
Diana Picus02e11012017-06-15 10:53:31 +0000401 LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
402 unsigned Size = LLTy.getSizeInBits();
Matthias Braunf1caa282017-12-15 22:22:58 +0000403 auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000404
Diana Picusfc1675e2017-07-05 12:57:24 +0000405 MIRBuilder.setInstr(MI);
406
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000407 switch (MI.getOpcode()) {
408 default:
409 return UnableToLegalize;
Diana Picuse97822e2017-04-24 07:22:31 +0000410 case TargetOpcode::G_SDIV:
Diana Picus02e11012017-06-15 10:53:31 +0000411 case TargetOpcode::G_UDIV:
412 case TargetOpcode::G_SREM:
Diana Picus0528e2c2018-11-26 11:07:02 +0000413 case TargetOpcode::G_UREM:
414 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000415 Type *HLTy = IntegerType::get(Ctx, Size);
Diana Picusfc1675e2017-07-05 12:57:24 +0000416 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
417 if (Status != Legalized)
418 return Status;
419 break;
Diana Picuse97822e2017-04-24 07:22:31 +0000420 }
Diana Picus1314a282017-04-11 10:52:34 +0000421 case TargetOpcode::G_FADD:
Javed Absar5cde1cc2017-10-30 13:51:56 +0000422 case TargetOpcode::G_FSUB:
Diana Picus9faa09b2017-11-23 12:44:20 +0000423 case TargetOpcode::G_FMUL:
Diana Picusc01f7f12017-11-23 13:26:07 +0000424 case TargetOpcode::G_FDIV:
Diana Picuse74243d2018-01-12 11:30:45 +0000425 case TargetOpcode::G_FMA:
Tim Northovere0418412017-02-08 23:23:39 +0000426 case TargetOpcode::G_FPOW:
Jessica Paquette7db82d72019-01-28 18:34:18 +0000427 case TargetOpcode::G_FREM:
428 case TargetOpcode::G_FCOS:
Jessica Paquettec49428a2019-01-28 19:53:14 +0000429 case TargetOpcode::G_FSIN:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +0000430 case TargetOpcode::G_FLOG10:
Jessica Paquette0154bd12019-01-30 21:16:04 +0000431 case TargetOpcode::G_FLOG:
Jessica Paquette84bedac2019-01-30 23:46:15 +0000432 case TargetOpcode::G_FLOG2:
Jessica Paquettee7941212019-04-03 16:58:32 +0000433 case TargetOpcode::G_FEXP:
Petar Avramovicfaaa2b52019-06-06 09:02:24 +0000434 case TargetOpcode::G_FEXP2:
435 case TargetOpcode::G_FCEIL:
436 case TargetOpcode::G_FFLOOR: {
Jessica Paquette7db82d72019-01-28 18:34:18 +0000437 if (Size > 64) {
438 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n");
439 return UnableToLegalize;
440 }
Diana Picus02e11012017-06-15 10:53:31 +0000441 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
Diana Picusfc1675e2017-07-05 12:57:24 +0000442 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
443 if (Status != Legalized)
444 return Status;
445 break;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000446 }
Diana Picus65ed3642018-01-17 13:34:10 +0000447 case TargetOpcode::G_FPEXT: {
448 // FIXME: Support other floating point types (half, fp128 etc)
449 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
450 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
451 if (ToSize != 64 || FromSize != 32)
452 return UnableToLegalize;
453 LegalizeResult Status = conversionLibcall(
454 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
455 if (Status != Legalized)
456 return Status;
457 break;
458 }
459 case TargetOpcode::G_FPTRUNC: {
460 // FIXME: Support other floating point types (half, fp128 etc)
461 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
462 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
463 if (ToSize != 32 || FromSize != 64)
464 return UnableToLegalize;
465 LegalizeResult Status = conversionLibcall(
466 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
467 if (Status != Legalized)
468 return Status;
469 break;
470 }
Diana Picus4ed0ee72018-01-30 07:54:52 +0000471 case TargetOpcode::G_FPTOSI:
472 case TargetOpcode::G_FPTOUI: {
473 // FIXME: Support other types
474 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
475 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000476 if ((ToSize != 32 && ToSize != 64) || (FromSize != 32 && FromSize != 64))
Diana Picus4ed0ee72018-01-30 07:54:52 +0000477 return UnableToLegalize;
478 LegalizeResult Status = conversionLibcall(
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000479 MI, MIRBuilder,
480 ToSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx),
Diana Picus4ed0ee72018-01-30 07:54:52 +0000481 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
482 if (Status != Legalized)
483 return Status;
484 break;
485 }
Diana Picus517531e2018-01-30 09:15:17 +0000486 case TargetOpcode::G_SITOFP:
487 case TargetOpcode::G_UITOFP: {
488 // FIXME: Support other types
489 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
490 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
Petar Avramovic153bd242019-06-20 09:05:02 +0000491 if ((FromSize != 32 && FromSize != 64) || (ToSize != 32 && ToSize != 64))
Diana Picus517531e2018-01-30 09:15:17 +0000492 return UnableToLegalize;
493 LegalizeResult Status = conversionLibcall(
494 MI, MIRBuilder,
495 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
Petar Avramovic153bd242019-06-20 09:05:02 +0000496 FromSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx));
Diana Picus517531e2018-01-30 09:15:17 +0000497 if (Status != Legalized)
498 return Status;
499 break;
500 }
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000501 }
Diana Picusfc1675e2017-07-05 12:57:24 +0000502
503 MI.eraseFromParent();
504 return Legalized;
Tim Northoveredb3c8c2016-08-29 19:07:16 +0000505}
506
Tim Northover69fa84a2016-10-14 22:18:18 +0000507LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
508 unsigned TypeIdx,
509 LLT NarrowTy) {
Justin Bognerfde01042017-01-18 17:29:54 +0000510 MIRBuilder.setInstr(MI);
511
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000512 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
513 uint64_t NarrowSize = NarrowTy.getSizeInBits();
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000514
Tim Northover9656f142016-08-04 20:54:13 +0000515 switch (MI.getOpcode()) {
516 default:
517 return UnableToLegalize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000518 case TargetOpcode::G_IMPLICIT_DEF: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000519 // FIXME: add support for when SizeOp0 isn't an exact multiple of
520 // NarrowSize.
521 if (SizeOp0 % NarrowSize != 0)
522 return UnableToLegalize;
523 int NumParts = SizeOp0 / NarrowSize;
Tim Northoverff5e7e12017-06-30 20:27:36 +0000524
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000525 SmallVector<Register, 2> DstRegs;
Volkan Keles02bb1742018-02-14 19:58:36 +0000526 for (int i = 0; i < NumParts; ++i)
527 DstRegs.push_back(
528 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
Amara Emerson5ec14602018-12-10 18:44:58 +0000529
Matt Arsenault3018d182019-06-28 01:47:44 +0000530 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000531 if(MRI.getType(DstReg).isVector())
532 MIRBuilder.buildBuildVector(DstReg, DstRegs);
533 else
534 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northoverff5e7e12017-06-30 20:27:36 +0000535 MI.eraseFromParent();
536 return Legalized;
537 }
Matt Arsenault71872722019-04-10 17:27:53 +0000538 case TargetOpcode::G_CONSTANT: {
539 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
540 const APInt &Val = MI.getOperand(1).getCImm()->getValue();
541 unsigned TotalSize = Ty.getSizeInBits();
542 unsigned NarrowSize = NarrowTy.getSizeInBits();
543 int NumParts = TotalSize / NarrowSize;
544
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000545 SmallVector<Register, 4> PartRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000546 for (int I = 0; I != NumParts; ++I) {
547 unsigned Offset = I * NarrowSize;
548 auto K = MIRBuilder.buildConstant(NarrowTy,
549 Val.lshr(Offset).trunc(NarrowSize));
550 PartRegs.push_back(K.getReg(0));
551 }
552
553 LLT LeftoverTy;
554 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000555 SmallVector<Register, 1> LeftoverRegs;
Matt Arsenault71872722019-04-10 17:27:53 +0000556 if (LeftoverBits != 0) {
557 LeftoverTy = LLT::scalar(LeftoverBits);
558 auto K = MIRBuilder.buildConstant(
559 LeftoverTy,
560 Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits));
561 LeftoverRegs.push_back(K.getReg(0));
562 }
563
564 insertParts(MI.getOperand(0).getReg(),
565 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
566
567 MI.eraseFromParent();
568 return Legalized;
569 }
Amara Emerson7bc4fad2019-07-26 23:46:38 +0000570 case TargetOpcode::G_SEXT: {
571 if (TypeIdx != 0)
572 return UnableToLegalize;
573
574 if (NarrowTy.getSizeInBits() != SizeOp0 / 2) {
575 LLVM_DEBUG(dbgs() << "Can't narrow sext to type " << NarrowTy << "\n");
576 return UnableToLegalize;
577 }
578
579 Register SrcReg = MI.getOperand(1).getReg();
580
581 // Shift the sign bit of the low register through the high register.
582 auto ShiftAmt =
583 MIRBuilder.buildConstant(LLT::scalar(64), NarrowTy.getSizeInBits() - 1);
584 auto Shift = MIRBuilder.buildAShr(NarrowTy, SrcReg, ShiftAmt);
585 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {SrcReg, Shift.getReg(0)});
586 MI.eraseFromParent();
587 return Legalized;
588 }
589
Tim Northover9656f142016-08-04 20:54:13 +0000590 case TargetOpcode::G_ADD: {
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000591 // FIXME: add support for when SizeOp0 isn't an exact multiple of
592 // NarrowSize.
593 if (SizeOp0 % NarrowSize != 0)
594 return UnableToLegalize;
Tim Northover9656f142016-08-04 20:54:13 +0000595 // Expand in terms of carry-setting/consuming G_ADDE instructions.
Kristof Beylsaf9814a2017-11-07 10:34:34 +0000596 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
Tim Northover9656f142016-08-04 20:54:13 +0000597
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000598 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Tim Northover9656f142016-08-04 20:54:13 +0000599 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
600 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
601
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000602 Register CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover0f140c72016-09-09 11:46:34 +0000603 MIRBuilder.buildConstant(CarryIn, 0);
Tim Northover9656f142016-08-04 20:54:13 +0000604
605 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000606 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
607 Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Tim Northover9656f142016-08-04 20:54:13 +0000608
Tim Northover0f140c72016-09-09 11:46:34 +0000609 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
Tim Northover91c81732016-08-19 17:17:06 +0000610 Src2Regs[i], CarryIn);
Tim Northover9656f142016-08-04 20:54:13 +0000611
612 DstRegs.push_back(DstReg);
613 CarryIn = CarryOut;
614 }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000615 Register DstReg = MI.getOperand(0).getReg();
Amara Emerson5ec14602018-12-10 18:44:58 +0000616 if(MRI.getType(DstReg).isVector())
617 MIRBuilder.buildBuildVector(DstReg, DstRegs);
618 else
619 MIRBuilder.buildMerge(DstReg, DstRegs);
Tim Northover9656f142016-08-04 20:54:13 +0000620 MI.eraseFromParent();
621 return Legalized;
622 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000623 case TargetOpcode::G_SUB: {
624 // FIXME: add support for when SizeOp0 isn't an exact multiple of
625 // NarrowSize.
626 if (SizeOp0 % NarrowSize != 0)
627 return UnableToLegalize;
628
629 int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
630
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000631 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000632 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
633 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
634
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000635 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
636 Register BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000637 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut},
638 {Src1Regs[0], Src2Regs[0]});
639 DstRegs.push_back(DstReg);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000640 Register BorrowIn = BorrowOut;
Petar Avramovic7cecadb2019-01-28 12:10:17 +0000641 for (int i = 1; i < NumParts; ++i) {
642 DstReg = MRI.createGenericVirtualRegister(NarrowTy);
643 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
644
645 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut},
646 {Src1Regs[i], Src2Regs[i], BorrowIn});
647
648 DstRegs.push_back(DstReg);
649 BorrowIn = BorrowOut;
650 }
651 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
652 MI.eraseFromParent();
653 return Legalized;
654 }
Matt Arsenault211e89d2019-01-27 00:52:51 +0000655 case TargetOpcode::G_MUL:
Petar Avramovic5229f472019-03-11 10:08:44 +0000656 case TargetOpcode::G_UMULH:
Petar Avramovic0b17e592019-03-11 10:00:17 +0000657 return narrowScalarMul(MI, NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +0000658 case TargetOpcode::G_EXTRACT:
659 return narrowScalarExtract(MI, TypeIdx, NarrowTy);
660 case TargetOpcode::G_INSERT:
661 return narrowScalarInsert(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000662 case TargetOpcode::G_LOAD: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000663 const auto &MMO = **MI.memoperands_begin();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000664 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000665 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000666 if (DstTy.isVector())
Matt Arsenault045bc9a2019-01-30 02:35:38 +0000667 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000668
669 if (8 * MMO.getSize() != DstTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000670 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000671 auto &MMO = **MI.memoperands_begin();
672 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO);
673 MIRBuilder.buildAnyExt(DstReg, TmpReg);
674 MI.eraseFromParent();
675 return Legalized;
676 }
677
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000678 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Justin Bognerd09c3ce2017-01-19 01:05:48 +0000679 }
Matt Arsenault6614f852019-01-22 19:02:10 +0000680 case TargetOpcode::G_ZEXTLOAD:
681 case TargetOpcode::G_SEXTLOAD: {
682 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000683 Register DstReg = MI.getOperand(0).getReg();
684 Register PtrReg = MI.getOperand(1).getReg();
Matt Arsenault6614f852019-01-22 19:02:10 +0000685
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000686 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault6614f852019-01-22 19:02:10 +0000687 auto &MMO = **MI.memoperands_begin();
Amara Emersond51adf02019-04-17 22:21:05 +0000688 if (MMO.getSizeInBits() == NarrowSize) {
Matt Arsenault6614f852019-01-22 19:02:10 +0000689 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
690 } else {
691 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD
692 : TargetOpcode::G_SEXTLOAD;
693 MIRBuilder.buildInstr(ExtLoad)
694 .addDef(TmpReg)
695 .addUse(PtrReg)
696 .addMemOperand(&MMO);
697 }
698
699 if (ZExt)
700 MIRBuilder.buildZExt(DstReg, TmpReg);
701 else
702 MIRBuilder.buildSExt(DstReg, TmpReg);
703
704 MI.eraseFromParent();
705 return Legalized;
706 }
Justin Bognerfde01042017-01-18 17:29:54 +0000707 case TargetOpcode::G_STORE: {
Daniel Sanders27fe8a52018-04-27 19:48:53 +0000708 const auto &MMO = **MI.memoperands_begin();
Matt Arsenault18619af2019-01-29 18:13:02 +0000709
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000710 Register SrcReg = MI.getOperand(0).getReg();
Matt Arsenault18619af2019-01-29 18:13:02 +0000711 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000712 if (SrcTy.isVector())
713 return UnableToLegalize;
714
715 int NumParts = SizeOp0 / NarrowSize;
716 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
717 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
718 if (SrcTy.isVector() && LeftoverBits != 0)
719 return UnableToLegalize;
Matt Arsenault18619af2019-01-29 18:13:02 +0000720
721 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000722 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault18619af2019-01-29 18:13:02 +0000723 auto &MMO = **MI.memoperands_begin();
724 MIRBuilder.buildTrunc(TmpReg, SrcReg);
725 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO);
726 MI.eraseFromParent();
727 return Legalized;
728 }
729
Matt Arsenault7f09fd62019-02-05 00:26:12 +0000730 return reduceLoadStoreWidth(MI, 0, NarrowTy);
Justin Bognerfde01042017-01-18 17:29:54 +0000731 }
Matt Arsenault81511e52019-02-05 00:13:44 +0000732 case TargetOpcode::G_SELECT:
733 return narrowScalarSelect(MI, TypeIdx, NarrowTy);
Petar Avramovic150fd432018-12-18 11:36:14 +0000734 case TargetOpcode::G_AND:
735 case TargetOpcode::G_OR:
736 case TargetOpcode::G_XOR: {
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000737 // Legalize bitwise operation:
738 // A = BinOp<Ty> B, C
739 // into:
740 // B1, ..., BN = G_UNMERGE_VALUES B
741 // C1, ..., CN = G_UNMERGE_VALUES C
742 // A1 = BinOp<Ty/N> B1, C2
743 // ...
744 // AN = BinOp<Ty/N> BN, CN
745 // A = G_MERGE_VALUES A1, ..., AN
Matt Arsenault9e0eeba2019-04-10 17:07:56 +0000746 return narrowScalarBasic(MI, TypeIdx, NarrowTy);
Quentin Colombetc2f3cea2017-10-03 04:53:56 +0000747 }
Matt Arsenault30989e42019-01-22 21:42:11 +0000748 case TargetOpcode::G_SHL:
749 case TargetOpcode::G_LSHR:
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +0000750 case TargetOpcode::G_ASHR:
751 return narrowScalarShift(MI, TypeIdx, NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000752 case TargetOpcode::G_CTLZ:
753 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
754 case TargetOpcode::G_CTTZ:
755 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
756 case TargetOpcode::G_CTPOP:
757 if (TypeIdx != 0)
758 return UnableToLegalize; // TODO
759
760 Observer.changingInstr(MI);
761 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
762 Observer.changedInstr(MI);
763 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +0000764 case TargetOpcode::G_INTTOPTR:
765 if (TypeIdx != 1)
766 return UnableToLegalize;
767
768 Observer.changingInstr(MI);
769 narrowScalarSrc(MI, NarrowTy, 1);
770 Observer.changedInstr(MI);
771 return Legalized;
772 case TargetOpcode::G_PTRTOINT:
773 if (TypeIdx != 0)
774 return UnableToLegalize;
775
776 Observer.changingInstr(MI);
777 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
778 Observer.changedInstr(MI);
779 return Legalized;
Petar Avramovicbe20e362019-07-09 14:36:17 +0000780 case TargetOpcode::G_PHI: {
781 unsigned NumParts = SizeOp0 / NarrowSize;
782 SmallVector<Register, 2> DstRegs;
783 SmallVector<SmallVector<Register, 2>, 2> SrcRegs;
784 DstRegs.resize(NumParts);
785 SrcRegs.resize(MI.getNumOperands() / 2);
786 Observer.changingInstr(MI);
787 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
788 MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB();
789 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
790 extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts,
791 SrcRegs[i / 2]);
792 }
793 MachineBasicBlock &MBB = *MI.getParent();
794 MIRBuilder.setInsertPt(MBB, MI);
795 for (unsigned i = 0; i < NumParts; ++i) {
796 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
797 MachineInstrBuilder MIB =
798 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
799 for (unsigned j = 1; j < MI.getNumOperands(); j += 2)
800 MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1));
801 }
802 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
803 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
804 Observer.changedInstr(MI);
805 MI.eraseFromParent();
806 return Legalized;
807 }
Matt Arsenault434d6642019-07-15 19:37:34 +0000808 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
809 case TargetOpcode::G_INSERT_VECTOR_ELT: {
810 if (TypeIdx != 2)
811 return UnableToLegalize;
812
813 int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
814 Observer.changingInstr(MI);
815 narrowScalarSrc(MI, NarrowTy, OpIdx);
816 Observer.changedInstr(MI);
817 return Legalized;
818 }
Petar Avramovic1e626352019-07-17 12:08:01 +0000819 case TargetOpcode::G_ICMP: {
820 uint64_t SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
821 if (NarrowSize * 2 != SrcSize)
822 return UnableToLegalize;
823
824 Observer.changingInstr(MI);
825 Register LHSL = MRI.createGenericVirtualRegister(NarrowTy);
826 Register LHSH = MRI.createGenericVirtualRegister(NarrowTy);
827 MIRBuilder.buildUnmerge({LHSL, LHSH}, MI.getOperand(2).getReg());
828
829 Register RHSL = MRI.createGenericVirtualRegister(NarrowTy);
830 Register RHSH = MRI.createGenericVirtualRegister(NarrowTy);
831 MIRBuilder.buildUnmerge({RHSL, RHSH}, MI.getOperand(3).getReg());
832
833 CmpInst::Predicate Pred =
834 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
Amara Emersona1997ce2019-07-24 20:46:42 +0000835 LLT ResTy = MRI.getType(MI.getOperand(0).getReg());
Petar Avramovic1e626352019-07-17 12:08:01 +0000836
837 if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) {
838 MachineInstrBuilder XorL = MIRBuilder.buildXor(NarrowTy, LHSL, RHSL);
839 MachineInstrBuilder XorH = MIRBuilder.buildXor(NarrowTy, LHSH, RHSH);
840 MachineInstrBuilder Or = MIRBuilder.buildOr(NarrowTy, XorL, XorH);
841 MachineInstrBuilder Zero = MIRBuilder.buildConstant(NarrowTy, 0);
842 MIRBuilder.buildICmp(Pred, MI.getOperand(0).getReg(), Or, Zero);
843 } else {
Amara Emersona1997ce2019-07-24 20:46:42 +0000844 MachineInstrBuilder CmpH = MIRBuilder.buildICmp(Pred, ResTy, LHSH, RHSH);
Petar Avramovic1e626352019-07-17 12:08:01 +0000845 MachineInstrBuilder CmpHEQ =
Amara Emersona1997ce2019-07-24 20:46:42 +0000846 MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy, LHSH, RHSH);
Petar Avramovic1e626352019-07-17 12:08:01 +0000847 MachineInstrBuilder CmpLU = MIRBuilder.buildICmp(
Amara Emersona1997ce2019-07-24 20:46:42 +0000848 ICmpInst::getUnsignedPredicate(Pred), ResTy, LHSL, RHSL);
Petar Avramovic1e626352019-07-17 12:08:01 +0000849 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), CmpHEQ, CmpLU, CmpH);
850 }
851 Observer.changedInstr(MI);
852 MI.eraseFromParent();
853 return Legalized;
854 }
Tim Northover9656f142016-08-04 20:54:13 +0000855 }
Tim Northover33b07d62016-07-22 20:03:43 +0000856}
857
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000858void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
859 unsigned OpIdx, unsigned ExtOpcode) {
860 MachineOperand &MO = MI.getOperand(OpIdx);
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000861 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000862 MO.setReg(ExtB->getOperand(0).getReg());
863}
864
Matt Arsenault30989e42019-01-22 21:42:11 +0000865void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
866 unsigned OpIdx) {
867 MachineOperand &MO = MI.getOperand(OpIdx);
868 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy},
869 {MO.getReg()});
870 MO.setReg(ExtB->getOperand(0).getReg());
871}
872
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000873void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
874 unsigned OpIdx, unsigned TruncOpcode) {
875 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000876 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000877 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000878 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt});
Roman Tereshind5fa9fd2018-05-09 17:28:18 +0000879 MO.setReg(DstExt);
880}
881
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000882void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
883 unsigned OpIdx, unsigned ExtOpcode) {
884 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000885 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultd5684f72019-01-31 02:09:57 +0000886 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
887 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc});
888 MO.setReg(DstTrunc);
889}
890
Matt Arsenault18ec3822019-02-11 22:00:39 +0000891void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy,
892 unsigned OpIdx) {
893 MachineOperand &MO = MI.getOperand(OpIdx);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000894 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +0000895 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
896 MIRBuilder.buildExtract(MO.getReg(), DstExt, 0);
897 MO.setReg(DstExt);
898}
899
Matt Arsenault26b7e852019-02-19 16:30:19 +0000900void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy,
901 unsigned OpIdx) {
902 MachineOperand &MO = MI.getOperand(OpIdx);
903
904 LLT OldTy = MRI.getType(MO.getReg());
905 unsigned OldElts = OldTy.getNumElements();
906 unsigned NewElts = MoreTy.getNumElements();
907
908 unsigned NumParts = NewElts / OldElts;
909
910 // Use concat_vectors if the result is a multiple of the number of elements.
911 if (NumParts * OldElts == NewElts) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000912 SmallVector<Register, 8> Parts;
Matt Arsenault26b7e852019-02-19 16:30:19 +0000913 Parts.push_back(MO.getReg());
914
Matt Arsenault3018d182019-06-28 01:47:44 +0000915 Register ImpDef = MIRBuilder.buildUndef(OldTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +0000916 for (unsigned I = 1; I != NumParts; ++I)
917 Parts.push_back(ImpDef);
918
919 auto Concat = MIRBuilder.buildConcatVectors(MoreTy, Parts);
920 MO.setReg(Concat.getReg(0));
921 return;
922 }
923
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000924 Register MoreReg = MRI.createGenericVirtualRegister(MoreTy);
925 Register ImpDef = MIRBuilder.buildUndef(MoreTy).getReg(0);
Matt Arsenault26b7e852019-02-19 16:30:19 +0000926 MIRBuilder.buildInsert(MoreReg, ImpDef, MO.getReg(), 0);
927 MO.setReg(MoreReg);
928}
929
Tim Northover69fa84a2016-10-14 22:18:18 +0000930LegalizerHelper::LegalizeResult
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000931LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
932 LLT WideTy) {
933 if (TypeIdx != 1)
934 return UnableToLegalize;
935
Matt Arsenaulte3a676e2019-06-24 15:50:29 +0000936 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000937 LLT DstTy = MRI.getType(DstReg);
Matt Arsenault43cbca52019-07-03 23:08:06 +0000938 if (DstTy.isVector())
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000939 return UnableToLegalize;
940
Matt Arsenaultc9f14f22019-07-01 19:36:10 +0000941 Register Src1 = MI.getOperand(1).getReg();
942 LLT SrcTy = MRI.getType(Src1);
Matt Arsenault0966dd02019-07-17 20:22:44 +0000943 const int DstSize = DstTy.getSizeInBits();
944 const int SrcSize = SrcTy.getSizeInBits();
945 const int WideSize = WideTy.getSizeInBits();
946 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
Matt Arsenaultc9f14f22019-07-01 19:36:10 +0000947
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000948 unsigned NumOps = MI.getNumOperands();
949 unsigned NumSrc = MI.getNumOperands() - 1;
950 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
951
Matt Arsenault0966dd02019-07-17 20:22:44 +0000952 if (WideSize >= DstSize) {
953 // Directly pack the bits in the target type.
954 Register ResultReg = MIRBuilder.buildZExt(WideTy, Src1).getReg(0);
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000955
Matt Arsenault0966dd02019-07-17 20:22:44 +0000956 for (unsigned I = 2; I != NumOps; ++I) {
957 const unsigned Offset = (I - 1) * PartSize;
Matt Arsenault888aa5d2019-02-03 00:07:33 +0000958
Matt Arsenault0966dd02019-07-17 20:22:44 +0000959 Register SrcReg = MI.getOperand(I).getReg();
960 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));
961
962 auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg);
963
964 Register NextResult = I + 1 == NumOps && WideSize == DstSize ? DstReg :
965 MRI.createGenericVirtualRegister(WideTy);
966
967 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset);
968 auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
969 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
970 ResultReg = NextResult;
971 }
972
973 if (WideSize > DstSize)
974 MIRBuilder.buildTrunc(DstReg, ResultReg);
975
976 MI.eraseFromParent();
977 return Legalized;
978 }
979
980 // Unmerge the original values to the GCD type, and recombine to the next
981 // multiple greater than the original type.
982 //
983 // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6
984 // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0
985 // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1
986 // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2
987 // %10:_(s6) = G_MERGE_VALUES %4, %5, %6
988 // %11:_(s6) = G_MERGE_VALUES %7, %8, %9
989 // %12:_(s12) = G_MERGE_VALUES %10, %11
990 //
991 // Padding with undef if necessary:
992 //
993 // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6
994 // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0
995 // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1
996 // %7:_(s2) = G_IMPLICIT_DEF
997 // %8:_(s6) = G_MERGE_VALUES %3, %4, %5
998 // %9:_(s6) = G_MERGE_VALUES %6, %7, %7
999 // %10:_(s12) = G_MERGE_VALUES %8, %9
1000
1001 const int GCD = greatestCommonDivisor(SrcSize, WideSize);
1002 LLT GCDTy = LLT::scalar(GCD);
1003
1004 SmallVector<Register, 8> Parts;
1005 SmallVector<Register, 8> NewMergeRegs;
1006 SmallVector<Register, 8> Unmerges;
1007 LLT WideDstTy = LLT::scalar(NumMerge * WideSize);
1008
1009 // Decompose the original operands if they don't evenly divide.
1010 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001011 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenault0966dd02019-07-17 20:22:44 +00001012 if (GCD == SrcSize) {
1013 Unmerges.push_back(SrcReg);
1014 } else {
1015 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg);
1016 for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
1017 Unmerges.push_back(Unmerge.getReg(J));
1018 }
1019 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001020
Matt Arsenault0966dd02019-07-17 20:22:44 +00001021 // Pad with undef to the next size that is a multiple of the requested size.
1022 if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) {
1023 Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0);
1024 for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I)
1025 Unmerges.push_back(UndefReg);
1026 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001027
Matt Arsenault0966dd02019-07-17 20:22:44 +00001028 const int PartsPerGCD = WideSize / GCD;
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001029
Matt Arsenault0966dd02019-07-17 20:22:44 +00001030 // Build merges of each piece.
1031 ArrayRef<Register> Slicer(Unmerges);
1032 for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) {
1033 auto Merge = MIRBuilder.buildMerge(WideTy, Slicer.take_front(PartsPerGCD));
1034 NewMergeRegs.push_back(Merge.getReg(0));
1035 }
1036
1037 // A truncate may be necessary if the requested type doesn't evenly divide the
1038 // original result type.
1039 if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) {
1040 MIRBuilder.buildMerge(DstReg, NewMergeRegs);
1041 } else {
1042 auto FinalMerge = MIRBuilder.buildMerge(WideDstTy, NewMergeRegs);
1043 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001044 }
1045
1046 MI.eraseFromParent();
1047 return Legalized;
1048}
1049
1050LegalizerHelper::LegalizeResult
1051LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
1052 LLT WideTy) {
1053 if (TypeIdx != 0)
1054 return UnableToLegalize;
1055
1056 unsigned NumDst = MI.getNumOperands() - 1;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001057 Register SrcReg = MI.getOperand(NumDst).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001058 LLT SrcTy = MRI.getType(SrcReg);
1059 if (!SrcTy.isScalar())
1060 return UnableToLegalize;
1061
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001062 Register Dst0Reg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001063 LLT DstTy = MRI.getType(Dst0Reg);
1064 if (!DstTy.isScalar())
1065 return UnableToLegalize;
1066
1067 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
1068 LLT NewSrcTy = LLT::scalar(NewSrcSize);
1069 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
1070
1071 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
1072
1073 for (unsigned I = 1; I != NumDst; ++I) {
1074 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
1075 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
1076 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
1077 }
1078
1079 Observer.changingInstr(MI);
1080
1081 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
1082 for (unsigned I = 0; I != NumDst; ++I)
1083 widenScalarDst(MI, WideTy, I);
1084
1085 Observer.changedInstr(MI);
1086
1087 return Legalized;
1088}
1089
1090LegalizerHelper::LegalizeResult
Matt Arsenault1cf71362019-02-12 14:54:52 +00001091LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
1092 LLT WideTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001093 Register DstReg = MI.getOperand(0).getReg();
1094 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00001095 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenaultfbe92a52019-02-18 22:39:27 +00001096
1097 LLT DstTy = MRI.getType(DstReg);
1098 unsigned Offset = MI.getOperand(2).getImm();
1099
1100 if (TypeIdx == 0) {
1101 if (SrcTy.isVector() || DstTy.isVector())
1102 return UnableToLegalize;
1103
1104 SrcOp Src(SrcReg);
1105 if (SrcTy.isPointer()) {
1106 // Extracts from pointers can be handled only if they are really just
1107 // simple integers.
1108 const DataLayout &DL = MIRBuilder.getDataLayout();
1109 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
1110 return UnableToLegalize;
1111
1112 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
1113 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
1114 SrcTy = SrcAsIntTy;
1115 }
1116
1117 if (DstTy.isPointer())
1118 return UnableToLegalize;
1119
1120 if (Offset == 0) {
1121 // Avoid a shift in the degenerate case.
1122 MIRBuilder.buildTrunc(DstReg,
1123 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
1124 MI.eraseFromParent();
1125 return Legalized;
1126 }
1127
1128 // Do a shift in the source type.
1129 LLT ShiftTy = SrcTy;
1130 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
1131 Src = MIRBuilder.buildAnyExt(WideTy, Src);
1132 ShiftTy = WideTy;
1133 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits())
1134 return UnableToLegalize;
1135
1136 auto LShr = MIRBuilder.buildLShr(
1137 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
1138 MIRBuilder.buildTrunc(DstReg, LShr);
1139 MI.eraseFromParent();
1140 return Legalized;
1141 }
1142
Matt Arsenault8f624ab2019-04-22 15:10:42 +00001143 if (SrcTy.isScalar()) {
1144 Observer.changingInstr(MI);
1145 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1146 Observer.changedInstr(MI);
1147 return Legalized;
1148 }
1149
Matt Arsenault1cf71362019-02-12 14:54:52 +00001150 if (!SrcTy.isVector())
1151 return UnableToLegalize;
1152
Matt Arsenault1cf71362019-02-12 14:54:52 +00001153 if (DstTy != SrcTy.getElementType())
1154 return UnableToLegalize;
1155
Matt Arsenault1cf71362019-02-12 14:54:52 +00001156 if (Offset % SrcTy.getScalarSizeInBits() != 0)
1157 return UnableToLegalize;
1158
1159 Observer.changingInstr(MI);
1160 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1161
1162 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
1163 Offset);
1164 widenScalarDst(MI, WideTy.getScalarType(), 0);
1165 Observer.changedInstr(MI);
1166 return Legalized;
1167}
1168
1169LegalizerHelper::LegalizeResult
1170LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
1171 LLT WideTy) {
1172 if (TypeIdx != 0)
1173 return UnableToLegalize;
1174 Observer.changingInstr(MI);
1175 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1176 widenScalarDst(MI, WideTy);
1177 Observer.changedInstr(MI);
1178 return Legalized;
1179}
1180
1181LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001182LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +00001183 MIRBuilder.setInstr(MI);
1184
Tim Northover32335812016-08-04 18:35:11 +00001185 switch (MI.getOpcode()) {
1186 default:
1187 return UnableToLegalize;
Matt Arsenault1cf71362019-02-12 14:54:52 +00001188 case TargetOpcode::G_EXTRACT:
1189 return widenScalarExtract(MI, TypeIdx, WideTy);
1190 case TargetOpcode::G_INSERT:
1191 return widenScalarInsert(MI, TypeIdx, WideTy);
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001192 case TargetOpcode::G_MERGE_VALUES:
1193 return widenScalarMergeValues(MI, TypeIdx, WideTy);
1194 case TargetOpcode::G_UNMERGE_VALUES:
1195 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001196 case TargetOpcode::G_UADDO:
1197 case TargetOpcode::G_USUBO: {
1198 if (TypeIdx == 1)
1199 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001200 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1201 {MI.getOperand(2).getReg()});
1202 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1203 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001204 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
1205 ? TargetOpcode::G_ADD
1206 : TargetOpcode::G_SUB;
1207 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001208 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001209 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
1210 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
1211 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001212 TargetOpcode::G_AND, {WideTy},
1213 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001214 // There is no overflow if the AndOp is the same as NewOp.
1215 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1216 AndOp);
1217 // Now trunc the NewOp to the original result.
1218 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1219 MI.eraseFromParent();
1220 return Legalized;
1221 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001222 case TargetOpcode::G_CTTZ:
1223 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1224 case TargetOpcode::G_CTLZ:
1225 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1226 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001227 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001228 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001229 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001230 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001231 return Legalized;
1232 }
1233
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001234 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001235
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001236 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001237 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1238 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001239 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1240 // The count is the same in the larger type except if the original
1241 // value was zero. This can be handled by setting the bit just off
1242 // the top of the original type.
1243 auto TopBit =
1244 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001245 MIBSrc = MIRBuilder.buildOr(
1246 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001247 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001248
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001249 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001250 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001251 // This is already the correct result for CTPOP and CTTZs
1252 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1253 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1254 // The correct result is NewOp - (Difference in widety and current ty).
1255 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001256 MIBNewOp = MIRBuilder.buildInstr(
1257 TargetOpcode::G_SUB, {WideTy},
1258 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001259 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001260
1261 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1262 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001263 return Legalized;
1264 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001265 case TargetOpcode::G_BSWAP: {
1266 Observer.changingInstr(MI);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001267 Register DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001268
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001269 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
1270 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
1271 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001272 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1273
1274 MI.getOperand(0).setReg(DstExt);
1275
1276 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1277
1278 LLT Ty = MRI.getType(DstReg);
1279 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1280 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1281 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1282 .addDef(ShrReg)
1283 .addUse(DstExt)
1284 .addUse(ShiftAmtReg);
1285
1286 MIRBuilder.buildTrunc(DstReg, ShrReg);
1287 Observer.changedInstr(MI);
1288 return Legalized;
1289 }
Tim Northover61c16142016-08-04 21:39:49 +00001290 case TargetOpcode::G_ADD:
1291 case TargetOpcode::G_AND:
1292 case TargetOpcode::G_MUL:
1293 case TargetOpcode::G_OR:
1294 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001295 case TargetOpcode::G_SUB:
Matt Arsenault1cf71362019-02-12 14:54:52 +00001296 // Perform operation at larger width (any extension is fines here, high bits
Tim Northover32335812016-08-04 18:35:11 +00001297 // don't affect the result) and then truncate the result back to the
1298 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001299 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001300 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1301 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1302 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001303 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001304 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001305
Roman Tereshin6d266382018-05-09 21:43:30 +00001306 case TargetOpcode::G_SHL:
Matt Arsenault012ecbb2019-05-16 04:08:46 +00001307 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001308
1309 if (TypeIdx == 0) {
1310 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1311 widenScalarDst(MI, WideTy);
1312 } else {
1313 assert(TypeIdx == 1);
1314 // The "number of bits to shift" operand must preserve its value as an
1315 // unsigned integer:
1316 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1317 }
1318
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001319 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001320 return Legalized;
1321
Tim Northover7a753d92016-08-26 17:46:06 +00001322 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001323 case TargetOpcode::G_SREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001324 case TargetOpcode::G_SMIN:
1325 case TargetOpcode::G_SMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001326 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001327 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1328 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1329 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001330 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001331 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001332
Roman Tereshin6d266382018-05-09 21:43:30 +00001333 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001334 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001335 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001336
1337 if (TypeIdx == 0) {
1338 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1339 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1340
1341 widenScalarSrc(MI, WideTy, 1, CvtOp);
1342 widenScalarDst(MI, WideTy);
1343 } else {
1344 assert(TypeIdx == 1);
1345 // The "number of bits to shift" operand must preserve its value as an
1346 // unsigned integer:
1347 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1348 }
1349
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001350 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001351 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001352 case TargetOpcode::G_UDIV:
1353 case TargetOpcode::G_UREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001354 case TargetOpcode::G_UMIN:
1355 case TargetOpcode::G_UMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001356 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001357 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1358 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1359 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001360 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001361 return Legalized;
1362
1363 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001364 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001365 if (TypeIdx == 0) {
1366 // Perform operation at larger width (any extension is fine here, high
1367 // bits don't affect the result) and then truncate the result back to the
1368 // original type.
1369 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1370 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1371 widenScalarDst(MI, WideTy);
1372 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001373 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001374 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001375 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001376 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001377 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001378 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001379
Ahmed Bougachab6137062017-01-23 21:10:14 +00001380 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001381 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001382 if (TypeIdx != 0)
1383 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001384 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001385 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001386 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001387 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001388
Ahmed Bougachad2948232017-01-20 01:37:24 +00001389 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001390 if (TypeIdx != 1)
1391 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001392 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001393 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001394 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001395 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001396
1397 case TargetOpcode::G_UITOFP:
1398 if (TypeIdx != 1)
1399 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001400 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001401 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001402 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001403 return Legalized;
1404
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001405 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001406 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001407 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001408 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001409 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001410 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001411 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001412
Tim Northover3c73e362016-08-23 18:20:09 +00001413 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001414 if (TypeIdx != 0)
1415 return UnableToLegalize;
1416
1417 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1418 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001419 return UnableToLegalize;
1420
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001421 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001422
1423 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1424 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1425 widenScalarSrc(MI, WideTy, 0, ExtType);
1426
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001427 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001428 return Legalized;
1429 }
Tim Northoverea904f92016-08-19 22:40:00 +00001430 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001431 MachineOperand &SrcMO = MI.getOperand(1);
1432 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1433 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001434 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001435 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1436
1437 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001438 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001439 return Legalized;
1440 }
Tim Northovera11be042016-08-19 22:40:08 +00001441 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001442 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001443 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001444 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001445 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001446 switch (WideTy.getSizeInBits()) {
1447 case 32:
Matt Arsenault996c6662019-02-12 14:54:54 +00001448 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
1449 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001450 break;
1451 case 64:
Matt Arsenault996c6662019-02-12 14:54:54 +00001452 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
1453 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001454 break;
1455 default:
Matt Arsenault996c6662019-02-12 14:54:54 +00001456 return UnableToLegalize;
Tim Northover6cd4b232016-08-23 21:01:26 +00001457 }
Matt Arsenault996c6662019-02-12 14:54:54 +00001458
1459 assert(!LosesInfo && "extend should always be lossless");
1460
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001461 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001462 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1463
1464 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001465 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001466 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001467 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001468 case TargetOpcode::G_IMPLICIT_DEF: {
1469 Observer.changingInstr(MI);
1470 widenScalarDst(MI, WideTy);
1471 Observer.changedInstr(MI);
1472 return Legalized;
1473 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001474 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001475 Observer.changingInstr(MI);
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +00001476 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001477 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001478 return Legalized;
1479
1480 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001481 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001482 if (TypeIdx == 0)
1483 widenScalarDst(MI, WideTy);
1484 else {
1485 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1486 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001487 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001488 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001489 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001490
1491 case TargetOpcode::G_ICMP:
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 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1497 MI.getOperand(1).getPredicate()))
1498 ? TargetOpcode::G_SEXT
1499 : TargetOpcode::G_ZEXT;
1500 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1501 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1502 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001503 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001504 return Legalized;
1505
1506 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001507 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001508 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001509 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001510 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001511 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001512
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001513 case TargetOpcode::G_PHI: {
1514 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001515
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001516 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001517 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1518 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1519 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1520 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001521 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001522
1523 MachineBasicBlock &MBB = *MI.getParent();
1524 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1525 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001526 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001527 return Legalized;
1528 }
Matt Arsenault63786292019-01-22 20:38:15 +00001529 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1530 if (TypeIdx == 0) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001531 Register VecReg = MI.getOperand(1).getReg();
Matt Arsenault63786292019-01-22 20:38:15 +00001532 LLT VecTy = MRI.getType(VecReg);
1533 Observer.changingInstr(MI);
1534
1535 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1536 WideTy.getSizeInBits()),
1537 1, TargetOpcode::G_SEXT);
1538
1539 widenScalarDst(MI, WideTy, 0);
1540 Observer.changedInstr(MI);
1541 return Legalized;
1542 }
1543
Amara Emersoncbd86d82018-10-25 14:04:54 +00001544 if (TypeIdx != 2)
1545 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001546 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001547 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001548 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001549 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001550 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001551 case TargetOpcode::G_FADD:
1552 case TargetOpcode::G_FMUL:
1553 case TargetOpcode::G_FSUB:
1554 case TargetOpcode::G_FMA:
1555 case TargetOpcode::G_FNEG:
1556 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001557 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001558 case TargetOpcode::G_FMINNUM:
1559 case TargetOpcode::G_FMAXNUM:
1560 case TargetOpcode::G_FMINNUM_IEEE:
1561 case TargetOpcode::G_FMAXNUM_IEEE:
1562 case TargetOpcode::G_FMINIMUM:
1563 case TargetOpcode::G_FMAXIMUM:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001564 case TargetOpcode::G_FDIV:
1565 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001566 case TargetOpcode::G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00001567 case TargetOpcode::G_FFLOOR:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001568 case TargetOpcode::G_FCOS:
1569 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001570 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001571 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001572 case TargetOpcode::G_FLOG2:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00001573 case TargetOpcode::G_FRINT:
Jessica Paquetteba557672019-04-25 16:44:40 +00001574 case TargetOpcode::G_FNEARBYINT:
Jessica Paquette22457f82019-01-30 21:03:52 +00001575 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001576 case TargetOpcode::G_FEXP:
Jessica Paquettee7941212019-04-03 16:58:32 +00001577 case TargetOpcode::G_FEXP2:
Jessica Paquettedfd87f62019-04-19 16:28:08 +00001578 case TargetOpcode::G_FPOW:
Jessica Paquette56342642019-04-23 18:20:44 +00001579 case TargetOpcode::G_INTRINSIC_TRUNC:
Jessica Paquette3cc6d1f2019-04-23 21:11:57 +00001580 case TargetOpcode::G_INTRINSIC_ROUND:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001581 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001582 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001583
1584 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1585 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1586
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001587 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1588 Observer.changedInstr(MI);
1589 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001590 case TargetOpcode::G_INTTOPTR:
1591 if (TypeIdx != 1)
1592 return UnableToLegalize;
1593
1594 Observer.changingInstr(MI);
1595 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1596 Observer.changedInstr(MI);
1597 return Legalized;
1598 case TargetOpcode::G_PTRTOINT:
1599 if (TypeIdx != 0)
1600 return UnableToLegalize;
1601
1602 Observer.changingInstr(MI);
1603 widenScalarDst(MI, WideTy, 0);
1604 Observer.changedInstr(MI);
1605 return Legalized;
Matt Arsenaultbd791b52019-07-08 13:48:06 +00001606 case TargetOpcode::G_BUILD_VECTOR: {
1607 Observer.changingInstr(MI);
1608
1609 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType();
1610 for (int I = 1, E = MI.getNumOperands(); I != E; ++I)
1611 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT);
1612
1613 // Avoid changing the result vector type if the source element type was
1614 // requested.
1615 if (TypeIdx == 1) {
1616 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
1617 MI.setDesc(TII.get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
1618 } else {
1619 widenScalarDst(MI, WideTy, 0);
1620 }
1621
1622 Observer.changedInstr(MI);
1623 return Legalized;
1624 }
Tim Northover32335812016-08-04 18:35:11 +00001625 }
Tim Northover33b07d62016-07-22 20:03:43 +00001626}
1627
Tim Northover69fa84a2016-10-14 22:18:18 +00001628LegalizerHelper::LegalizeResult
1629LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001630 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001631 MIRBuilder.setInstr(MI);
1632
1633 switch(MI.getOpcode()) {
1634 default:
1635 return UnableToLegalize;
1636 case TargetOpcode::G_SREM:
1637 case TargetOpcode::G_UREM: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001638 Register QuotReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001639 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001640 .addDef(QuotReg)
1641 .addUse(MI.getOperand(1).getReg())
1642 .addUse(MI.getOperand(2).getReg());
1643
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001644 Register ProdReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001645 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1646 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1647 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001648 MI.eraseFromParent();
1649 return Legalized;
1650 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001651 case TargetOpcode::G_SMULO:
1652 case TargetOpcode::G_UMULO: {
1653 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1654 // result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001655 Register Res = MI.getOperand(0).getReg();
1656 Register Overflow = MI.getOperand(1).getReg();
1657 Register LHS = MI.getOperand(2).getReg();
1658 Register RHS = MI.getOperand(3).getReg();
Tim Northover0a9b2792017-02-08 21:22:15 +00001659
1660 MIRBuilder.buildMul(Res, LHS, RHS);
1661
1662 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1663 ? TargetOpcode::G_SMULH
1664 : TargetOpcode::G_UMULH;
1665
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001666 Register HiPart = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001667 MIRBuilder.buildInstr(Opcode)
1668 .addDef(HiPart)
1669 .addUse(LHS)
1670 .addUse(RHS);
1671
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001672 Register Zero = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001673 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001674
1675 // For *signed* multiply, overflow is detected by checking:
1676 // (hi != (lo >> bitwidth-1))
1677 if (Opcode == TargetOpcode::G_SMULH) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001678 Register Shifted = MRI.createGenericVirtualRegister(Ty);
1679 Register ShiftAmt = MRI.createGenericVirtualRegister(Ty);
Amara Emerson9de62132018-01-03 04:56:56 +00001680 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1681 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1682 .addDef(Shifted)
1683 .addUse(Res)
1684 .addUse(ShiftAmt);
1685 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1686 } else {
1687 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1688 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001689 MI.eraseFromParent();
1690 return Legalized;
1691 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001692 case TargetOpcode::G_FNEG: {
1693 // TODO: Handle vector types once we are able to
1694 // represent them.
1695 if (Ty.isVector())
1696 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001697 Register Res = MI.getOperand(0).getReg();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001698 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001699 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001700 switch (Ty.getSizeInBits()) {
1701 case 16:
1702 ZeroTy = Type::getHalfTy(Ctx);
1703 break;
1704 case 32:
1705 ZeroTy = Type::getFloatTy(Ctx);
1706 break;
1707 case 64:
1708 ZeroTy = Type::getDoubleTy(Ctx);
1709 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001710 case 128:
1711 ZeroTy = Type::getFP128Ty(Ctx);
1712 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001713 default:
1714 llvm_unreachable("unexpected floating-point type");
1715 }
1716 ConstantFP &ZeroForNegation =
1717 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001718 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001719 Register SubByReg = MI.getOperand(1).getReg();
1720 Register ZeroReg = Zero->getOperand(0).getReg();
Michael Bergd573aa02019-04-18 18:48:57 +00001721 MIRBuilder.buildInstr(TargetOpcode::G_FSUB, {Res}, {ZeroReg, SubByReg},
Matt Arsenault5a321b82019-06-17 23:48:43 +00001722 MI.getFlags());
Volkan Keles5698b2a2017-03-08 18:09:14 +00001723 MI.eraseFromParent();
1724 return Legalized;
1725 }
Volkan Keles225921a2017-03-10 21:25:09 +00001726 case TargetOpcode::G_FSUB: {
1727 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1728 // First, check if G_FNEG is marked as Lower. If so, we may
1729 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001730 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001731 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001732 Register Res = MI.getOperand(0).getReg();
1733 Register LHS = MI.getOperand(1).getReg();
1734 Register RHS = MI.getOperand(2).getReg();
1735 Register Neg = MRI.createGenericVirtualRegister(Ty);
Volkan Keles225921a2017-03-10 21:25:09 +00001736 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
Michael Bergd573aa02019-04-18 18:48:57 +00001737 MIRBuilder.buildInstr(TargetOpcode::G_FADD, {Res}, {LHS, Neg}, MI.getFlags());
Volkan Keles225921a2017-03-10 21:25:09 +00001738 MI.eraseFromParent();
1739 return Legalized;
1740 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001741 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001742 Register OldValRes = MI.getOperand(0).getReg();
1743 Register SuccessRes = MI.getOperand(1).getReg();
1744 Register Addr = MI.getOperand(2).getReg();
1745 Register CmpVal = MI.getOperand(3).getReg();
1746 Register NewVal = MI.getOperand(4).getReg();
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001747 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1748 **MI.memoperands_begin());
1749 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1750 MI.eraseFromParent();
1751 return Legalized;
1752 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001753 case TargetOpcode::G_LOAD:
1754 case TargetOpcode::G_SEXTLOAD:
1755 case TargetOpcode::G_ZEXTLOAD: {
1756 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001757 Register DstReg = MI.getOperand(0).getReg();
1758 Register PtrReg = MI.getOperand(1).getReg();
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001759 LLT DstTy = MRI.getType(DstReg);
1760 auto &MMO = **MI.memoperands_begin();
1761
Amara Emerson42866522019-04-20 21:25:00 +00001762 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) {
1763 // In the case of G_LOAD, this was a non-extending load already and we're
1764 // about to lower to the same instruction.
1765 if (MI.getOpcode() == TargetOpcode::G_LOAD)
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001766 return UnableToLegalize;
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001767 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1768 MI.eraseFromParent();
1769 return Legalized;
1770 }
1771
1772 if (DstTy.isScalar()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001773 Register TmpReg =
Amara Emersond51adf02019-04-17 22:21:05 +00001774 MRI.createGenericVirtualRegister(LLT::scalar(MMO.getSizeInBits()));
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001775 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1776 switch (MI.getOpcode()) {
1777 default:
1778 llvm_unreachable("Unexpected opcode");
1779 case TargetOpcode::G_LOAD:
1780 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1781 break;
1782 case TargetOpcode::G_SEXTLOAD:
1783 MIRBuilder.buildSExt(DstReg, TmpReg);
1784 break;
1785 case TargetOpcode::G_ZEXTLOAD:
1786 MIRBuilder.buildZExt(DstReg, TmpReg);
1787 break;
1788 }
1789 MI.eraseFromParent();
1790 return Legalized;
1791 }
1792
1793 return UnableToLegalize;
1794 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001795 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1796 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1797 case TargetOpcode::G_CTLZ:
1798 case TargetOpcode::G_CTTZ:
1799 case TargetOpcode::G_CTPOP:
1800 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicbd395692019-02-26 17:22:42 +00001801 case G_UADDO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001802 Register Res = MI.getOperand(0).getReg();
1803 Register CarryOut = MI.getOperand(1).getReg();
1804 Register LHS = MI.getOperand(2).getReg();
1805 Register RHS = MI.getOperand(3).getReg();
Petar Avramovicbd395692019-02-26 17:22:42 +00001806
1807 MIRBuilder.buildAdd(Res, LHS, RHS);
1808 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS);
1809
1810 MI.eraseFromParent();
1811 return Legalized;
1812 }
Petar Avramovicb8276f22018-12-17 12:31:07 +00001813 case G_UADDE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001814 Register Res = MI.getOperand(0).getReg();
1815 Register CarryOut = MI.getOperand(1).getReg();
1816 Register LHS = MI.getOperand(2).getReg();
1817 Register RHS = MI.getOperand(3).getReg();
1818 Register CarryIn = MI.getOperand(4).getReg();
Petar Avramovicb8276f22018-12-17 12:31:07 +00001819
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001820 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1821 Register ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001822
1823 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1824 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1825 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1826 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1827
1828 MI.eraseFromParent();
1829 return Legalized;
1830 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001831 case G_USUBO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001832 Register Res = MI.getOperand(0).getReg();
1833 Register BorrowOut = MI.getOperand(1).getReg();
1834 Register LHS = MI.getOperand(2).getReg();
1835 Register RHS = MI.getOperand(3).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001836
1837 MIRBuilder.buildSub(Res, LHS, RHS);
1838 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1839
1840 MI.eraseFromParent();
1841 return Legalized;
1842 }
1843 case G_USUBE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001844 Register Res = MI.getOperand(0).getReg();
1845 Register BorrowOut = MI.getOperand(1).getReg();
1846 Register LHS = MI.getOperand(2).getReg();
1847 Register RHS = MI.getOperand(3).getReg();
1848 Register BorrowIn = MI.getOperand(4).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001849
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001850 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1851 Register ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1852 Register LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1853 Register LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001854
1855 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1856 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1857 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1858 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1859 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1860 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1861
1862 MI.eraseFromParent();
1863 return Legalized;
1864 }
Matt Arsenault02b5ca82019-05-17 23:05:13 +00001865 case G_UITOFP:
1866 return lowerUITOFP(MI, TypeIdx, Ty);
1867 case G_SITOFP:
1868 return lowerSITOFP(MI, TypeIdx, Ty);
Matt Arsenault6f74f552019-07-01 17:18:03 +00001869 case G_SMIN:
1870 case G_SMAX:
1871 case G_UMIN:
1872 case G_UMAX:
1873 return lowerMinMax(MI, TypeIdx, Ty);
Matt Arsenaultb1843e12019-07-09 23:34:29 +00001874 case G_FCOPYSIGN:
1875 return lowerFCopySign(MI, TypeIdx, Ty);
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001876 case G_FMINNUM:
1877 case G_FMAXNUM:
1878 return lowerFMinNumMaxNum(MI);
Tim Northovercecee562016-08-26 17:46:13 +00001879 }
1880}
1881
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001882LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1883 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001884 SmallVector<Register, 2> DstRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001885
1886 unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001887 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001888 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1889 int NumParts = Size / NarrowSize;
1890 // FIXME: Don't know how to handle the situation where the small vectors
1891 // aren't all the same size yet.
1892 if (Size % NarrowSize != 0)
1893 return UnableToLegalize;
1894
1895 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001896 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001897 MIRBuilder.buildUndef(TmpReg);
1898 DstRegs.push_back(TmpReg);
1899 }
1900
1901 if (NarrowTy.isVector())
1902 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1903 else
1904 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1905
1906 MI.eraseFromParent();
1907 return Legalized;
1908}
1909
1910LegalizerHelper::LegalizeResult
1911LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
1912 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001913 const unsigned Opc = MI.getOpcode();
1914 const unsigned NumOps = MI.getNumOperands() - 1;
1915 const unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenault3018d182019-06-28 01:47:44 +00001916 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001917 const unsigned Flags = MI.getFlags();
1918 const LLT DstTy = MRI.getType(DstReg);
1919 const unsigned Size = DstTy.getSizeInBits();
1920 const int NumParts = Size / NarrowSize;
1921 const LLT EltTy = DstTy.getElementType();
1922 const unsigned EltSize = EltTy.getSizeInBits();
1923 const unsigned BitsForNumParts = NarrowSize * NumParts;
1924
1925 // Check if we have any leftovers. If we do, then only handle the case where
1926 // the leftover is one element.
1927 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001928 return UnableToLegalize;
1929
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001930 if (BitsForNumParts != Size) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001931 Register AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001932 MIRBuilder.buildUndef(AccumDstReg);
1933
1934 // Handle the pieces which evenly divide into the requested type with
1935 // extract/op/insert sequence.
1936 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
1937 SmallVector<SrcOp, 4> SrcOps;
1938 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001939 Register PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001940 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
1941 SrcOps.push_back(PartOpReg);
1942 }
1943
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001944 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001945 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1946
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001947 Register PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001948 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
1949 AccumDstReg = PartInsertReg;
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001950 }
1951
1952 // Handle the remaining element sized leftover piece.
1953 SmallVector<SrcOp, 4> SrcOps;
1954 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001955 Register PartOpReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001956 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
1957 BitsForNumParts);
1958 SrcOps.push_back(PartOpReg);
1959 }
1960
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001961 Register PartDstReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00001962 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
1963 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
1964 MI.eraseFromParent();
1965
1966 return Legalized;
1967 }
1968
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001969 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001970
1971 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
1972
1973 if (NumOps >= 2)
1974 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
1975
1976 if (NumOps >= 3)
1977 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
1978
1979 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001980 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001981
1982 if (NumOps == 1)
1983 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
1984 else if (NumOps == 2) {
1985 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
1986 } else if (NumOps == 3) {
1987 MIRBuilder.buildInstr(Opc, {DstReg},
1988 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
1989 }
1990
1991 DstRegs.push_back(DstReg);
1992 }
1993
1994 if (NarrowTy.isVector())
1995 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1996 else
1997 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1998
1999 MI.eraseFromParent();
2000 return Legalized;
2001}
2002
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002003// Handle splitting vector operations which need to have the same number of
2004// elements in each type index, but each type index may have a different element
2005// type.
2006//
2007// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
2008// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2009// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2010//
2011// Also handles some irregular breakdown cases, e.g.
2012// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
2013// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2014// s64 = G_SHL s64, s32
2015LegalizerHelper::LegalizeResult
2016LegalizerHelper::fewerElementsVectorMultiEltType(
2017 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
2018 if (TypeIdx != 0)
2019 return UnableToLegalize;
2020
2021 const LLT NarrowTy0 = NarrowTyArg;
2022 const unsigned NewNumElts =
2023 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
2024
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002025 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002026 LLT DstTy = MRI.getType(DstReg);
2027 LLT LeftoverTy0;
2028
2029 // All of the operands need to have the same number of elements, so if we can
2030 // determine a type breakdown for the result type, we can for all of the
2031 // source types.
Fangrui Songb251cc02019-07-12 14:58:15 +00002032 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0).first;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002033 if (NumParts < 0)
2034 return UnableToLegalize;
2035
2036 SmallVector<MachineInstrBuilder, 4> NewInsts;
2037
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002038 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
2039 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002040
2041 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
2042 LLT LeftoverTy;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002043 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002044 LLT SrcTyI = MRI.getType(SrcReg);
2045 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
2046 LLT LeftoverTyI;
2047
2048 // Split this operand into the requested typed registers, and any leftover
2049 // required to reproduce the original type.
2050 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
2051 LeftoverRegs))
2052 return UnableToLegalize;
2053
2054 if (I == 1) {
2055 // For the first operand, create an instruction for each part and setup
2056 // the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002057 for (Register PartReg : PartRegs) {
2058 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002059 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2060 .addDef(PartDstReg)
2061 .addUse(PartReg));
2062 DstRegs.push_back(PartDstReg);
2063 }
2064
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002065 for (Register LeftoverReg : LeftoverRegs) {
2066 Register PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002067 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2068 .addDef(PartDstReg)
2069 .addUse(LeftoverReg));
2070 LeftoverDstRegs.push_back(PartDstReg);
2071 }
2072 } else {
2073 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
2074
2075 // Add the newly created operand splits to the existing instructions. The
2076 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2077 // pieces.
2078 unsigned InstCount = 0;
2079 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
2080 NewInsts[InstCount++].addUse(PartRegs[J]);
2081 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
2082 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
2083 }
2084
2085 PartRegs.clear();
2086 LeftoverRegs.clear();
2087 }
2088
2089 // Insert the newly built operations and rebuild the result register.
2090 for (auto &MIB : NewInsts)
2091 MIRBuilder.insertInstr(MIB);
2092
2093 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
2094
2095 MI.eraseFromParent();
2096 return Legalized;
2097}
2098
Tim Northover69fa84a2016-10-14 22:18:18 +00002099LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00002100LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
2101 LLT NarrowTy) {
2102 if (TypeIdx != 0)
2103 return UnableToLegalize;
2104
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002105 Register DstReg = MI.getOperand(0).getReg();
2106 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenaultca676342019-01-25 02:36:32 +00002107 LLT DstTy = MRI.getType(DstReg);
2108 LLT SrcTy = MRI.getType(SrcReg);
2109
2110 LLT NarrowTy0 = NarrowTy;
2111 LLT NarrowTy1;
2112 unsigned NumParts;
2113
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002114 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00002115 // Uneven breakdown not handled.
2116 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
2117 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
2118 return UnableToLegalize;
2119
2120 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002121 } else {
2122 NumParts = DstTy.getNumElements();
2123 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00002124 }
2125
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002126 SmallVector<Register, 4> SrcRegs, DstRegs;
Matt Arsenaultca676342019-01-25 02:36:32 +00002127 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
2128
2129 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002130 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultca676342019-01-25 02:36:32 +00002131 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
2132 .addDef(DstReg)
2133 .addUse(SrcRegs[I]);
2134
2135 NewInst->setFlags(MI.getFlags());
2136 DstRegs.push_back(DstReg);
2137 }
2138
2139 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002140 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002141 else
2142 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2143
2144 MI.eraseFromParent();
2145 return Legalized;
2146}
2147
2148LegalizerHelper::LegalizeResult
2149LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
2150 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002151 Register DstReg = MI.getOperand(0).getReg();
2152 Register Src0Reg = MI.getOperand(2).getReg();
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002153 LLT DstTy = MRI.getType(DstReg);
2154 LLT SrcTy = MRI.getType(Src0Reg);
2155
2156 unsigned NumParts;
2157 LLT NarrowTy0, NarrowTy1;
2158
2159 if (TypeIdx == 0) {
2160 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2161 unsigned OldElts = DstTy.getNumElements();
2162
2163 NarrowTy0 = NarrowTy;
2164 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
2165 NarrowTy1 = NarrowTy.isVector() ?
2166 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
2167 SrcTy.getElementType();
2168
2169 } else {
2170 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2171 unsigned OldElts = SrcTy.getNumElements();
2172
2173 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
2174 NarrowTy.getNumElements();
2175 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
2176 DstTy.getScalarSizeInBits());
2177 NarrowTy1 = NarrowTy;
2178 }
2179
2180 // FIXME: Don't know how to handle the situation where the small vectors
2181 // aren't all the same size yet.
2182 if (NarrowTy1.isVector() &&
2183 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
2184 return UnableToLegalize;
2185
2186 CmpInst::Predicate Pred
2187 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
2188
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002189 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002190 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
2191 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
2192
2193 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002194 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002195 DstRegs.push_back(DstReg);
2196
2197 if (MI.getOpcode() == TargetOpcode::G_ICMP)
2198 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2199 else {
2200 MachineInstr *NewCmp
2201 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2202 NewCmp->setFlags(MI.getFlags());
2203 }
2204 }
2205
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002206 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00002207 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2208 else
2209 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2210
2211 MI.eraseFromParent();
2212 return Legalized;
2213}
2214
2215LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002216LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
2217 LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002218 Register DstReg = MI.getOperand(0).getReg();
2219 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002220
2221 unsigned NumParts = 0;
2222 LLT NarrowTy0, NarrowTy1;
2223
2224 LLT DstTy = MRI.getType(DstReg);
2225 LLT CondTy = MRI.getType(CondReg);
2226 unsigned Size = DstTy.getSizeInBits();
2227
2228 assert(TypeIdx == 0 || CondTy.isVector());
2229
2230 if (TypeIdx == 0) {
2231 NarrowTy0 = NarrowTy;
2232 NarrowTy1 = CondTy;
2233
2234 unsigned NarrowSize = NarrowTy0.getSizeInBits();
2235 // FIXME: Don't know how to handle the situation where the small vectors
2236 // aren't all the same size yet.
2237 if (Size % NarrowSize != 0)
2238 return UnableToLegalize;
2239
2240 NumParts = Size / NarrowSize;
2241
2242 // Need to break down the condition type
2243 if (CondTy.isVector()) {
2244 if (CondTy.getNumElements() == NumParts)
2245 NarrowTy1 = CondTy.getElementType();
2246 else
2247 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
2248 CondTy.getScalarSizeInBits());
2249 }
2250 } else {
2251 NumParts = CondTy.getNumElements();
2252 if (NarrowTy.isVector()) {
2253 // TODO: Handle uneven breakdown.
2254 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
2255 return UnableToLegalize;
2256
2257 return UnableToLegalize;
2258 } else {
2259 NarrowTy0 = DstTy.getElementType();
2260 NarrowTy1 = NarrowTy;
2261 }
2262 }
2263
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002264 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002265 if (CondTy.isVector())
2266 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2267
2268 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2269 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2270
2271 for (unsigned i = 0; i < NumParts; ++i) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002272 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002273 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2274 Src1Regs[i], Src2Regs[i]);
2275 DstRegs.push_back(DstReg);
2276 }
2277
2278 if (NarrowTy0.isVector())
2279 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2280 else
2281 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2282
2283 MI.eraseFromParent();
2284 return Legalized;
2285}
2286
2287LegalizerHelper::LegalizeResult
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002288LegalizerHelper::fewerElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2289 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002290 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002291 LLT PhiTy = MRI.getType(DstReg);
2292 LLT LeftoverTy;
2293
2294 // All of the operands need to have the same number of elements, so if we can
2295 // determine a type breakdown for the result type, we can for all of the
2296 // source types.
2297 int NumParts, NumLeftover;
2298 std::tie(NumParts, NumLeftover)
2299 = getNarrowTypeBreakDown(PhiTy, NarrowTy, LeftoverTy);
2300 if (NumParts < 0)
2301 return UnableToLegalize;
2302
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002303 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002304 SmallVector<MachineInstrBuilder, 4> NewInsts;
2305
2306 const int TotalNumParts = NumParts + NumLeftover;
2307
2308 // Insert the new phis in the result block first.
2309 for (int I = 0; I != TotalNumParts; ++I) {
2310 LLT Ty = I < NumParts ? NarrowTy : LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002311 Register PartDstReg = MRI.createGenericVirtualRegister(Ty);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002312 NewInsts.push_back(MIRBuilder.buildInstr(TargetOpcode::G_PHI)
2313 .addDef(PartDstReg));
2314 if (I < NumParts)
2315 DstRegs.push_back(PartDstReg);
2316 else
2317 LeftoverDstRegs.push_back(PartDstReg);
2318 }
2319
2320 MachineBasicBlock *MBB = MI.getParent();
2321 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
2322 insertParts(DstReg, PhiTy, NarrowTy, DstRegs, LeftoverTy, LeftoverDstRegs);
2323
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002324 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002325
2326 // Insert code to extract the incoming values in each predecessor block.
2327 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2328 PartRegs.clear();
2329 LeftoverRegs.clear();
2330
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002331 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002332 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2333 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2334
2335 LLT Unused;
2336 if (!extractParts(SrcReg, PhiTy, NarrowTy, Unused, PartRegs,
2337 LeftoverRegs))
2338 return UnableToLegalize;
2339
2340 // Add the newly created operand splits to the existing instructions. The
2341 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2342 // pieces.
2343 for (int J = 0; J != TotalNumParts; ++J) {
2344 MachineInstrBuilder MIB = NewInsts[J];
2345 MIB.addUse(J < NumParts ? PartRegs[J] : LeftoverRegs[J - NumParts]);
2346 MIB.addMBB(&OpMBB);
2347 }
2348 }
2349
2350 MI.eraseFromParent();
2351 return Legalized;
2352}
2353
2354LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002355LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2356 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002357 // FIXME: Don't know how to handle secondary types yet.
2358 if (TypeIdx != 0)
2359 return UnableToLegalize;
2360
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002361 MachineMemOperand *MMO = *MI.memoperands_begin();
2362
2363 // This implementation doesn't work for atomics. Give up instead of doing
2364 // something invalid.
2365 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2366 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2367 return UnableToLegalize;
2368
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002369 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002370 Register ValReg = MI.getOperand(0).getReg();
2371 Register AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002372 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002373
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002374 int NumParts = -1;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002375 int NumLeftover = -1;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002376 LLT LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002377 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002378 if (IsLoad) {
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002379 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002380 } else {
2381 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002382 NarrowLeftoverRegs)) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002383 NumParts = NarrowRegs.size();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002384 NumLeftover = NarrowLeftoverRegs.size();
2385 }
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002386 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002387
2388 if (NumParts == -1)
2389 return UnableToLegalize;
2390
2391 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2392
2393 unsigned TotalSize = ValTy.getSizeInBits();
2394
2395 // Split the load/store into PartTy sized pieces starting at Offset. If this
2396 // is a load, return the new registers in ValRegs. For a store, each elements
2397 // of ValRegs should be PartTy. Returns the next offset that needs to be
2398 // handled.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002399 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002400 unsigned Offset) -> unsigned {
2401 MachineFunction &MF = MIRBuilder.getMF();
2402 unsigned PartSize = PartTy.getSizeInBits();
2403 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2404 Offset += PartSize, ++Idx) {
2405 unsigned ByteSize = PartSize / 8;
2406 unsigned ByteOffset = Offset / 8;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002407 Register NewAddrReg;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002408
2409 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2410
2411 MachineMemOperand *NewMMO =
2412 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2413
2414 if (IsLoad) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002415 Register Dst = MRI.createGenericVirtualRegister(PartTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002416 ValRegs.push_back(Dst);
2417 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2418 } else {
2419 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2420 }
2421 }
2422
2423 return Offset;
2424 };
2425
2426 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2427
2428 // Handle the rest of the register if this isn't an even type breakdown.
2429 if (LeftoverTy.isValid())
2430 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2431
2432 if (IsLoad) {
2433 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2434 LeftoverTy, NarrowLeftoverRegs);
2435 }
2436
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002437 MI.eraseFromParent();
2438 return Legalized;
2439}
2440
2441LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002442LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2443 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002444 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002445
2446 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002447 switch (MI.getOpcode()) {
2448 case G_IMPLICIT_DEF:
2449 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2450 case G_AND:
2451 case G_OR:
2452 case G_XOR:
2453 case G_ADD:
2454 case G_SUB:
2455 case G_MUL:
2456 case G_SMULH:
2457 case G_UMULH:
2458 case G_FADD:
2459 case G_FMUL:
2460 case G_FSUB:
2461 case G_FNEG:
2462 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002463 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002464 case G_FDIV:
2465 case G_FREM:
2466 case G_FMA:
2467 case G_FPOW:
2468 case G_FEXP:
2469 case G_FEXP2:
2470 case G_FLOG:
2471 case G_FLOG2:
2472 case G_FLOG10:
Jessica Paquetteba557672019-04-25 16:44:40 +00002473 case G_FNEARBYINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002474 case G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00002475 case G_FFLOOR:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00002476 case G_FRINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002477 case G_INTRINSIC_ROUND:
2478 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002479 case G_FCOS:
2480 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002481 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002482 case G_BSWAP:
Amara Emersonae878da2019-04-10 23:06:08 +00002483 case G_SDIV:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002484 case G_SMIN:
2485 case G_SMAX:
2486 case G_UMIN:
2487 case G_UMAX:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00002488 case G_FMINNUM:
2489 case G_FMAXNUM:
2490 case G_FMINNUM_IEEE:
2491 case G_FMAXNUM_IEEE:
2492 case G_FMINIMUM:
2493 case G_FMAXIMUM:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002494 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002495 case G_SHL:
2496 case G_LSHR:
2497 case G_ASHR:
Matt Arsenault75e30c42019-02-20 16:42:52 +00002498 case G_CTLZ:
2499 case G_CTLZ_ZERO_UNDEF:
2500 case G_CTTZ:
2501 case G_CTTZ_ZERO_UNDEF:
2502 case G_CTPOP:
Matt Arsenault1448f562019-05-17 12:19:52 +00002503 case G_FCOPYSIGN:
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002504 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002505 case G_ZEXT:
2506 case G_SEXT:
2507 case G_ANYEXT:
2508 case G_FPEXT:
2509 case G_FPTRUNC:
2510 case G_SITOFP:
2511 case G_UITOFP:
2512 case G_FPTOSI:
2513 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002514 case G_INTTOPTR:
2515 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002516 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002517 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2518 case G_ICMP:
2519 case G_FCMP:
2520 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002521 case G_SELECT:
2522 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002523 case G_PHI:
2524 return fewerElementsVectorPhi(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002525 case G_LOAD:
2526 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002527 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002528 default:
2529 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002530 }
2531}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002532
2533LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002534LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2535 const LLT HalfTy, const LLT AmtTy) {
2536
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002537 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2538 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002539 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2540
2541 if (Amt.isNullValue()) {
2542 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2543 MI.eraseFromParent();
2544 return Legalized;
2545 }
2546
2547 LLT NVT = HalfTy;
2548 unsigned NVTBits = HalfTy.getSizeInBits();
2549 unsigned VTBits = 2 * NVTBits;
2550
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002551 SrcOp Lo(Register(0)), Hi(Register(0));
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002552 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2553 if (Amt.ugt(VTBits)) {
2554 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2555 } else if (Amt.ugt(NVTBits)) {
2556 Lo = MIRBuilder.buildConstant(NVT, 0);
2557 Hi = MIRBuilder.buildShl(NVT, InL,
2558 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2559 } else if (Amt == NVTBits) {
2560 Lo = MIRBuilder.buildConstant(NVT, 0);
2561 Hi = InL;
2562 } else {
2563 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002564 auto OrLHS =
2565 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2566 auto OrRHS = MIRBuilder.buildLShr(
2567 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2568 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002569 }
2570 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2571 if (Amt.ugt(VTBits)) {
2572 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2573 } else if (Amt.ugt(NVTBits)) {
2574 Lo = MIRBuilder.buildLShr(NVT, InH,
2575 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2576 Hi = MIRBuilder.buildConstant(NVT, 0);
2577 } else if (Amt == NVTBits) {
2578 Lo = InH;
2579 Hi = MIRBuilder.buildConstant(NVT, 0);
2580 } else {
2581 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2582
2583 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2584 auto OrRHS = MIRBuilder.buildShl(
2585 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2586
2587 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2588 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2589 }
2590 } else {
2591 if (Amt.ugt(VTBits)) {
2592 Hi = Lo = MIRBuilder.buildAShr(
2593 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2594 } else if (Amt.ugt(NVTBits)) {
2595 Lo = MIRBuilder.buildAShr(NVT, InH,
2596 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2597 Hi = MIRBuilder.buildAShr(NVT, InH,
2598 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2599 } else if (Amt == NVTBits) {
2600 Lo = InH;
2601 Hi = MIRBuilder.buildAShr(NVT, InH,
2602 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2603 } else {
2604 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2605
2606 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2607 auto OrRHS = MIRBuilder.buildShl(
2608 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2609
2610 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2611 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2612 }
2613 }
2614
2615 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2616 MI.eraseFromParent();
2617
2618 return Legalized;
2619}
2620
2621// TODO: Optimize if constant shift amount.
2622LegalizerHelper::LegalizeResult
2623LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2624 LLT RequestedTy) {
2625 if (TypeIdx == 1) {
2626 Observer.changingInstr(MI);
2627 narrowScalarSrc(MI, RequestedTy, 2);
2628 Observer.changedInstr(MI);
2629 return Legalized;
2630 }
2631
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002632 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002633 LLT DstTy = MRI.getType(DstReg);
2634 if (DstTy.isVector())
2635 return UnableToLegalize;
2636
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002637 Register Amt = MI.getOperand(2).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002638 LLT ShiftAmtTy = MRI.getType(Amt);
2639 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2640 if (DstEltSize % 2 != 0)
2641 return UnableToLegalize;
2642
2643 // Ignore the input type. We can only go to exactly half the size of the
2644 // input. If that isn't small enough, the resulting pieces will be further
2645 // legalized.
2646 const unsigned NewBitSize = DstEltSize / 2;
2647 const LLT HalfTy = LLT::scalar(NewBitSize);
2648 const LLT CondTy = LLT::scalar(1);
2649
2650 if (const MachineInstr *KShiftAmt =
2651 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2652 return narrowScalarShiftByConstant(
2653 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2654 }
2655
2656 // TODO: Expand with known bits.
2657
2658 // Handle the fully general expansion by an unknown amount.
2659 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2660
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002661 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2662 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002663 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2664
2665 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2666 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2667
2668 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2669 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2670 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2671
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002672 Register ResultRegs[2];
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002673 switch (MI.getOpcode()) {
2674 case TargetOpcode::G_SHL: {
2675 // Short: ShAmt < NewBitSize
2676 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2677
2678 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2679 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2680 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2681
2682 // Long: ShAmt >= NewBitSize
2683 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2684 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2685
2686 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2687 auto Hi = MIRBuilder.buildSelect(
2688 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2689
2690 ResultRegs[0] = Lo.getReg(0);
2691 ResultRegs[1] = Hi.getReg(0);
2692 break;
2693 }
2694 case TargetOpcode::G_LSHR: {
2695 // Short: ShAmt < NewBitSize
2696 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2697
2698 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2699 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2700 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2701
2702 // Long: ShAmt >= NewBitSize
2703 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2704 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2705
2706 auto Lo = MIRBuilder.buildSelect(
2707 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2708 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2709
2710 ResultRegs[0] = Lo.getReg(0);
2711 ResultRegs[1] = Hi.getReg(0);
2712 break;
2713 }
2714 case TargetOpcode::G_ASHR: {
2715 // Short: ShAmt < NewBitSize
2716 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2717
2718 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2719 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2720 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2721
2722 // Long: ShAmt >= NewBitSize
2723
2724 // Sign of Hi part.
2725 auto HiL = MIRBuilder.buildAShr(
2726 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2727
2728 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2729
2730 auto Lo = MIRBuilder.buildSelect(
2731 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2732
2733 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2734
2735 ResultRegs[0] = Lo.getReg(0);
2736 ResultRegs[1] = Hi.getReg(0);
2737 break;
2738 }
2739 default:
2740 llvm_unreachable("not a shift");
2741 }
2742
2743 MIRBuilder.buildMerge(DstReg, ResultRegs);
2744 MI.eraseFromParent();
2745 return Legalized;
2746}
2747
2748LegalizerHelper::LegalizeResult
Matt Arsenault72bcf152019-02-28 00:01:05 +00002749LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2750 LLT MoreTy) {
2751 assert(TypeIdx == 0 && "Expecting only Idx 0");
2752
2753 Observer.changingInstr(MI);
2754 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2755 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2756 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2757 moreElementsVectorSrc(MI, MoreTy, I);
2758 }
2759
2760 MachineBasicBlock &MBB = *MI.getParent();
2761 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
2762 moreElementsVectorDst(MI, MoreTy, 0);
2763 Observer.changedInstr(MI);
2764 return Legalized;
2765}
2766
2767LegalizerHelper::LegalizeResult
Matt Arsenault18ec3822019-02-11 22:00:39 +00002768LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
2769 LLT MoreTy) {
2770 MIRBuilder.setInstr(MI);
2771 unsigned Opc = MI.getOpcode();
2772 switch (Opc) {
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002773 case TargetOpcode::G_IMPLICIT_DEF:
2774 case TargetOpcode::G_LOAD: {
2775 if (TypeIdx != 0)
2776 return UnableToLegalize;
Matt Arsenault18ec3822019-02-11 22:00:39 +00002777 Observer.changingInstr(MI);
2778 moreElementsVectorDst(MI, MoreTy, 0);
2779 Observer.changedInstr(MI);
2780 return Legalized;
2781 }
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002782 case TargetOpcode::G_STORE:
2783 if (TypeIdx != 0)
2784 return UnableToLegalize;
2785 Observer.changingInstr(MI);
2786 moreElementsVectorSrc(MI, MoreTy, 0);
2787 Observer.changedInstr(MI);
2788 return Legalized;
Matt Arsenault26b7e852019-02-19 16:30:19 +00002789 case TargetOpcode::G_AND:
2790 case TargetOpcode::G_OR:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002791 case TargetOpcode::G_XOR:
2792 case TargetOpcode::G_SMIN:
2793 case TargetOpcode::G_SMAX:
2794 case TargetOpcode::G_UMIN:
2795 case TargetOpcode::G_UMAX: {
Matt Arsenault26b7e852019-02-19 16:30:19 +00002796 Observer.changingInstr(MI);
2797 moreElementsVectorSrc(MI, MoreTy, 1);
2798 moreElementsVectorSrc(MI, MoreTy, 2);
2799 moreElementsVectorDst(MI, MoreTy, 0);
2800 Observer.changedInstr(MI);
2801 return Legalized;
2802 }
Matt Arsenault4d884272019-02-19 16:44:22 +00002803 case TargetOpcode::G_EXTRACT:
2804 if (TypeIdx != 1)
2805 return UnableToLegalize;
2806 Observer.changingInstr(MI);
2807 moreElementsVectorSrc(MI, MoreTy, 1);
2808 Observer.changedInstr(MI);
2809 return Legalized;
Matt Arsenaultc4d07552019-02-20 16:11:22 +00002810 case TargetOpcode::G_INSERT:
2811 if (TypeIdx != 0)
2812 return UnableToLegalize;
2813 Observer.changingInstr(MI);
2814 moreElementsVectorSrc(MI, MoreTy, 1);
2815 moreElementsVectorDst(MI, MoreTy, 0);
2816 Observer.changedInstr(MI);
2817 return Legalized;
Matt Arsenaultb4c95b32019-02-19 17:03:09 +00002818 case TargetOpcode::G_SELECT:
2819 if (TypeIdx != 0)
2820 return UnableToLegalize;
2821 if (MRI.getType(MI.getOperand(1).getReg()).isVector())
2822 return UnableToLegalize;
2823
2824 Observer.changingInstr(MI);
2825 moreElementsVectorSrc(MI, MoreTy, 2);
2826 moreElementsVectorSrc(MI, MoreTy, 3);
2827 moreElementsVectorDst(MI, MoreTy, 0);
2828 Observer.changedInstr(MI);
2829 return Legalized;
Matt Arsenault72bcf152019-02-28 00:01:05 +00002830 case TargetOpcode::G_PHI:
2831 return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +00002832 default:
2833 return UnableToLegalize;
2834 }
2835}
2836
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002837void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
2838 ArrayRef<Register> Src1Regs,
2839 ArrayRef<Register> Src2Regs,
Petar Avramovic0b17e592019-03-11 10:00:17 +00002840 LLT NarrowTy) {
2841 MachineIRBuilder &B = MIRBuilder;
2842 unsigned SrcParts = Src1Regs.size();
2843 unsigned DstParts = DstRegs.size();
2844
2845 unsigned DstIdx = 0; // Low bits of the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002846 Register FactorSum =
Petar Avramovic0b17e592019-03-11 10:00:17 +00002847 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
2848 DstRegs[DstIdx] = FactorSum;
2849
2850 unsigned CarrySumPrevDstIdx;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002851 SmallVector<Register, 4> Factors;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002852
2853 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
2854 // Collect low parts of muls for DstIdx.
2855 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
2856 i <= std::min(DstIdx, SrcParts - 1); ++i) {
2857 MachineInstrBuilder Mul =
2858 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
2859 Factors.push_back(Mul.getReg(0));
2860 }
2861 // Collect high parts of muls from previous DstIdx.
2862 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
2863 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
2864 MachineInstrBuilder Umulh =
2865 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
2866 Factors.push_back(Umulh.getReg(0));
2867 }
2868 // Add CarrySum from additons calculated for previous DstIdx.
2869 if (DstIdx != 1) {
2870 Factors.push_back(CarrySumPrevDstIdx);
2871 }
2872
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002873 Register CarrySum;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002874 // Add all factors and accumulate all carries into CarrySum.
2875 if (DstIdx != DstParts - 1) {
2876 MachineInstrBuilder Uaddo =
2877 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]);
2878 FactorSum = Uaddo.getReg(0);
2879 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0);
2880 for (unsigned i = 2; i < Factors.size(); ++i) {
2881 MachineInstrBuilder Uaddo =
2882 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]);
2883 FactorSum = Uaddo.getReg(0);
2884 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1));
2885 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
2886 }
2887 } else {
2888 // Since value for the next index is not calculated, neither is CarrySum.
2889 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
2890 for (unsigned i = 2; i < Factors.size(); ++i)
2891 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
2892 }
2893
2894 CarrySumPrevDstIdx = CarrySum;
2895 DstRegs[DstIdx] = FactorSum;
2896 Factors.clear();
2897 }
2898}
2899
Matt Arsenault18ec3822019-02-11 22:00:39 +00002900LegalizerHelper::LegalizeResult
Petar Avramovic0b17e592019-03-11 10:00:17 +00002901LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002902 Register DstReg = MI.getOperand(0).getReg();
2903 Register Src1 = MI.getOperand(1).getReg();
2904 Register Src2 = MI.getOperand(2).getReg();
Petar Avramovic0b17e592019-03-11 10:00:17 +00002905
Matt Arsenault211e89d2019-01-27 00:52:51 +00002906 LLT Ty = MRI.getType(DstReg);
2907 if (Ty.isVector())
2908 return UnableToLegalize;
2909
Petar Avramovic0b17e592019-03-11 10:00:17 +00002910 unsigned SrcSize = MRI.getType(Src1).getSizeInBits();
2911 unsigned DstSize = Ty.getSizeInBits();
2912 unsigned NarrowSize = NarrowTy.getSizeInBits();
2913 if (DstSize % NarrowSize != 0 || SrcSize % NarrowSize != 0)
Matt Arsenault211e89d2019-01-27 00:52:51 +00002914 return UnableToLegalize;
2915
Petar Avramovic0b17e592019-03-11 10:00:17 +00002916 unsigned NumDstParts = DstSize / NarrowSize;
2917 unsigned NumSrcParts = SrcSize / NarrowSize;
Petar Avramovic5229f472019-03-11 10:08:44 +00002918 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH;
2919 unsigned DstTmpParts = NumDstParts * (IsMulHigh ? 2 : 1);
Matt Arsenault211e89d2019-01-27 00:52:51 +00002920
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002921 SmallVector<Register, 2> Src1Parts, Src2Parts, DstTmpRegs;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002922 extractParts(Src1, NarrowTy, NumSrcParts, Src1Parts);
2923 extractParts(Src2, NarrowTy, NumSrcParts, Src2Parts);
Petar Avramovic5229f472019-03-11 10:08:44 +00002924 DstTmpRegs.resize(DstTmpParts);
2925 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
Matt Arsenault211e89d2019-01-27 00:52:51 +00002926
Petar Avramovic5229f472019-03-11 10:08:44 +00002927 // Take only high half of registers if this is high mul.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002928 ArrayRef<Register> DstRegs(
Petar Avramovic5229f472019-03-11 10:08:44 +00002929 IsMulHigh ? &DstTmpRegs[DstTmpParts / 2] : &DstTmpRegs[0], NumDstParts);
Petar Avramovic0b17e592019-03-11 10:00:17 +00002930 MIRBuilder.buildMerge(DstReg, DstRegs);
Matt Arsenault211e89d2019-01-27 00:52:51 +00002931 MI.eraseFromParent();
2932 return Legalized;
2933}
2934
Matt Arsenault1cf71362019-02-12 14:54:52 +00002935LegalizerHelper::LegalizeResult
2936LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
2937 LLT NarrowTy) {
2938 if (TypeIdx != 1)
2939 return UnableToLegalize;
2940
2941 uint64_t NarrowSize = NarrowTy.getSizeInBits();
2942
2943 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
2944 // FIXME: add support for when SizeOp1 isn't an exact multiple of
2945 // NarrowSize.
2946 if (SizeOp1 % NarrowSize != 0)
2947 return UnableToLegalize;
2948 int NumParts = SizeOp1 / NarrowSize;
2949
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002950 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00002951 SmallVector<uint64_t, 2> Indexes;
2952 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
2953
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002954 Register OpReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00002955 uint64_t OpStart = MI.getOperand(2).getImm();
2956 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
2957 for (int i = 0; i < NumParts; ++i) {
2958 unsigned SrcStart = i * NarrowSize;
2959
2960 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
2961 // No part of the extract uses this subregister, ignore it.
2962 continue;
2963 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
2964 // The entire subregister is extracted, forward the value.
2965 DstRegs.push_back(SrcRegs[i]);
2966 continue;
2967 }
2968
2969 // OpSegStart is where this destination segment would start in OpReg if it
2970 // extended infinitely in both directions.
2971 int64_t ExtractOffset;
2972 uint64_t SegSize;
2973 if (OpStart < SrcStart) {
2974 ExtractOffset = 0;
2975 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
2976 } else {
2977 ExtractOffset = OpStart - SrcStart;
2978 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
2979 }
2980
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002981 Register SegReg = SrcRegs[i];
Matt Arsenault1cf71362019-02-12 14:54:52 +00002982 if (ExtractOffset != 0 || SegSize != NarrowSize) {
2983 // A genuine extract is needed.
2984 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
2985 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
2986 }
2987
2988 DstRegs.push_back(SegReg);
2989 }
2990
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002991 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00002992 if(MRI.getType(DstReg).isVector())
2993 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2994 else
2995 MIRBuilder.buildMerge(DstReg, DstRegs);
2996 MI.eraseFromParent();
2997 return Legalized;
2998}
2999
3000LegalizerHelper::LegalizeResult
3001LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
3002 LLT NarrowTy) {
3003 // FIXME: Don't know how to handle secondary types yet.
3004 if (TypeIdx != 0)
3005 return UnableToLegalize;
3006
3007 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
3008 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3009
3010 // FIXME: add support for when SizeOp0 isn't an exact multiple of
3011 // NarrowSize.
3012 if (SizeOp0 % NarrowSize != 0)
3013 return UnableToLegalize;
3014
3015 int NumParts = SizeOp0 / NarrowSize;
3016
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003017 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003018 SmallVector<uint64_t, 2> Indexes;
3019 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3020
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003021 Register OpReg = MI.getOperand(2).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003022 uint64_t OpStart = MI.getOperand(3).getImm();
3023 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3024 for (int i = 0; i < NumParts; ++i) {
3025 unsigned DstStart = i * NarrowSize;
3026
3027 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
3028 // No part of the insert affects this subregister, forward the original.
3029 DstRegs.push_back(SrcRegs[i]);
3030 continue;
3031 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3032 // The entire subregister is defined by this insert, forward the new
3033 // value.
3034 DstRegs.push_back(OpReg);
3035 continue;
3036 }
3037
3038 // OpSegStart is where this destination segment would start in OpReg if it
3039 // extended infinitely in both directions.
3040 int64_t ExtractOffset, InsertOffset;
3041 uint64_t SegSize;
3042 if (OpStart < DstStart) {
3043 InsertOffset = 0;
3044 ExtractOffset = DstStart - OpStart;
3045 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
3046 } else {
3047 InsertOffset = OpStart - DstStart;
3048 ExtractOffset = 0;
3049 SegSize =
3050 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
3051 }
3052
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003053 Register SegReg = OpReg;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003054 if (ExtractOffset != 0 || SegSize != OpSize) {
3055 // A genuine extract is needed.
3056 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3057 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
3058 }
3059
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003060 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +00003061 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
3062 DstRegs.push_back(DstReg);
3063 }
3064
3065 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003066 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003067 if(MRI.getType(DstReg).isVector())
3068 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3069 else
3070 MIRBuilder.buildMerge(DstReg, DstRegs);
3071 MI.eraseFromParent();
3072 return Legalized;
3073}
3074
Matt Arsenault211e89d2019-01-27 00:52:51 +00003075LegalizerHelper::LegalizeResult
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003076LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx,
3077 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003078 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003079 LLT DstTy = MRI.getType(DstReg);
3080
3081 assert(MI.getNumOperands() == 3 && TypeIdx == 0);
3082
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003083 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3084 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs;
3085 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003086 LLT LeftoverTy;
3087 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
3088 Src0Regs, Src0LeftoverRegs))
3089 return UnableToLegalize;
3090
3091 LLT Unused;
3092 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
3093 Src1Regs, Src1LeftoverRegs))
3094 llvm_unreachable("inconsistent extractParts result");
3095
3096 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3097 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
3098 {Src0Regs[I], Src1Regs[I]});
3099 DstRegs.push_back(Inst->getOperand(0).getReg());
3100 }
3101
3102 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3103 auto Inst = MIRBuilder.buildInstr(
3104 MI.getOpcode(),
3105 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
3106 DstLeftoverRegs.push_back(Inst->getOperand(0).getReg());
3107 }
3108
3109 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3110 LeftoverTy, DstLeftoverRegs);
3111
3112 MI.eraseFromParent();
3113 return Legalized;
3114}
3115
3116LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00003117LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
3118 LLT NarrowTy) {
3119 if (TypeIdx != 0)
3120 return UnableToLegalize;
3121
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003122 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003123 LLT CondTy = MRI.getType(CondReg);
3124 if (CondTy.isVector()) // TODO: Handle vselect
3125 return UnableToLegalize;
3126
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003127 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003128 LLT DstTy = MRI.getType(DstReg);
3129
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003130 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3131 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
3132 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs;
Matt Arsenault81511e52019-02-05 00:13:44 +00003133 LLT LeftoverTy;
3134 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
3135 Src1Regs, Src1LeftoverRegs))
3136 return UnableToLegalize;
3137
3138 LLT Unused;
3139 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
3140 Src2Regs, Src2LeftoverRegs))
3141 llvm_unreachable("inconsistent extractParts result");
3142
3143 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3144 auto Select = MIRBuilder.buildSelect(NarrowTy,
3145 CondReg, Src1Regs[I], Src2Regs[I]);
3146 DstRegs.push_back(Select->getOperand(0).getReg());
3147 }
3148
3149 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3150 auto Select = MIRBuilder.buildSelect(
3151 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
3152 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
3153 }
3154
3155 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3156 LeftoverTy, DstLeftoverRegs);
3157
3158 MI.eraseFromParent();
3159 return Legalized;
3160}
3161
3162LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003163LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3164 unsigned Opc = MI.getOpcode();
3165 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00003166 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003167 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00003168 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003169 };
3170 switch (Opc) {
3171 default:
3172 return UnableToLegalize;
3173 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
3174 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003175 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003176 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003177 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003178 return Legalized;
3179 }
3180 case TargetOpcode::G_CTLZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003181 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003182 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003183 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00003184 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003185 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
3186 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003187 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3188 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3189 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3190 SrcReg, MIBZero);
3191 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3192 MIBCtlzZU);
3193 MI.eraseFromParent();
3194 return Legalized;
3195 }
3196 // for now, we do this:
3197 // NewLen = NextPowerOf2(Len);
3198 // x = x | (x >> 1);
3199 // x = x | (x >> 2);
3200 // ...
3201 // x = x | (x >>16);
3202 // x = x | (x >>32); // for 64-bit input
3203 // Upto NewLen/2
3204 // return Len - popcount(x);
3205 //
3206 // Ref: "Hacker's Delight" by Henry Warren
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003207 Register Op = SrcReg;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003208 unsigned NewLen = PowerOf2Ceil(Len);
3209 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
3210 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
3211 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003212 TargetOpcode::G_OR, {Ty},
3213 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
3214 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003215 Op = MIBOp->getOperand(0).getReg();
3216 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003217 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
3218 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3219 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003220 MI.eraseFromParent();
3221 return Legalized;
3222 }
3223 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
3224 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003225 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003226 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003227 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003228 return Legalized;
3229 }
3230 case TargetOpcode::G_CTTZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003231 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003232 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003233 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003234 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
3235 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003236 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
3237 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003238 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3239 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3240 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3241 SrcReg, MIBZero);
3242 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3243 MIBCttzZU);
3244 MI.eraseFromParent();
3245 return Legalized;
3246 }
3247 // for now, we use: { return popcount(~x & (x - 1)); }
3248 // unless the target has ctlz but not ctpop, in which case we use:
3249 // { return 32 - nlz(~x & (x-1)); }
3250 // Ref: "Hacker's Delight" by Henry Warren
3251 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
3252 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003253 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003254 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003255 TargetOpcode::G_AND, {Ty},
3256 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
3257 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003258 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
3259 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003260 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
3261 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003262 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3263 {MIBCstLen,
3264 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003265 MI.eraseFromParent();
3266 return Legalized;
3267 }
3268 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
3269 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
3270 return Legalized;
3271 }
3272 }
3273}
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003274
3275// Expand s32 = G_UITOFP s64 using bit operations to an IEEE float
3276// representation.
3277LegalizerHelper::LegalizeResult
3278LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003279 Register Dst = MI.getOperand(0).getReg();
3280 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003281 const LLT S64 = LLT::scalar(64);
3282 const LLT S32 = LLT::scalar(32);
3283 const LLT S1 = LLT::scalar(1);
3284
3285 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);
3286
3287 // unsigned cul2f(ulong u) {
3288 // uint lz = clz(u);
3289 // uint e = (u != 0) ? 127U + 63U - lz : 0;
3290 // u = (u << lz) & 0x7fffffffffffffffUL;
3291 // ulong t = u & 0xffffffffffUL;
3292 // uint v = (e << 23) | (uint)(u >> 40);
3293 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
3294 // return as_float(v + r);
3295 // }
3296
3297 auto Zero32 = MIRBuilder.buildConstant(S32, 0);
3298 auto Zero64 = MIRBuilder.buildConstant(S64, 0);
3299
3300 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src);
3301
3302 auto K = MIRBuilder.buildConstant(S32, 127U + 63U);
3303 auto Sub = MIRBuilder.buildSub(S32, K, LZ);
3304
3305 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64);
3306 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32);
3307
3308 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1);
3309 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ);
3310
3311 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0);
3312
3313 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL);
3314 auto T = MIRBuilder.buildAnd(S64, U, Mask1);
3315
3316 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40));
3317 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23));
3318 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl));
3319
3320 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL);
3321 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C);
3322 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C);
3323 auto One = MIRBuilder.buildConstant(S32, 1);
3324
3325 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One);
3326 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32);
3327 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0);
3328 MIRBuilder.buildAdd(Dst, V, R);
3329
3330 return Legalized;
3331}
3332
3333LegalizerHelper::LegalizeResult
3334LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003335 Register Dst = MI.getOperand(0).getReg();
3336 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003337 LLT DstTy = MRI.getType(Dst);
3338 LLT SrcTy = MRI.getType(Src);
3339
3340 if (SrcTy != LLT::scalar(64))
3341 return UnableToLegalize;
3342
3343 if (DstTy == LLT::scalar(32)) {
3344 // TODO: SelectionDAG has several alternative expansions to port which may
3345 // be more reasonble depending on the available instructions. If a target
3346 // has sitofp, does not have CTLZ, or can efficiently use f64 as an
3347 // intermediate type, this is probably worse.
3348 return lowerU64ToF32BitOps(MI);
3349 }
3350
3351 return UnableToLegalize;
3352}
3353
3354LegalizerHelper::LegalizeResult
3355LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003356 Register Dst = MI.getOperand(0).getReg();
3357 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003358 LLT DstTy = MRI.getType(Dst);
3359 LLT SrcTy = MRI.getType(Src);
3360
3361 const LLT S64 = LLT::scalar(64);
3362 const LLT S32 = LLT::scalar(32);
3363 const LLT S1 = LLT::scalar(1);
3364
3365 if (SrcTy != S64)
3366 return UnableToLegalize;
3367
3368 if (DstTy == S32) {
3369 // signed cl2f(long l) {
3370 // long s = l >> 63;
3371 // float r = cul2f((l + s) ^ s);
3372 // return s ? -r : r;
3373 // }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003374 Register L = Src;
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003375 auto SignBit = MIRBuilder.buildConstant(S64, 63);
3376 auto S = MIRBuilder.buildAShr(S64, L, SignBit);
3377
3378 auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
3379 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
3380 auto R = MIRBuilder.buildUITOFP(S32, Xor);
3381
3382 auto RNeg = MIRBuilder.buildFNeg(S32, R);
3383 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
3384 MIRBuilder.buildConstant(S64, 0));
3385 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
3386 return Legalized;
3387 }
3388
3389 return UnableToLegalize;
3390}
Matt Arsenault6f74f552019-07-01 17:18:03 +00003391
3392static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
3393 switch (Opc) {
3394 case TargetOpcode::G_SMIN:
3395 return CmpInst::ICMP_SLT;
3396 case TargetOpcode::G_SMAX:
3397 return CmpInst::ICMP_SGT;
3398 case TargetOpcode::G_UMIN:
3399 return CmpInst::ICMP_ULT;
3400 case TargetOpcode::G_UMAX:
3401 return CmpInst::ICMP_UGT;
3402 default:
3403 llvm_unreachable("not in integer min/max");
3404 }
3405}
3406
3407LegalizerHelper::LegalizeResult
3408LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3409 Register Dst = MI.getOperand(0).getReg();
3410 Register Src0 = MI.getOperand(1).getReg();
3411 Register Src1 = MI.getOperand(2).getReg();
3412
3413 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
3414 LLT CmpType = MRI.getType(Dst).changeElementSize(1);
3415
3416 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
3417 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
3418
3419 MI.eraseFromParent();
3420 return Legalized;
3421}
Matt Arsenaultb1843e12019-07-09 23:34:29 +00003422
3423LegalizerHelper::LegalizeResult
3424LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3425 Register Dst = MI.getOperand(0).getReg();
3426 Register Src0 = MI.getOperand(1).getReg();
3427 Register Src1 = MI.getOperand(2).getReg();
3428
3429 const LLT Src0Ty = MRI.getType(Src0);
3430 const LLT Src1Ty = MRI.getType(Src1);
3431
3432 const int Src0Size = Src0Ty.getScalarSizeInBits();
3433 const int Src1Size = Src1Ty.getScalarSizeInBits();
3434
3435 auto SignBitMask = MIRBuilder.buildConstant(
3436 Src0Ty, APInt::getSignMask(Src0Size));
3437
3438 auto NotSignBitMask = MIRBuilder.buildConstant(
3439 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
3440
3441 auto And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask);
3442 MachineInstr *Or;
3443
3444 if (Src0Ty == Src1Ty) {
3445 auto And1 = MIRBuilder.buildAnd(Src1Ty, Src0, SignBitMask);
3446 Or = MIRBuilder.buildOr(Dst, And0, And1);
3447 } else if (Src0Size > Src1Size) {
3448 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
3449 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
3450 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
3451 auto And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask);
3452 Or = MIRBuilder.buildOr(Dst, And0, And1);
3453 } else {
3454 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
3455 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
3456 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
3457 auto And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask);
3458 Or = MIRBuilder.buildOr(Dst, And0, And1);
3459 }
3460
3461 // Be careful about setting nsz/nnan/ninf on every instruction, since the
3462 // constants are a nan and -0.0, but the final result should preserve
3463 // everything.
3464 if (unsigned Flags = MI.getFlags())
3465 Or->setFlags(Flags);
3466
3467 MI.eraseFromParent();
3468 return Legalized;
3469}
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00003470
3471LegalizerHelper::LegalizeResult
3472LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
3473 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ?
3474 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE;
3475
3476 Register Dst = MI.getOperand(0).getReg();
3477 Register Src0 = MI.getOperand(1).getReg();
3478 Register Src1 = MI.getOperand(2).getReg();
3479 LLT Ty = MRI.getType(Dst);
3480
3481 if (!MI.getFlag(MachineInstr::FmNoNans)) {
3482 // Insert canonicalizes if it's possible we need to quiet to get correct
3483 // sNaN behavior.
3484
3485 // Note this must be done here, and not as an optimization combine in the
3486 // absence of a dedicate quiet-snan instruction as we're using an
3487 // omni-purpose G_FCANONICALIZE.
3488 if (!isKnownNeverSNaN(Src0, MRI))
3489 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);
3490
3491 if (!isKnownNeverSNaN(Src1, MRI))
3492 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
3493 }
3494
3495 // If there are no nans, it's safe to simply replace this with the non-IEEE
3496 // version.
3497 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags());
3498 MI.eraseFromParent();
3499 return Legalized;
3500}