blob: d4bce603231275abec061a1a0f00c88268f0ea14 [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
Matt Arsenault5faa5332019-08-01 18:13:16 +0000964 Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg :
Matt Arsenault0966dd02019-07-17 20:22:44 +0000965 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);
Matt Arsenault5faa5332019-08-01 18:13:16 +0000975 else if (DstTy.isPointer())
976 MIRBuilder.buildIntToPtr(DstReg, ResultReg);
Matt Arsenault0966dd02019-07-17 20:22:44 +0000977
978 MI.eraseFromParent();
979 return Legalized;
980 }
981
982 // Unmerge the original values to the GCD type, and recombine to the next
983 // multiple greater than the original type.
984 //
985 // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6
986 // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0
987 // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1
988 // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2
989 // %10:_(s6) = G_MERGE_VALUES %4, %5, %6
990 // %11:_(s6) = G_MERGE_VALUES %7, %8, %9
991 // %12:_(s12) = G_MERGE_VALUES %10, %11
992 //
993 // Padding with undef if necessary:
994 //
995 // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6
996 // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0
997 // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1
998 // %7:_(s2) = G_IMPLICIT_DEF
999 // %8:_(s6) = G_MERGE_VALUES %3, %4, %5
1000 // %9:_(s6) = G_MERGE_VALUES %6, %7, %7
1001 // %10:_(s12) = G_MERGE_VALUES %8, %9
1002
1003 const int GCD = greatestCommonDivisor(SrcSize, WideSize);
1004 LLT GCDTy = LLT::scalar(GCD);
1005
1006 SmallVector<Register, 8> Parts;
1007 SmallVector<Register, 8> NewMergeRegs;
1008 SmallVector<Register, 8> Unmerges;
1009 LLT WideDstTy = LLT::scalar(NumMerge * WideSize);
1010
1011 // Decompose the original operands if they don't evenly divide.
1012 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001013 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenault0966dd02019-07-17 20:22:44 +00001014 if (GCD == SrcSize) {
1015 Unmerges.push_back(SrcReg);
1016 } else {
1017 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg);
1018 for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
1019 Unmerges.push_back(Unmerge.getReg(J));
1020 }
1021 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001022
Matt Arsenault0966dd02019-07-17 20:22:44 +00001023 // Pad with undef to the next size that is a multiple of the requested size.
1024 if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) {
1025 Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0);
1026 for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I)
1027 Unmerges.push_back(UndefReg);
1028 }
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001029
Matt Arsenault0966dd02019-07-17 20:22:44 +00001030 const int PartsPerGCD = WideSize / GCD;
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001031
Matt Arsenault0966dd02019-07-17 20:22:44 +00001032 // Build merges of each piece.
1033 ArrayRef<Register> Slicer(Unmerges);
1034 for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) {
1035 auto Merge = MIRBuilder.buildMerge(WideTy, Slicer.take_front(PartsPerGCD));
1036 NewMergeRegs.push_back(Merge.getReg(0));
1037 }
1038
1039 // A truncate may be necessary if the requested type doesn't evenly divide the
1040 // original result type.
1041 if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) {
1042 MIRBuilder.buildMerge(DstReg, NewMergeRegs);
1043 } else {
1044 auto FinalMerge = MIRBuilder.buildMerge(WideDstTy, NewMergeRegs);
1045 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001046 }
1047
1048 MI.eraseFromParent();
1049 return Legalized;
1050}
1051
1052LegalizerHelper::LegalizeResult
1053LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
1054 LLT WideTy) {
1055 if (TypeIdx != 0)
1056 return UnableToLegalize;
1057
1058 unsigned NumDst = MI.getNumOperands() - 1;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001059 Register SrcReg = MI.getOperand(NumDst).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001060 LLT SrcTy = MRI.getType(SrcReg);
1061 if (!SrcTy.isScalar())
1062 return UnableToLegalize;
1063
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001064 Register Dst0Reg = MI.getOperand(0).getReg();
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001065 LLT DstTy = MRI.getType(Dst0Reg);
1066 if (!DstTy.isScalar())
1067 return UnableToLegalize;
1068
1069 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits();
1070 LLT NewSrcTy = LLT::scalar(NewSrcSize);
1071 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits();
1072
1073 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg);
1074
1075 for (unsigned I = 1; I != NumDst; ++I) {
1076 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I);
1077 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt);
1078 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl);
1079 }
1080
1081 Observer.changingInstr(MI);
1082
1083 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg());
1084 for (unsigned I = 0; I != NumDst; ++I)
1085 widenScalarDst(MI, WideTy, I);
1086
1087 Observer.changedInstr(MI);
1088
1089 return Legalized;
1090}
1091
1092LegalizerHelper::LegalizeResult
Matt Arsenault1cf71362019-02-12 14:54:52 +00001093LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
1094 LLT WideTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001095 Register DstReg = MI.getOperand(0).getReg();
1096 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00001097 LLT SrcTy = MRI.getType(SrcReg);
Matt Arsenaultfbe92a52019-02-18 22:39:27 +00001098
1099 LLT DstTy = MRI.getType(DstReg);
1100 unsigned Offset = MI.getOperand(2).getImm();
1101
1102 if (TypeIdx == 0) {
1103 if (SrcTy.isVector() || DstTy.isVector())
1104 return UnableToLegalize;
1105
1106 SrcOp Src(SrcReg);
1107 if (SrcTy.isPointer()) {
1108 // Extracts from pointers can be handled only if they are really just
1109 // simple integers.
1110 const DataLayout &DL = MIRBuilder.getDataLayout();
1111 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
1112 return UnableToLegalize;
1113
1114 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
1115 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
1116 SrcTy = SrcAsIntTy;
1117 }
1118
1119 if (DstTy.isPointer())
1120 return UnableToLegalize;
1121
1122 if (Offset == 0) {
1123 // Avoid a shift in the degenerate case.
1124 MIRBuilder.buildTrunc(DstReg,
1125 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
1126 MI.eraseFromParent();
1127 return Legalized;
1128 }
1129
1130 // Do a shift in the source type.
1131 LLT ShiftTy = SrcTy;
1132 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
1133 Src = MIRBuilder.buildAnyExt(WideTy, Src);
1134 ShiftTy = WideTy;
1135 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits())
1136 return UnableToLegalize;
1137
1138 auto LShr = MIRBuilder.buildLShr(
1139 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
1140 MIRBuilder.buildTrunc(DstReg, LShr);
1141 MI.eraseFromParent();
1142 return Legalized;
1143 }
1144
Matt Arsenault8f624ab2019-04-22 15:10:42 +00001145 if (SrcTy.isScalar()) {
1146 Observer.changingInstr(MI);
1147 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1148 Observer.changedInstr(MI);
1149 return Legalized;
1150 }
1151
Matt Arsenault1cf71362019-02-12 14:54:52 +00001152 if (!SrcTy.isVector())
1153 return UnableToLegalize;
1154
Matt Arsenault1cf71362019-02-12 14:54:52 +00001155 if (DstTy != SrcTy.getElementType())
1156 return UnableToLegalize;
1157
Matt Arsenault1cf71362019-02-12 14:54:52 +00001158 if (Offset % SrcTy.getScalarSizeInBits() != 0)
1159 return UnableToLegalize;
1160
1161 Observer.changingInstr(MI);
1162 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1163
1164 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
1165 Offset);
1166 widenScalarDst(MI, WideTy.getScalarType(), 0);
1167 Observer.changedInstr(MI);
1168 return Legalized;
1169}
1170
1171LegalizerHelper::LegalizeResult
1172LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
1173 LLT WideTy) {
1174 if (TypeIdx != 0)
1175 return UnableToLegalize;
1176 Observer.changingInstr(MI);
1177 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1178 widenScalarDst(MI, WideTy);
1179 Observer.changedInstr(MI);
1180 return Legalized;
1181}
1182
1183LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00001184LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
Tim Northover3c73e362016-08-23 18:20:09 +00001185 MIRBuilder.setInstr(MI);
1186
Tim Northover32335812016-08-04 18:35:11 +00001187 switch (MI.getOpcode()) {
1188 default:
1189 return UnableToLegalize;
Matt Arsenault1cf71362019-02-12 14:54:52 +00001190 case TargetOpcode::G_EXTRACT:
1191 return widenScalarExtract(MI, TypeIdx, WideTy);
1192 case TargetOpcode::G_INSERT:
1193 return widenScalarInsert(MI, TypeIdx, WideTy);
Matt Arsenault888aa5d2019-02-03 00:07:33 +00001194 case TargetOpcode::G_MERGE_VALUES:
1195 return widenScalarMergeValues(MI, TypeIdx, WideTy);
1196 case TargetOpcode::G_UNMERGE_VALUES:
1197 return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001198 case TargetOpcode::G_UADDO:
1199 case TargetOpcode::G_USUBO: {
1200 if (TypeIdx == 1)
1201 return UnableToLegalize; // TODO
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001202 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1203 {MI.getOperand(2).getReg()});
1204 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy},
1205 {MI.getOperand(3).getReg()});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001206 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO
1207 ? TargetOpcode::G_ADD
1208 : TargetOpcode::G_SUB;
1209 // Do the arithmetic in the larger type.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001210 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001211 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
1212 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits());
1213 auto AndOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001214 TargetOpcode::G_AND, {WideTy},
1215 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())});
Aditya Nandakumar6d47a412018-08-29 03:17:08 +00001216 // There is no overflow if the AndOp is the same as NewOp.
1217 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp,
1218 AndOp);
1219 // Now trunc the NewOp to the original result.
1220 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp);
1221 MI.eraseFromParent();
1222 return Legalized;
1223 }
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001224 case TargetOpcode::G_CTTZ:
1225 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1226 case TargetOpcode::G_CTLZ:
1227 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1228 case TargetOpcode::G_CTPOP: {
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001229 if (TypeIdx == 0) {
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001230 Observer.changingInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001231 widenScalarDst(MI, WideTy, 0);
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001232 Observer.changedInstr(MI);
Matt Arsenaultd5684f72019-01-31 02:09:57 +00001233 return Legalized;
1234 }
1235
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001236 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001237
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001238 // First ZEXT the input.
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001239 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg);
1240 LLT CurTy = MRI.getType(SrcReg);
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001241 if (MI.getOpcode() == TargetOpcode::G_CTTZ) {
1242 // The count is the same in the larger type except if the original
1243 // value was zero. This can be handled by setting the bit just off
1244 // the top of the original type.
1245 auto TopBit =
1246 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits());
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001247 MIBSrc = MIRBuilder.buildOr(
1248 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001249 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001250
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001251 // Perform the operation at the larger size.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001252 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001253 // This is already the correct result for CTPOP and CTTZs
1254 if (MI.getOpcode() == TargetOpcode::G_CTLZ ||
1255 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
1256 // The correct result is NewOp - (Difference in widety and current ty).
1257 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits();
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00001258 MIBNewOp = MIRBuilder.buildInstr(
1259 TargetOpcode::G_SUB, {WideTy},
1260 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)});
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001261 }
Matt Arsenault3d6a49b2019-02-04 22:26:33 +00001262
1263 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
1264 MI.eraseFromParent();
Aditya Nandakumarc1061832018-08-22 17:59:18 +00001265 return Legalized;
1266 }
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001267 case TargetOpcode::G_BSWAP: {
1268 Observer.changingInstr(MI);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001269 Register DstReg = MI.getOperand(0).getReg();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001270
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001271 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
1272 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
1273 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00001274 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1275
1276 MI.getOperand(0).setReg(DstExt);
1277
1278 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1279
1280 LLT Ty = MRI.getType(DstReg);
1281 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
1282 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
1283 MIRBuilder.buildInstr(TargetOpcode::G_LSHR)
1284 .addDef(ShrReg)
1285 .addUse(DstExt)
1286 .addUse(ShiftAmtReg);
1287
1288 MIRBuilder.buildTrunc(DstReg, ShrReg);
1289 Observer.changedInstr(MI);
1290 return Legalized;
1291 }
Tim Northover61c16142016-08-04 21:39:49 +00001292 case TargetOpcode::G_ADD:
1293 case TargetOpcode::G_AND:
1294 case TargetOpcode::G_MUL:
1295 case TargetOpcode::G_OR:
1296 case TargetOpcode::G_XOR:
Justin Bognerddb80ae2017-01-19 07:51:17 +00001297 case TargetOpcode::G_SUB:
Matt Arsenault1cf71362019-02-12 14:54:52 +00001298 // Perform operation at larger width (any extension is fines here, high bits
Tim Northover32335812016-08-04 18:35:11 +00001299 // don't affect the result) and then truncate the result back to the
1300 // original type.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001301 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001302 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1303 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1304 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001305 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001306 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001307
Roman Tereshin6d266382018-05-09 21:43:30 +00001308 case TargetOpcode::G_SHL:
Matt Arsenault012ecbb2019-05-16 04:08:46 +00001309 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001310
1311 if (TypeIdx == 0) {
1312 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
1313 widenScalarDst(MI, WideTy);
1314 } else {
1315 assert(TypeIdx == 1);
1316 // The "number of bits to shift" operand must preserve its value as an
1317 // unsigned integer:
1318 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1319 }
1320
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001321 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001322 return Legalized;
1323
Tim Northover7a753d92016-08-26 17:46:06 +00001324 case TargetOpcode::G_SDIV:
Roman Tereshin27bba442018-05-09 01:43:12 +00001325 case TargetOpcode::G_SREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001326 case TargetOpcode::G_SMIN:
1327 case TargetOpcode::G_SMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001328 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001329 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
1330 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
1331 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001332 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001333 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001334
Roman Tereshin6d266382018-05-09 21:43:30 +00001335 case TargetOpcode::G_ASHR:
Matt Arsenault30989e42019-01-22 21:42:11 +00001336 case TargetOpcode::G_LSHR:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001337 Observer.changingInstr(MI);
Matt Arsenault30989e42019-01-22 21:42:11 +00001338
1339 if (TypeIdx == 0) {
1340 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ?
1341 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
1342
1343 widenScalarSrc(MI, WideTy, 1, CvtOp);
1344 widenScalarDst(MI, WideTy);
1345 } else {
1346 assert(TypeIdx == 1);
1347 // The "number of bits to shift" operand must preserve its value as an
1348 // unsigned integer:
1349 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1350 }
1351
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001352 Observer.changedInstr(MI);
Roman Tereshin6d266382018-05-09 21:43:30 +00001353 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001354 case TargetOpcode::G_UDIV:
1355 case TargetOpcode::G_UREM:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00001356 case TargetOpcode::G_UMIN:
1357 case TargetOpcode::G_UMAX:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001358 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001359 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1360 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
1361 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001362 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001363 return Legalized;
1364
1365 case TargetOpcode::G_SELECT:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001366 Observer.changingInstr(MI);
Petar Avramovic09dff332018-12-25 14:42:30 +00001367 if (TypeIdx == 0) {
1368 // Perform operation at larger width (any extension is fine here, high
1369 // bits don't affect the result) and then truncate the result back to the
1370 // original type.
1371 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
1372 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
1373 widenScalarDst(MI, WideTy);
1374 } else {
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001375 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
Petar Avramovic09dff332018-12-25 14:42:30 +00001376 // Explicit extension is required here since high bits affect the result.
Matt Arsenault6d8e1b42019-01-30 02:57:43 +00001377 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
Petar Avramovic09dff332018-12-25 14:42:30 +00001378 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001379 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001380 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001381
Ahmed Bougachab6137062017-01-23 21:10:14 +00001382 case TargetOpcode::G_FPTOSI:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001383 case TargetOpcode::G_FPTOUI:
Ahmed Bougachab6137062017-01-23 21:10:14 +00001384 if (TypeIdx != 0)
1385 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001386 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001387 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001388 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001389 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001390
Ahmed Bougachad2948232017-01-20 01:37:24 +00001391 case TargetOpcode::G_SITOFP:
Ahmed Bougachad2948232017-01-20 01:37:24 +00001392 if (TypeIdx != 1)
1393 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001394 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001395 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001396 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001397 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001398
1399 case TargetOpcode::G_UITOFP:
1400 if (TypeIdx != 1)
1401 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001402 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001403 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001404 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001405 return Legalized;
1406
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001407 case TargetOpcode::G_LOAD:
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001408 case TargetOpcode::G_SEXTLOAD:
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001409 case TargetOpcode::G_ZEXTLOAD:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001410 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001411 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001412 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001413 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001414
Tim Northover3c73e362016-08-23 18:20:09 +00001415 case TargetOpcode::G_STORE: {
Matt Arsenault92c50012019-01-30 02:04:31 +00001416 if (TypeIdx != 0)
1417 return UnableToLegalize;
1418
1419 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1420 if (!isPowerOf2_32(Ty.getSizeInBits()))
Tim Northover548feee2017-03-21 22:22:05 +00001421 return UnableToLegalize;
1422
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001423 Observer.changingInstr(MI);
Matt Arsenault92c50012019-01-30 02:04:31 +00001424
1425 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
1426 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
1427 widenScalarSrc(MI, WideTy, 0, ExtType);
1428
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001429 Observer.changedInstr(MI);
Tim Northover3c73e362016-08-23 18:20:09 +00001430 return Legalized;
1431 }
Tim Northoverea904f92016-08-19 22:40:00 +00001432 case TargetOpcode::G_CONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001433 MachineOperand &SrcMO = MI.getOperand(1);
1434 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
1435 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001436 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001437 SrcMO.setCImm(ConstantInt::get(Ctx, Val));
1438
1439 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001440 Observer.changedInstr(MI);
Tim Northoverea904f92016-08-19 22:40:00 +00001441 return Legalized;
1442 }
Tim Northovera11be042016-08-19 22:40:08 +00001443 case TargetOpcode::G_FCONSTANT: {
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001444 MachineOperand &SrcMO = MI.getOperand(1);
Amara Emerson77a5c962018-01-27 07:07:20 +00001445 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001446 APFloat Val = SrcMO.getFPImm()->getValueAPF();
Amara Emerson77a5c962018-01-27 07:07:20 +00001447 bool LosesInfo;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001448 switch (WideTy.getSizeInBits()) {
1449 case 32:
Matt Arsenault996c6662019-02-12 14:54:54 +00001450 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
1451 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001452 break;
1453 case 64:
Matt Arsenault996c6662019-02-12 14:54:54 +00001454 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
1455 &LosesInfo);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001456 break;
1457 default:
Matt Arsenault996c6662019-02-12 14:54:54 +00001458 return UnableToLegalize;
Tim Northover6cd4b232016-08-23 21:01:26 +00001459 }
Matt Arsenault996c6662019-02-12 14:54:54 +00001460
1461 assert(!LosesInfo && "extend should always be lossless");
1462
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001463 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001464 SrcMO.setFPImm(ConstantFP::get(Ctx, Val));
1465
1466 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001467 Observer.changedInstr(MI);
Roman Tereshin25cbfe62018-05-08 22:53:09 +00001468 return Legalized;
Roman Tereshin27bba442018-05-09 01:43:12 +00001469 }
Matt Arsenaultbefee402019-01-09 07:34:14 +00001470 case TargetOpcode::G_IMPLICIT_DEF: {
1471 Observer.changingInstr(MI);
1472 widenScalarDst(MI, WideTy);
1473 Observer.changedInstr(MI);
1474 return Legalized;
1475 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001476 case TargetOpcode::G_BRCOND:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001477 Observer.changingInstr(MI);
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +00001478 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001479 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001480 return Legalized;
1481
1482 case TargetOpcode::G_FCMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001483 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001484 if (TypeIdx == 0)
1485 widenScalarDst(MI, WideTy);
1486 else {
1487 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT);
1488 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT);
Roman Tereshin27bba442018-05-09 01:43:12 +00001489 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001490 Observer.changedInstr(MI);
Roman Tereshin27bba442018-05-09 01:43:12 +00001491 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001492
1493 case TargetOpcode::G_ICMP:
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001494 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001495 if (TypeIdx == 0)
1496 widenScalarDst(MI, WideTy);
1497 else {
1498 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>(
1499 MI.getOperand(1).getPredicate()))
1500 ? TargetOpcode::G_SEXT
1501 : TargetOpcode::G_ZEXT;
1502 widenScalarSrc(MI, WideTy, 2, ExtOpcode);
1503 widenScalarSrc(MI, WideTy, 3, ExtOpcode);
1504 }
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001505 Observer.changedInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001506 return Legalized;
1507
1508 case TargetOpcode::G_GEP:
Tim Northover22d82cf2016-09-15 11:02:19 +00001509 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001510 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001511 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001512 Observer.changedInstr(MI);
Tim Northover22d82cf2016-09-15 11:02:19 +00001513 return Legalized;
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001514
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001515 case TargetOpcode::G_PHI: {
1516 assert(TypeIdx == 0 && "Expecting only Idx 0");
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001517
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001518 Observer.changingInstr(MI);
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001519 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
1520 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
1521 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
1522 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001523 }
Roman Tereshind5fa9fd2018-05-09 17:28:18 +00001524
1525 MachineBasicBlock &MBB = *MI.getParent();
1526 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
1527 widenScalarDst(MI, WideTy);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001528 Observer.changedInstr(MI);
Aditya Nandakumar892979e2017-08-25 04:57:27 +00001529 return Legalized;
1530 }
Matt Arsenault63786292019-01-22 20:38:15 +00001531 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1532 if (TypeIdx == 0) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001533 Register VecReg = MI.getOperand(1).getReg();
Matt Arsenault63786292019-01-22 20:38:15 +00001534 LLT VecTy = MRI.getType(VecReg);
1535 Observer.changingInstr(MI);
1536
1537 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(),
1538 WideTy.getSizeInBits()),
1539 1, TargetOpcode::G_SEXT);
1540
1541 widenScalarDst(MI, WideTy, 0);
1542 Observer.changedInstr(MI);
1543 return Legalized;
1544 }
1545
Amara Emersoncbd86d82018-10-25 14:04:54 +00001546 if (TypeIdx != 2)
1547 return UnableToLegalize;
Daniel Sandersd001e0e2018-12-12 23:48:13 +00001548 Observer.changingInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001549 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00001550 Observer.changedInstr(MI);
Amara Emersoncbd86d82018-10-25 14:04:54 +00001551 return Legalized;
Matt Arsenault63786292019-01-22 20:38:15 +00001552 }
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001553 case TargetOpcode::G_FADD:
1554 case TargetOpcode::G_FMUL:
1555 case TargetOpcode::G_FSUB:
1556 case TargetOpcode::G_FMA:
1557 case TargetOpcode::G_FNEG:
1558 case TargetOpcode::G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00001559 case TargetOpcode::G_FCANONICALIZE:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001560 case TargetOpcode::G_FMINNUM:
1561 case TargetOpcode::G_FMAXNUM:
1562 case TargetOpcode::G_FMINNUM_IEEE:
1563 case TargetOpcode::G_FMAXNUM_IEEE:
1564 case TargetOpcode::G_FMINIMUM:
1565 case TargetOpcode::G_FMAXIMUM:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001566 case TargetOpcode::G_FDIV:
1567 case TargetOpcode::G_FREM:
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001568 case TargetOpcode::G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00001569 case TargetOpcode::G_FFLOOR:
Jessica Paquette7db82d72019-01-28 18:34:18 +00001570 case TargetOpcode::G_FCOS:
1571 case TargetOpcode::G_FSIN:
Jessica Paquettec49428a2019-01-28 19:53:14 +00001572 case TargetOpcode::G_FLOG10:
Jessica Paquette2d73ecd2019-01-28 21:27:23 +00001573 case TargetOpcode::G_FLOG:
Jessica Paquette0154bd12019-01-30 21:16:04 +00001574 case TargetOpcode::G_FLOG2:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00001575 case TargetOpcode::G_FRINT:
Jessica Paquetteba557672019-04-25 16:44:40 +00001576 case TargetOpcode::G_FNEARBYINT:
Jessica Paquette22457f82019-01-30 21:03:52 +00001577 case TargetOpcode::G_FSQRT:
Jessica Paquette84bedac2019-01-30 23:46:15 +00001578 case TargetOpcode::G_FEXP:
Jessica Paquettee7941212019-04-03 16:58:32 +00001579 case TargetOpcode::G_FEXP2:
Jessica Paquettedfd87f62019-04-19 16:28:08 +00001580 case TargetOpcode::G_FPOW:
Jessica Paquette56342642019-04-23 18:20:44 +00001581 case TargetOpcode::G_INTRINSIC_TRUNC:
Jessica Paquette3cc6d1f2019-04-23 21:11:57 +00001582 case TargetOpcode::G_INTRINSIC_ROUND:
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001583 assert(TypeIdx == 0);
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001584 Observer.changingInstr(MI);
Matt Arsenault745fd9f2019-01-20 19:10:31 +00001585
1586 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
1587 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT);
1588
Jessica Paquette453ab1d2018-12-21 17:05:26 +00001589 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC);
1590 Observer.changedInstr(MI);
1591 return Legalized;
Matt Arsenaultcbaada62019-02-02 23:29:55 +00001592 case TargetOpcode::G_INTTOPTR:
1593 if (TypeIdx != 1)
1594 return UnableToLegalize;
1595
1596 Observer.changingInstr(MI);
1597 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
1598 Observer.changedInstr(MI);
1599 return Legalized;
1600 case TargetOpcode::G_PTRTOINT:
1601 if (TypeIdx != 0)
1602 return UnableToLegalize;
1603
1604 Observer.changingInstr(MI);
1605 widenScalarDst(MI, WideTy, 0);
1606 Observer.changedInstr(MI);
1607 return Legalized;
Matt Arsenaultbd791b52019-07-08 13:48:06 +00001608 case TargetOpcode::G_BUILD_VECTOR: {
1609 Observer.changingInstr(MI);
1610
1611 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType();
1612 for (int I = 1, E = MI.getNumOperands(); I != E; ++I)
1613 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT);
1614
1615 // Avoid changing the result vector type if the source element type was
1616 // requested.
1617 if (TypeIdx == 1) {
1618 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
1619 MI.setDesc(TII.get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
1620 } else {
1621 widenScalarDst(MI, WideTy, 0);
1622 }
1623
1624 Observer.changedInstr(MI);
1625 return Legalized;
1626 }
Tim Northover32335812016-08-04 18:35:11 +00001627 }
Tim Northover33b07d62016-07-22 20:03:43 +00001628}
1629
Tim Northover69fa84a2016-10-14 22:18:18 +00001630LegalizerHelper::LegalizeResult
1631LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Tim Northovercecee562016-08-26 17:46:13 +00001632 using namespace TargetOpcode;
Tim Northovercecee562016-08-26 17:46:13 +00001633 MIRBuilder.setInstr(MI);
1634
1635 switch(MI.getOpcode()) {
1636 default:
1637 return UnableToLegalize;
1638 case TargetOpcode::G_SREM:
1639 case TargetOpcode::G_UREM: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001640 Register QuotReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001641 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
Tim Northovercecee562016-08-26 17:46:13 +00001642 .addDef(QuotReg)
1643 .addUse(MI.getOperand(1).getReg())
1644 .addUse(MI.getOperand(2).getReg());
1645
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001646 Register ProdReg = MRI.createGenericVirtualRegister(Ty);
Tim Northover0f140c72016-09-09 11:46:34 +00001647 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
1648 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
1649 ProdReg);
Tim Northovercecee562016-08-26 17:46:13 +00001650 MI.eraseFromParent();
1651 return Legalized;
1652 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001653 case TargetOpcode::G_SMULO:
1654 case TargetOpcode::G_UMULO: {
1655 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
1656 // result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001657 Register Res = MI.getOperand(0).getReg();
1658 Register Overflow = MI.getOperand(1).getReg();
1659 Register LHS = MI.getOperand(2).getReg();
1660 Register RHS = MI.getOperand(3).getReg();
Tim Northover0a9b2792017-02-08 21:22:15 +00001661
1662 MIRBuilder.buildMul(Res, LHS, RHS);
1663
1664 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
1665 ? TargetOpcode::G_SMULH
1666 : TargetOpcode::G_UMULH;
1667
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001668 Register HiPart = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001669 MIRBuilder.buildInstr(Opcode)
1670 .addDef(HiPart)
1671 .addUse(LHS)
1672 .addUse(RHS);
1673
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001674 Register Zero = MRI.createGenericVirtualRegister(Ty);
Tim Northover0a9b2792017-02-08 21:22:15 +00001675 MIRBuilder.buildConstant(Zero, 0);
Amara Emerson9de62132018-01-03 04:56:56 +00001676
1677 // For *signed* multiply, overflow is detected by checking:
1678 // (hi != (lo >> bitwidth-1))
1679 if (Opcode == TargetOpcode::G_SMULH) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001680 Register Shifted = MRI.createGenericVirtualRegister(Ty);
1681 Register ShiftAmt = MRI.createGenericVirtualRegister(Ty);
Amara Emerson9de62132018-01-03 04:56:56 +00001682 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
1683 MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
1684 .addDef(Shifted)
1685 .addUse(Res)
1686 .addUse(ShiftAmt);
1687 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
1688 } else {
1689 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
1690 }
Tim Northover0a9b2792017-02-08 21:22:15 +00001691 MI.eraseFromParent();
1692 return Legalized;
1693 }
Volkan Keles5698b2a2017-03-08 18:09:14 +00001694 case TargetOpcode::G_FNEG: {
1695 // TODO: Handle vector types once we are able to
1696 // represent them.
1697 if (Ty.isVector())
1698 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001699 Register Res = MI.getOperand(0).getReg();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001700 Type *ZeroTy;
Matthias Braunf1caa282017-12-15 22:22:58 +00001701 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
Volkan Keles5698b2a2017-03-08 18:09:14 +00001702 switch (Ty.getSizeInBits()) {
1703 case 16:
1704 ZeroTy = Type::getHalfTy(Ctx);
1705 break;
1706 case 32:
1707 ZeroTy = Type::getFloatTy(Ctx);
1708 break;
1709 case 64:
1710 ZeroTy = Type::getDoubleTy(Ctx);
1711 break;
Amara Emersonb6ddbef2017-12-19 17:21:35 +00001712 case 128:
1713 ZeroTy = Type::getFP128Ty(Ctx);
1714 break;
Volkan Keles5698b2a2017-03-08 18:09:14 +00001715 default:
1716 llvm_unreachable("unexpected floating-point type");
1717 }
1718 ConstantFP &ZeroForNegation =
1719 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
Volkan Keles02bb1742018-02-14 19:58:36 +00001720 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001721 Register SubByReg = MI.getOperand(1).getReg();
1722 Register ZeroReg = Zero->getOperand(0).getReg();
Michael Bergd573aa02019-04-18 18:48:57 +00001723 MIRBuilder.buildInstr(TargetOpcode::G_FSUB, {Res}, {ZeroReg, SubByReg},
Matt Arsenault5a321b82019-06-17 23:48:43 +00001724 MI.getFlags());
Volkan Keles5698b2a2017-03-08 18:09:14 +00001725 MI.eraseFromParent();
1726 return Legalized;
1727 }
Volkan Keles225921a2017-03-10 21:25:09 +00001728 case TargetOpcode::G_FSUB: {
1729 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
1730 // First, check if G_FNEG is marked as Lower. If so, we may
1731 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
Daniel Sanders9ade5592018-01-29 17:37:29 +00001732 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
Volkan Keles225921a2017-03-10 21:25:09 +00001733 return UnableToLegalize;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001734 Register Res = MI.getOperand(0).getReg();
1735 Register LHS = MI.getOperand(1).getReg();
1736 Register RHS = MI.getOperand(2).getReg();
1737 Register Neg = MRI.createGenericVirtualRegister(Ty);
Volkan Keles225921a2017-03-10 21:25:09 +00001738 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
Michael Bergd573aa02019-04-18 18:48:57 +00001739 MIRBuilder.buildInstr(TargetOpcode::G_FADD, {Res}, {LHS, Neg}, MI.getFlags());
Volkan Keles225921a2017-03-10 21:25:09 +00001740 MI.eraseFromParent();
1741 return Legalized;
1742 }
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001743 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001744 Register OldValRes = MI.getOperand(0).getReg();
1745 Register SuccessRes = MI.getOperand(1).getReg();
1746 Register Addr = MI.getOperand(2).getReg();
1747 Register CmpVal = MI.getOperand(3).getReg();
1748 Register NewVal = MI.getOperand(4).getReg();
Daniel Sandersaef1dfc2017-11-30 20:11:42 +00001749 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1750 **MI.memoperands_begin());
1751 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1752 MI.eraseFromParent();
1753 return Legalized;
1754 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001755 case TargetOpcode::G_LOAD:
1756 case TargetOpcode::G_SEXTLOAD:
1757 case TargetOpcode::G_ZEXTLOAD: {
1758 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001759 Register DstReg = MI.getOperand(0).getReg();
1760 Register PtrReg = MI.getOperand(1).getReg();
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001761 LLT DstTy = MRI.getType(DstReg);
1762 auto &MMO = **MI.memoperands_begin();
1763
Amara Emersonc8351642019-08-02 23:44:24 +00001764 if (DstTy.getSizeInBits() == MMO.getSizeInBits()) {
1765 if (MI.getOpcode() == TargetOpcode::G_LOAD) {
1766 // This load needs splitting into power of 2 sized loads.
1767 if (DstTy.isVector())
Daniel Sanders2de9d4a2018-04-30 17:20:01 +00001768 return UnableToLegalize;
Amara Emersonc8351642019-08-02 23:44:24 +00001769 if (isPowerOf2_32(DstTy.getSizeInBits()))
1770 return UnableToLegalize; // Don't know what we're being asked to do.
1771
1772 // Our strategy here is to generate anyextending loads for the smaller
1773 // types up to next power-2 result type, and then combine the two larger
1774 // result values together, before truncating back down to the non-pow-2
1775 // type.
1776 // E.g. v1 = i24 load =>
1777 // v2 = i32 load (2 byte)
1778 // v3 = i32 load (1 byte)
1779 // v4 = i32 shl v3, 16
1780 // v5 = i32 or v4, v2
1781 // v1 = i24 trunc v5
1782 // By doing this we generate the correct truncate which should get
1783 // combined away as an artifact with a matching extend.
1784 uint64_t LargeSplitSize = PowerOf2Floor(DstTy.getSizeInBits());
1785 uint64_t SmallSplitSize = DstTy.getSizeInBits() - LargeSplitSize;
1786
1787 MachineFunction &MF = MIRBuilder.getMF();
1788 MachineMemOperand *LargeMMO =
1789 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
1790 MachineMemOperand *SmallMMO = MF.getMachineMemOperand(
1791 &MMO, LargeSplitSize / 8, SmallSplitSize / 8);
1792
1793 LLT PtrTy = MRI.getType(PtrReg);
1794 unsigned AnyExtSize = NextPowerOf2(DstTy.getSizeInBits());
1795 LLT AnyExtTy = LLT::scalar(AnyExtSize);
1796 Register LargeLdReg = MRI.createGenericVirtualRegister(AnyExtTy);
1797 Register SmallLdReg = MRI.createGenericVirtualRegister(AnyExtTy);
1798 auto LargeLoad =
1799 MIRBuilder.buildLoad(LargeLdReg, PtrReg, *LargeMMO);
1800
1801 auto OffsetCst =
1802 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8);
1803 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy);
1804 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0));
1805 auto SmallLoad = MIRBuilder.buildLoad(SmallLdReg, SmallPtr.getReg(0),
1806 *SmallMMO);
1807
1808 auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
1809 auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
1810 auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
1811 MIRBuilder.buildTrunc(DstReg, {Or.getReg(0)});
1812 MI.eraseFromParent();
1813 return Legalized;
1814 }
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001815 MIRBuilder.buildLoad(DstReg, PtrReg, MMO);
1816 MI.eraseFromParent();
1817 return Legalized;
1818 }
1819
1820 if (DstTy.isScalar()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001821 Register TmpReg =
Amara Emersond51adf02019-04-17 22:21:05 +00001822 MRI.createGenericVirtualRegister(LLT::scalar(MMO.getSizeInBits()));
Daniel Sanders5eb9f582018-04-28 18:14:50 +00001823 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
1824 switch (MI.getOpcode()) {
1825 default:
1826 llvm_unreachable("Unexpected opcode");
1827 case TargetOpcode::G_LOAD:
1828 MIRBuilder.buildAnyExt(DstReg, TmpReg);
1829 break;
1830 case TargetOpcode::G_SEXTLOAD:
1831 MIRBuilder.buildSExt(DstReg, TmpReg);
1832 break;
1833 case TargetOpcode::G_ZEXTLOAD:
1834 MIRBuilder.buildZExt(DstReg, TmpReg);
1835 break;
1836 }
1837 MI.eraseFromParent();
1838 return Legalized;
1839 }
1840
1841 return UnableToLegalize;
1842 }
Amara Emersonc8351642019-08-02 23:44:24 +00001843 case TargetOpcode::G_STORE: {
1844 // Lower a non-power of 2 store into multiple pow-2 stores.
1845 // E.g. split an i24 store into an i16 store + i8 store.
1846 // We do this by first extending the stored value to the next largest power
1847 // of 2 type, and then using truncating stores to store the components.
1848 // By doing this, likewise with G_LOAD, generate an extend that can be
1849 // artifact-combined away instead of leaving behind extracts.
1850 Register SrcReg = MI.getOperand(0).getReg();
1851 Register PtrReg = MI.getOperand(1).getReg();
1852 LLT SrcTy = MRI.getType(SrcReg);
1853 MachineMemOperand &MMO = **MI.memoperands_begin();
1854 if (SrcTy.getSizeInBits() != MMO.getSizeInBits())
1855 return UnableToLegalize;
1856 if (SrcTy.isVector())
1857 return UnableToLegalize;
1858 if (isPowerOf2_32(SrcTy.getSizeInBits()))
1859 return UnableToLegalize; // Don't know what we're being asked to do.
1860
1861 // Extend to the next pow-2.
1862 const LLT ExtendTy = LLT::scalar(NextPowerOf2(SrcTy.getSizeInBits()));
1863 auto ExtVal = MIRBuilder.buildAnyExt(ExtendTy, SrcReg);
1864
1865 // Obtain the smaller value by shifting away the larger value.
1866 uint64_t LargeSplitSize = PowerOf2Floor(SrcTy.getSizeInBits());
1867 uint64_t SmallSplitSize = SrcTy.getSizeInBits() - LargeSplitSize;
1868 auto ShiftAmt = MIRBuilder.buildConstant(ExtendTy, LargeSplitSize);
1869 auto SmallVal = MIRBuilder.buildLShr(ExtendTy, ExtVal, ShiftAmt);
1870
1871 // Generate the GEP and truncating stores.
1872 LLT PtrTy = MRI.getType(PtrReg);
1873 auto OffsetCst =
1874 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8);
1875 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy);
1876 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0));
1877
1878 MachineFunction &MF = MIRBuilder.getMF();
1879 MachineMemOperand *LargeMMO =
1880 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
1881 MachineMemOperand *SmallMMO =
1882 MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8);
1883 MIRBuilder.buildStore(ExtVal.getReg(0), PtrReg, *LargeMMO);
1884 MIRBuilder.buildStore(SmallVal.getReg(0), SmallPtr.getReg(0), *SmallMMO);
1885 MI.eraseFromParent();
1886 return Legalized;
1887 }
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00001888 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1889 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1890 case TargetOpcode::G_CTLZ:
1891 case TargetOpcode::G_CTTZ:
1892 case TargetOpcode::G_CTPOP:
1893 return lowerBitCount(MI, TypeIdx, Ty);
Petar Avramovicbd395692019-02-26 17:22:42 +00001894 case G_UADDO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001895 Register Res = MI.getOperand(0).getReg();
1896 Register CarryOut = MI.getOperand(1).getReg();
1897 Register LHS = MI.getOperand(2).getReg();
1898 Register RHS = MI.getOperand(3).getReg();
Petar Avramovicbd395692019-02-26 17:22:42 +00001899
1900 MIRBuilder.buildAdd(Res, LHS, RHS);
1901 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS);
1902
1903 MI.eraseFromParent();
1904 return Legalized;
1905 }
Petar Avramovicb8276f22018-12-17 12:31:07 +00001906 case G_UADDE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001907 Register Res = MI.getOperand(0).getReg();
1908 Register CarryOut = MI.getOperand(1).getReg();
1909 Register LHS = MI.getOperand(2).getReg();
1910 Register RHS = MI.getOperand(3).getReg();
1911 Register CarryIn = MI.getOperand(4).getReg();
Petar Avramovicb8276f22018-12-17 12:31:07 +00001912
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001913 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1914 Register ZExtCarryIn = MRI.createGenericVirtualRegister(Ty);
Petar Avramovicb8276f22018-12-17 12:31:07 +00001915
1916 MIRBuilder.buildAdd(TmpRes, LHS, RHS);
1917 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn);
1918 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn);
1919 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS);
1920
1921 MI.eraseFromParent();
1922 return Legalized;
1923 }
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001924 case G_USUBO: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001925 Register Res = MI.getOperand(0).getReg();
1926 Register BorrowOut = MI.getOperand(1).getReg();
1927 Register LHS = MI.getOperand(2).getReg();
1928 Register RHS = MI.getOperand(3).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001929
1930 MIRBuilder.buildSub(Res, LHS, RHS);
1931 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);
1932
1933 MI.eraseFromParent();
1934 return Legalized;
1935 }
1936 case G_USUBE: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001937 Register Res = MI.getOperand(0).getReg();
1938 Register BorrowOut = MI.getOperand(1).getReg();
1939 Register LHS = MI.getOperand(2).getReg();
1940 Register RHS = MI.getOperand(3).getReg();
1941 Register BorrowIn = MI.getOperand(4).getReg();
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001942
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001943 Register TmpRes = MRI.createGenericVirtualRegister(Ty);
1944 Register ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty);
1945 Register LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
1946 Register LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1));
Petar Avramovic7cecadb2019-01-28 12:10:17 +00001947
1948 MIRBuilder.buildSub(TmpRes, LHS, RHS);
1949 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn);
1950 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
1951 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS);
1952 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS);
1953 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS);
1954
1955 MI.eraseFromParent();
1956 return Legalized;
1957 }
Matt Arsenault02b5ca82019-05-17 23:05:13 +00001958 case G_UITOFP:
1959 return lowerUITOFP(MI, TypeIdx, Ty);
1960 case G_SITOFP:
1961 return lowerSITOFP(MI, TypeIdx, Ty);
Matt Arsenault6f74f552019-07-01 17:18:03 +00001962 case G_SMIN:
1963 case G_SMAX:
1964 case G_UMIN:
1965 case G_UMAX:
1966 return lowerMinMax(MI, TypeIdx, Ty);
Matt Arsenaultb1843e12019-07-09 23:34:29 +00001967 case G_FCOPYSIGN:
1968 return lowerFCopySign(MI, TypeIdx, Ty);
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00001969 case G_FMINNUM:
1970 case G_FMAXNUM:
1971 return lowerFMinNumMaxNum(MI);
Matt Arsenaultd9d30a42019-08-01 19:10:05 +00001972 case G_UNMERGE_VALUES:
1973 return lowerUnmergeValues(MI);
Tim Northovercecee562016-08-26 17:46:13 +00001974 }
1975}
1976
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001977LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef(
1978 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00001979 SmallVector<Register, 2> DstRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001980
1981 unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001982 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001983 unsigned Size = MRI.getType(DstReg).getSizeInBits();
1984 int NumParts = Size / NarrowSize;
1985 // FIXME: Don't know how to handle the situation where the small vectors
1986 // aren't all the same size yet.
1987 if (Size % NarrowSize != 0)
1988 return UnableToLegalize;
1989
1990 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00001991 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00001992 MIRBuilder.buildUndef(TmpReg);
1993 DstRegs.push_back(TmpReg);
1994 }
1995
1996 if (NarrowTy.isVector())
1997 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
1998 else
1999 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2000
2001 MI.eraseFromParent();
2002 return Legalized;
2003}
2004
2005LegalizerHelper::LegalizeResult
2006LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx,
2007 LLT NarrowTy) {
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002008 const unsigned Opc = MI.getOpcode();
2009 const unsigned NumOps = MI.getNumOperands() - 1;
2010 const unsigned NarrowSize = NarrowTy.getSizeInBits();
Matt Arsenault3018d182019-06-28 01:47:44 +00002011 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002012 const unsigned Flags = MI.getFlags();
2013 const LLT DstTy = MRI.getType(DstReg);
2014 const unsigned Size = DstTy.getSizeInBits();
2015 const int NumParts = Size / NarrowSize;
2016 const LLT EltTy = DstTy.getElementType();
2017 const unsigned EltSize = EltTy.getSizeInBits();
2018 const unsigned BitsForNumParts = NarrowSize * NumParts;
2019
2020 // Check if we have any leftovers. If we do, then only handle the case where
2021 // the leftover is one element.
2022 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size)
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002023 return UnableToLegalize;
2024
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002025 if (BitsForNumParts != Size) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002026 Register AccumDstReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002027 MIRBuilder.buildUndef(AccumDstReg);
2028
2029 // Handle the pieces which evenly divide into the requested type with
2030 // extract/op/insert sequence.
2031 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) {
2032 SmallVector<SrcOp, 4> SrcOps;
2033 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002034 Register PartOpReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002035 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset);
2036 SrcOps.push_back(PartOpReg);
2037 }
2038
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002039 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002040 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
2041
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002042 Register PartInsertReg = MRI.createGenericVirtualRegister(DstTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002043 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset);
2044 AccumDstReg = PartInsertReg;
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002045 }
2046
2047 // Handle the remaining element sized leftover piece.
2048 SmallVector<SrcOp, 4> SrcOps;
2049 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002050 Register PartOpReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002051 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(),
2052 BitsForNumParts);
2053 SrcOps.push_back(PartOpReg);
2054 }
2055
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002056 Register PartDstReg = MRI.createGenericVirtualRegister(EltTy);
Matt Arsenaultccefbbd2019-01-30 02:22:13 +00002057 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags);
2058 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts);
2059 MI.eraseFromParent();
2060
2061 return Legalized;
2062 }
2063
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002064 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002065
2066 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs);
2067
2068 if (NumOps >= 2)
2069 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs);
2070
2071 if (NumOps >= 3)
2072 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs);
2073
2074 for (int i = 0; i < NumParts; ++i) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002075 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002076
2077 if (NumOps == 1)
2078 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags);
2079 else if (NumOps == 2) {
2080 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags);
2081 } else if (NumOps == 3) {
2082 MIRBuilder.buildInstr(Opc, {DstReg},
2083 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags);
2084 }
2085
2086 DstRegs.push_back(DstReg);
2087 }
2088
2089 if (NarrowTy.isVector())
2090 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2091 else
2092 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2093
2094 MI.eraseFromParent();
2095 return Legalized;
2096}
2097
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002098// Handle splitting vector operations which need to have the same number of
2099// elements in each type index, but each type index may have a different element
2100// type.
2101//
2102// e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
2103// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2104// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2105//
2106// Also handles some irregular breakdown cases, e.g.
2107// e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
2108// <2 x s64> = G_SHL <2 x s64>, <2 x s32>
2109// s64 = G_SHL s64, s32
2110LegalizerHelper::LegalizeResult
2111LegalizerHelper::fewerElementsVectorMultiEltType(
2112 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) {
2113 if (TypeIdx != 0)
2114 return UnableToLegalize;
2115
2116 const LLT NarrowTy0 = NarrowTyArg;
2117 const unsigned NewNumElts =
2118 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1;
2119
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002120 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002121 LLT DstTy = MRI.getType(DstReg);
2122 LLT LeftoverTy0;
2123
2124 // All of the operands need to have the same number of elements, so if we can
2125 // determine a type breakdown for the result type, we can for all of the
2126 // source types.
Fangrui Songb251cc02019-07-12 14:58:15 +00002127 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0).first;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002128 if (NumParts < 0)
2129 return UnableToLegalize;
2130
2131 SmallVector<MachineInstrBuilder, 4> NewInsts;
2132
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002133 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
2134 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002135
2136 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) {
2137 LLT LeftoverTy;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002138 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002139 LLT SrcTyI = MRI.getType(SrcReg);
2140 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType());
2141 LLT LeftoverTyI;
2142
2143 // Split this operand into the requested typed registers, and any leftover
2144 // required to reproduce the original type.
2145 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs,
2146 LeftoverRegs))
2147 return UnableToLegalize;
2148
2149 if (I == 1) {
2150 // For the first operand, create an instruction for each part and setup
2151 // the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002152 for (Register PartReg : PartRegs) {
2153 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002154 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2155 .addDef(PartDstReg)
2156 .addUse(PartReg));
2157 DstRegs.push_back(PartDstReg);
2158 }
2159
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002160 for (Register LeftoverReg : LeftoverRegs) {
2161 Register PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002162 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode())
2163 .addDef(PartDstReg)
2164 .addUse(LeftoverReg));
2165 LeftoverDstRegs.push_back(PartDstReg);
2166 }
2167 } else {
2168 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size());
2169
2170 // Add the newly created operand splits to the existing instructions. The
2171 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2172 // pieces.
2173 unsigned InstCount = 0;
2174 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J)
2175 NewInsts[InstCount++].addUse(PartRegs[J]);
2176 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J)
2177 NewInsts[InstCount++].addUse(LeftoverRegs[J]);
2178 }
2179
2180 PartRegs.clear();
2181 LeftoverRegs.clear();
2182 }
2183
2184 // Insert the newly built operations and rebuild the result register.
2185 for (auto &MIB : NewInsts)
2186 MIRBuilder.insertInstr(MIB);
2187
2188 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs);
2189
2190 MI.eraseFromParent();
2191 return Legalized;
2192}
2193
Tim Northover69fa84a2016-10-14 22:18:18 +00002194LegalizerHelper::LegalizeResult
Matt Arsenaultca676342019-01-25 02:36:32 +00002195LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx,
2196 LLT NarrowTy) {
2197 if (TypeIdx != 0)
2198 return UnableToLegalize;
2199
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002200 Register DstReg = MI.getOperand(0).getReg();
2201 Register SrcReg = MI.getOperand(1).getReg();
Matt Arsenaultca676342019-01-25 02:36:32 +00002202 LLT DstTy = MRI.getType(DstReg);
2203 LLT SrcTy = MRI.getType(SrcReg);
2204
2205 LLT NarrowTy0 = NarrowTy;
2206 LLT NarrowTy1;
2207 unsigned NumParts;
2208
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002209 if (NarrowTy.isVector()) {
Matt Arsenaultca676342019-01-25 02:36:32 +00002210 // Uneven breakdown not handled.
2211 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
2212 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements())
2213 return UnableToLegalize;
2214
2215 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits());
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002216 } else {
2217 NumParts = DstTy.getNumElements();
2218 NarrowTy1 = SrcTy.getElementType();
Matt Arsenaultca676342019-01-25 02:36:32 +00002219 }
2220
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002221 SmallVector<Register, 4> SrcRegs, DstRegs;
Matt Arsenaultca676342019-01-25 02:36:32 +00002222 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs);
2223
2224 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002225 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultca676342019-01-25 02:36:32 +00002226 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode())
2227 .addDef(DstReg)
2228 .addUse(SrcRegs[I]);
2229
2230 NewInst->setFlags(MI.getFlags());
2231 DstRegs.push_back(DstReg);
2232 }
2233
2234 if (NarrowTy.isVector())
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002235 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002236 else
2237 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2238
2239 MI.eraseFromParent();
2240 return Legalized;
2241}
2242
2243LegalizerHelper::LegalizeResult
2244LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx,
2245 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002246 Register DstReg = MI.getOperand(0).getReg();
2247 Register Src0Reg = MI.getOperand(2).getReg();
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002248 LLT DstTy = MRI.getType(DstReg);
2249 LLT SrcTy = MRI.getType(Src0Reg);
2250
2251 unsigned NumParts;
2252 LLT NarrowTy0, NarrowTy1;
2253
2254 if (TypeIdx == 0) {
2255 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2256 unsigned OldElts = DstTy.getNumElements();
2257
2258 NarrowTy0 = NarrowTy;
2259 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements();
2260 NarrowTy1 = NarrowTy.isVector() ?
2261 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) :
2262 SrcTy.getElementType();
2263
2264 } else {
2265 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;
2266 unsigned OldElts = SrcTy.getNumElements();
2267
2268 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) :
2269 NarrowTy.getNumElements();
2270 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(),
2271 DstTy.getScalarSizeInBits());
2272 NarrowTy1 = NarrowTy;
2273 }
2274
2275 // FIXME: Don't know how to handle the situation where the small vectors
2276 // aren't all the same size yet.
2277 if (NarrowTy1.isVector() &&
2278 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements())
2279 return UnableToLegalize;
2280
2281 CmpInst::Predicate Pred
2282 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
2283
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002284 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs;
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002285 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs);
2286 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs);
2287
2288 for (unsigned I = 0; I < NumParts; ++I) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002289 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002290 DstRegs.push_back(DstReg);
2291
2292 if (MI.getOpcode() == TargetOpcode::G_ICMP)
2293 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2294 else {
2295 MachineInstr *NewCmp
2296 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]);
2297 NewCmp->setFlags(MI.getFlags());
2298 }
2299 }
2300
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002301 if (NarrowTy1.isVector())
Matt Arsenaultca676342019-01-25 02:36:32 +00002302 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2303 else
2304 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2305
2306 MI.eraseFromParent();
2307 return Legalized;
2308}
2309
2310LegalizerHelper::LegalizeResult
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002311LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx,
2312 LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002313 Register DstReg = MI.getOperand(0).getReg();
2314 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002315
2316 unsigned NumParts = 0;
2317 LLT NarrowTy0, NarrowTy1;
2318
2319 LLT DstTy = MRI.getType(DstReg);
2320 LLT CondTy = MRI.getType(CondReg);
2321 unsigned Size = DstTy.getSizeInBits();
2322
2323 assert(TypeIdx == 0 || CondTy.isVector());
2324
2325 if (TypeIdx == 0) {
2326 NarrowTy0 = NarrowTy;
2327 NarrowTy1 = CondTy;
2328
2329 unsigned NarrowSize = NarrowTy0.getSizeInBits();
2330 // FIXME: Don't know how to handle the situation where the small vectors
2331 // aren't all the same size yet.
2332 if (Size % NarrowSize != 0)
2333 return UnableToLegalize;
2334
2335 NumParts = Size / NarrowSize;
2336
2337 // Need to break down the condition type
2338 if (CondTy.isVector()) {
2339 if (CondTy.getNumElements() == NumParts)
2340 NarrowTy1 = CondTy.getElementType();
2341 else
2342 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts,
2343 CondTy.getScalarSizeInBits());
2344 }
2345 } else {
2346 NumParts = CondTy.getNumElements();
2347 if (NarrowTy.isVector()) {
2348 // TODO: Handle uneven breakdown.
2349 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements())
2350 return UnableToLegalize;
2351
2352 return UnableToLegalize;
2353 } else {
2354 NarrowTy0 = DstTy.getElementType();
2355 NarrowTy1 = NarrowTy;
2356 }
2357 }
2358
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002359 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs;
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002360 if (CondTy.isVector())
2361 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs);
2362
2363 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs);
2364 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs);
2365
2366 for (unsigned i = 0; i < NumParts; ++i) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002367 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002368 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg,
2369 Src1Regs[i], Src2Regs[i]);
2370 DstRegs.push_back(DstReg);
2371 }
2372
2373 if (NarrowTy0.isVector())
2374 MIRBuilder.buildConcatVectors(DstReg, DstRegs);
2375 else
2376 MIRBuilder.buildBuildVector(DstReg, DstRegs);
2377
2378 MI.eraseFromParent();
2379 return Legalized;
2380}
2381
2382LegalizerHelper::LegalizeResult
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002383LegalizerHelper::fewerElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2384 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002385 const Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002386 LLT PhiTy = MRI.getType(DstReg);
2387 LLT LeftoverTy;
2388
2389 // All of the operands need to have the same number of elements, so if we can
2390 // determine a type breakdown for the result type, we can for all of the
2391 // source types.
2392 int NumParts, NumLeftover;
2393 std::tie(NumParts, NumLeftover)
2394 = getNarrowTypeBreakDown(PhiTy, NarrowTy, LeftoverTy);
2395 if (NumParts < 0)
2396 return UnableToLegalize;
2397
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002398 SmallVector<Register, 4> DstRegs, LeftoverDstRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002399 SmallVector<MachineInstrBuilder, 4> NewInsts;
2400
2401 const int TotalNumParts = NumParts + NumLeftover;
2402
2403 // Insert the new phis in the result block first.
2404 for (int I = 0; I != TotalNumParts; ++I) {
2405 LLT Ty = I < NumParts ? NarrowTy : LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002406 Register PartDstReg = MRI.createGenericVirtualRegister(Ty);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002407 NewInsts.push_back(MIRBuilder.buildInstr(TargetOpcode::G_PHI)
2408 .addDef(PartDstReg));
2409 if (I < NumParts)
2410 DstRegs.push_back(PartDstReg);
2411 else
2412 LeftoverDstRegs.push_back(PartDstReg);
2413 }
2414
2415 MachineBasicBlock *MBB = MI.getParent();
2416 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
2417 insertParts(DstReg, PhiTy, NarrowTy, DstRegs, LeftoverTy, LeftoverDstRegs);
2418
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002419 SmallVector<Register, 4> PartRegs, LeftoverRegs;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002420
2421 // Insert code to extract the incoming values in each predecessor block.
2422 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2423 PartRegs.clear();
2424 LeftoverRegs.clear();
2425
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002426 Register SrcReg = MI.getOperand(I).getReg();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002427 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2428 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2429
2430 LLT Unused;
2431 if (!extractParts(SrcReg, PhiTy, NarrowTy, Unused, PartRegs,
2432 LeftoverRegs))
2433 return UnableToLegalize;
2434
2435 // Add the newly created operand splits to the existing instructions. The
2436 // odd-sized pieces are ordered after the requested NarrowTyArg sized
2437 // pieces.
2438 for (int J = 0; J != TotalNumParts; ++J) {
2439 MachineInstrBuilder MIB = NewInsts[J];
2440 MIB.addUse(J < NumParts ? PartRegs[J] : LeftoverRegs[J - NumParts]);
2441 MIB.addMBB(&OpMBB);
2442 }
2443 }
2444
2445 MI.eraseFromParent();
2446 return Legalized;
2447}
2448
2449LegalizerHelper::LegalizeResult
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002450LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx,
2451 LLT NarrowTy) {
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002452 // FIXME: Don't know how to handle secondary types yet.
2453 if (TypeIdx != 0)
2454 return UnableToLegalize;
2455
Matt Arsenaultcfca2a72019-01-27 22:36:24 +00002456 MachineMemOperand *MMO = *MI.memoperands_begin();
2457
2458 // This implementation doesn't work for atomics. Give up instead of doing
2459 // something invalid.
2460 if (MMO->getOrdering() != AtomicOrdering::NotAtomic ||
2461 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic)
2462 return UnableToLegalize;
2463
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002464 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002465 Register ValReg = MI.getOperand(0).getReg();
2466 Register AddrReg = MI.getOperand(1).getReg();
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002467 LLT ValTy = MRI.getType(ValReg);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002468
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002469 int NumParts = -1;
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002470 int NumLeftover = -1;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002471 LLT LeftoverTy;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002472 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs;
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002473 if (IsLoad) {
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002474 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002475 } else {
2476 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002477 NarrowLeftoverRegs)) {
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002478 NumParts = NarrowRegs.size();
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002479 NumLeftover = NarrowLeftoverRegs.size();
2480 }
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002481 }
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002482
2483 if (NumParts == -1)
2484 return UnableToLegalize;
2485
2486 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits());
2487
2488 unsigned TotalSize = ValTy.getSizeInBits();
2489
2490 // Split the load/store into PartTy sized pieces starting at Offset. If this
2491 // is a load, return the new registers in ValRegs. For a store, each elements
2492 // of ValRegs should be PartTy. Returns the next offset that needs to be
2493 // handled.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002494 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs,
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002495 unsigned Offset) -> unsigned {
2496 MachineFunction &MF = MIRBuilder.getMF();
2497 unsigned PartSize = PartTy.getSizeInBits();
2498 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
2499 Offset += PartSize, ++Idx) {
2500 unsigned ByteSize = PartSize / 8;
2501 unsigned ByteOffset = Offset / 8;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002502 Register NewAddrReg;
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002503
2504 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset);
2505
2506 MachineMemOperand *NewMMO =
2507 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize);
2508
2509 if (IsLoad) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002510 Register Dst = MRI.createGenericVirtualRegister(PartTy);
Matt Arsenaultc7bce732019-01-31 02:46:05 +00002511 ValRegs.push_back(Dst);
2512 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
2513 } else {
2514 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
2515 }
2516 }
2517
2518 return Offset;
2519 };
2520
2521 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0);
2522
2523 // Handle the rest of the register if this isn't an even type breakdown.
2524 if (LeftoverTy.isValid())
2525 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset);
2526
2527 if (IsLoad) {
2528 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
2529 LeftoverTy, NarrowLeftoverRegs);
2530 }
2531
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002532 MI.eraseFromParent();
2533 return Legalized;
2534}
2535
2536LegalizerHelper::LegalizeResult
Tim Northover69fa84a2016-10-14 22:18:18 +00002537LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
2538 LLT NarrowTy) {
Matt Arsenault1b1e6852019-01-25 02:59:34 +00002539 using namespace TargetOpcode;
Volkan Keles574d7372018-12-14 22:11:20 +00002540
2541 MIRBuilder.setInstr(MI);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002542 switch (MI.getOpcode()) {
2543 case G_IMPLICIT_DEF:
2544 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy);
2545 case G_AND:
2546 case G_OR:
2547 case G_XOR:
2548 case G_ADD:
2549 case G_SUB:
2550 case G_MUL:
2551 case G_SMULH:
2552 case G_UMULH:
2553 case G_FADD:
2554 case G_FMUL:
2555 case G_FSUB:
2556 case G_FNEG:
2557 case G_FABS:
Matt Arsenault9dba67f2019-02-11 17:05:20 +00002558 case G_FCANONICALIZE:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002559 case G_FDIV:
2560 case G_FREM:
2561 case G_FMA:
2562 case G_FPOW:
2563 case G_FEXP:
2564 case G_FEXP2:
2565 case G_FLOG:
2566 case G_FLOG2:
2567 case G_FLOG10:
Jessica Paquetteba557672019-04-25 16:44:40 +00002568 case G_FNEARBYINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002569 case G_FCEIL:
Jessica Paquetteebdb0212019-02-11 17:22:58 +00002570 case G_FFLOOR:
Jessica Paquetted5c69e02019-04-19 23:41:52 +00002571 case G_FRINT:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002572 case G_INTRINSIC_ROUND:
2573 case G_INTRINSIC_TRUNC:
Jessica Paquette7db82d72019-01-28 18:34:18 +00002574 case G_FCOS:
2575 case G_FSIN:
Jessica Paquette22457f82019-01-30 21:03:52 +00002576 case G_FSQRT:
Matt Arsenaultd1bfc8d2019-01-31 02:34:03 +00002577 case G_BSWAP:
Amara Emersonae878da2019-04-10 23:06:08 +00002578 case G_SDIV:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002579 case G_SMIN:
2580 case G_SMAX:
2581 case G_UMIN:
2582 case G_UMAX:
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00002583 case G_FMINNUM:
2584 case G_FMAXNUM:
2585 case G_FMINNUM_IEEE:
2586 case G_FMAXNUM_IEEE:
2587 case G_FMINIMUM:
2588 case G_FMAXIMUM:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002589 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy);
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002590 case G_SHL:
2591 case G_LSHR:
2592 case G_ASHR:
Matt Arsenault75e30c42019-02-20 16:42:52 +00002593 case G_CTLZ:
2594 case G_CTLZ_ZERO_UNDEF:
2595 case G_CTTZ:
2596 case G_CTTZ_ZERO_UNDEF:
2597 case G_CTPOP:
Matt Arsenault1448f562019-05-17 12:19:52 +00002598 case G_FCOPYSIGN:
Matt Arsenaultc83b8232019-02-07 17:38:00 +00002599 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002600 case G_ZEXT:
2601 case G_SEXT:
2602 case G_ANYEXT:
2603 case G_FPEXT:
2604 case G_FPTRUNC:
2605 case G_SITOFP:
2606 case G_UITOFP:
2607 case G_FPTOSI:
2608 case G_FPTOUI:
Matt Arsenaultcbaada62019-02-02 23:29:55 +00002609 case G_INTTOPTR:
2610 case G_PTRTOINT:
Matt Arsenaulta8b43392019-02-08 02:40:47 +00002611 case G_ADDRSPACE_CAST:
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002612 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy);
2613 case G_ICMP:
2614 case G_FCMP:
2615 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy);
Matt Arsenaultdc6c7852019-01-30 04:19:31 +00002616 case G_SELECT:
2617 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy);
Matt Arsenaultd3093c22019-02-28 00:16:32 +00002618 case G_PHI:
2619 return fewerElementsVectorPhi(MI, TypeIdx, NarrowTy);
Matt Arsenault816c9b3e2019-01-27 21:53:09 +00002620 case G_LOAD:
2621 case G_STORE:
Matt Arsenault7f09fd62019-02-05 00:26:12 +00002622 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy);
Tim Northover33b07d62016-07-22 20:03:43 +00002623 default:
2624 return UnableToLegalize;
Tim Northover33b07d62016-07-22 20:03:43 +00002625 }
2626}
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00002627
2628LegalizerHelper::LegalizeResult
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002629LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
2630 const LLT HalfTy, const LLT AmtTy) {
2631
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002632 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2633 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002634 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2635
2636 if (Amt.isNullValue()) {
2637 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH});
2638 MI.eraseFromParent();
2639 return Legalized;
2640 }
2641
2642 LLT NVT = HalfTy;
2643 unsigned NVTBits = HalfTy.getSizeInBits();
2644 unsigned VTBits = 2 * NVTBits;
2645
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002646 SrcOp Lo(Register(0)), Hi(Register(0));
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002647 if (MI.getOpcode() == TargetOpcode::G_SHL) {
2648 if (Amt.ugt(VTBits)) {
2649 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2650 } else if (Amt.ugt(NVTBits)) {
2651 Lo = MIRBuilder.buildConstant(NVT, 0);
2652 Hi = MIRBuilder.buildShl(NVT, InL,
2653 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2654 } else if (Amt == NVTBits) {
2655 Lo = MIRBuilder.buildConstant(NVT, 0);
2656 Hi = InL;
2657 } else {
2658 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
Matt Arsenaulte98cab12019-02-07 20:44:08 +00002659 auto OrLHS =
2660 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
2661 auto OrRHS = MIRBuilder.buildLShr(
2662 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2663 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002664 }
2665 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2666 if (Amt.ugt(VTBits)) {
2667 Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
2668 } else if (Amt.ugt(NVTBits)) {
2669 Lo = MIRBuilder.buildLShr(NVT, InH,
2670 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2671 Hi = MIRBuilder.buildConstant(NVT, 0);
2672 } else if (Amt == NVTBits) {
2673 Lo = InH;
2674 Hi = MIRBuilder.buildConstant(NVT, 0);
2675 } else {
2676 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2677
2678 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2679 auto OrRHS = MIRBuilder.buildShl(
2680 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2681
2682 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2683 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
2684 }
2685 } else {
2686 if (Amt.ugt(VTBits)) {
2687 Hi = Lo = MIRBuilder.buildAShr(
2688 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2689 } else if (Amt.ugt(NVTBits)) {
2690 Lo = MIRBuilder.buildAShr(NVT, InH,
2691 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
2692 Hi = MIRBuilder.buildAShr(NVT, InH,
2693 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2694 } else if (Amt == NVTBits) {
2695 Lo = InH;
2696 Hi = MIRBuilder.buildAShr(NVT, InH,
2697 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
2698 } else {
2699 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);
2700
2701 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
2702 auto OrRHS = MIRBuilder.buildShl(
2703 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
2704
2705 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
2706 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
2707 }
2708 }
2709
2710 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()});
2711 MI.eraseFromParent();
2712
2713 return Legalized;
2714}
2715
2716// TODO: Optimize if constant shift amount.
2717LegalizerHelper::LegalizeResult
2718LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
2719 LLT RequestedTy) {
2720 if (TypeIdx == 1) {
2721 Observer.changingInstr(MI);
2722 narrowScalarSrc(MI, RequestedTy, 2);
2723 Observer.changedInstr(MI);
2724 return Legalized;
2725 }
2726
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002727 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002728 LLT DstTy = MRI.getType(DstReg);
2729 if (DstTy.isVector())
2730 return UnableToLegalize;
2731
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002732 Register Amt = MI.getOperand(2).getReg();
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002733 LLT ShiftAmtTy = MRI.getType(Amt);
2734 const unsigned DstEltSize = DstTy.getScalarSizeInBits();
2735 if (DstEltSize % 2 != 0)
2736 return UnableToLegalize;
2737
2738 // Ignore the input type. We can only go to exactly half the size of the
2739 // input. If that isn't small enough, the resulting pieces will be further
2740 // legalized.
2741 const unsigned NewBitSize = DstEltSize / 2;
2742 const LLT HalfTy = LLT::scalar(NewBitSize);
2743 const LLT CondTy = LLT::scalar(1);
2744
2745 if (const MachineInstr *KShiftAmt =
2746 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) {
2747 return narrowScalarShiftByConstant(
2748 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy);
2749 }
2750
2751 // TODO: Expand with known bits.
2752
2753 // Handle the fully general expansion by an unknown amount.
2754 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
2755
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002756 Register InL = MRI.createGenericVirtualRegister(HalfTy);
2757 Register InH = MRI.createGenericVirtualRegister(HalfTy);
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002758 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg());
2759
2760 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
2761 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
2762
2763 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
2764 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
2765 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);
2766
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002767 Register ResultRegs[2];
Matt Arsenaultfbec8fe2019-02-07 19:37:44 +00002768 switch (MI.getOpcode()) {
2769 case TargetOpcode::G_SHL: {
2770 // Short: ShAmt < NewBitSize
2771 auto LoS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2772
2773 auto OrLHS = MIRBuilder.buildShl(HalfTy, InH, Amt);
2774 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
2775 auto HiS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2776
2777 // Long: ShAmt >= NewBitSize
2778 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero.
2779 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.
2780
2781 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
2782 auto Hi = MIRBuilder.buildSelect(
2783 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
2784
2785 ResultRegs[0] = Lo.getReg(0);
2786 ResultRegs[1] = Hi.getReg(0);
2787 break;
2788 }
2789 case TargetOpcode::G_LSHR: {
2790 // Short: ShAmt < NewBitSize
2791 auto HiS = MIRBuilder.buildLShr(HalfTy, InH, Amt);
2792
2793 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2794 auto OrRHS = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
2795 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2796
2797 // Long: ShAmt >= NewBitSize
2798 auto HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero.
2799 auto LoL = MIRBuilder.buildLShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2800
2801 auto Lo = MIRBuilder.buildSelect(
2802 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2803 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2804
2805 ResultRegs[0] = Lo.getReg(0);
2806 ResultRegs[1] = Hi.getReg(0);
2807 break;
2808 }
2809 case TargetOpcode::G_ASHR: {
2810 // Short: ShAmt < NewBitSize
2811 auto HiS = MIRBuilder.buildAShr(HalfTy, InH, Amt);
2812
2813 auto OrLHS = MIRBuilder.buildLShr(HalfTy, InL, Amt);
2814 auto OrRHS = MIRBuilder.buildLShr(HalfTy, InH, AmtLack);
2815 auto LoS = MIRBuilder.buildOr(HalfTy, OrLHS, OrRHS);
2816
2817 // Long: ShAmt >= NewBitSize
2818
2819 // Sign of Hi part.
2820 auto HiL = MIRBuilder.buildAShr(
2821 HalfTy, InH, MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1));
2822
2823 auto LoL = MIRBuilder.buildAShr(HalfTy, InH, AmtExcess); // Lo from Hi part.
2824
2825 auto Lo = MIRBuilder.buildSelect(
2826 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
2827
2828 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
2829
2830 ResultRegs[0] = Lo.getReg(0);
2831 ResultRegs[1] = Hi.getReg(0);
2832 break;
2833 }
2834 default:
2835 llvm_unreachable("not a shift");
2836 }
2837
2838 MIRBuilder.buildMerge(DstReg, ResultRegs);
2839 MI.eraseFromParent();
2840 return Legalized;
2841}
2842
2843LegalizerHelper::LegalizeResult
Matt Arsenault72bcf152019-02-28 00:01:05 +00002844LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
2845 LLT MoreTy) {
2846 assert(TypeIdx == 0 && "Expecting only Idx 0");
2847
2848 Observer.changingInstr(MI);
2849 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2850 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
2851 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
2852 moreElementsVectorSrc(MI, MoreTy, I);
2853 }
2854
2855 MachineBasicBlock &MBB = *MI.getParent();
2856 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
2857 moreElementsVectorDst(MI, MoreTy, 0);
2858 Observer.changedInstr(MI);
2859 return Legalized;
2860}
2861
2862LegalizerHelper::LegalizeResult
Matt Arsenault18ec3822019-02-11 22:00:39 +00002863LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
2864 LLT MoreTy) {
2865 MIRBuilder.setInstr(MI);
2866 unsigned Opc = MI.getOpcode();
2867 switch (Opc) {
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002868 case TargetOpcode::G_IMPLICIT_DEF:
2869 case TargetOpcode::G_LOAD: {
2870 if (TypeIdx != 0)
2871 return UnableToLegalize;
Matt Arsenault18ec3822019-02-11 22:00:39 +00002872 Observer.changingInstr(MI);
2873 moreElementsVectorDst(MI, MoreTy, 0);
2874 Observer.changedInstr(MI);
2875 return Legalized;
2876 }
Matt Arsenault7bedceb2019-08-01 01:44:22 +00002877 case TargetOpcode::G_STORE:
2878 if (TypeIdx != 0)
2879 return UnableToLegalize;
2880 Observer.changingInstr(MI);
2881 moreElementsVectorSrc(MI, MoreTy, 0);
2882 Observer.changedInstr(MI);
2883 return Legalized;
Matt Arsenault26b7e852019-02-19 16:30:19 +00002884 case TargetOpcode::G_AND:
2885 case TargetOpcode::G_OR:
Matt Arsenault0f3ba442019-05-23 17:58:48 +00002886 case TargetOpcode::G_XOR:
2887 case TargetOpcode::G_SMIN:
2888 case TargetOpcode::G_SMAX:
2889 case TargetOpcode::G_UMIN:
2890 case TargetOpcode::G_UMAX: {
Matt Arsenault26b7e852019-02-19 16:30:19 +00002891 Observer.changingInstr(MI);
2892 moreElementsVectorSrc(MI, MoreTy, 1);
2893 moreElementsVectorSrc(MI, MoreTy, 2);
2894 moreElementsVectorDst(MI, MoreTy, 0);
2895 Observer.changedInstr(MI);
2896 return Legalized;
2897 }
Matt Arsenault4d884272019-02-19 16:44:22 +00002898 case TargetOpcode::G_EXTRACT:
2899 if (TypeIdx != 1)
2900 return UnableToLegalize;
2901 Observer.changingInstr(MI);
2902 moreElementsVectorSrc(MI, MoreTy, 1);
2903 Observer.changedInstr(MI);
2904 return Legalized;
Matt Arsenaultc4d07552019-02-20 16:11:22 +00002905 case TargetOpcode::G_INSERT:
2906 if (TypeIdx != 0)
2907 return UnableToLegalize;
2908 Observer.changingInstr(MI);
2909 moreElementsVectorSrc(MI, MoreTy, 1);
2910 moreElementsVectorDst(MI, MoreTy, 0);
2911 Observer.changedInstr(MI);
2912 return Legalized;
Matt Arsenaultb4c95b32019-02-19 17:03:09 +00002913 case TargetOpcode::G_SELECT:
2914 if (TypeIdx != 0)
2915 return UnableToLegalize;
2916 if (MRI.getType(MI.getOperand(1).getReg()).isVector())
2917 return UnableToLegalize;
2918
2919 Observer.changingInstr(MI);
2920 moreElementsVectorSrc(MI, MoreTy, 2);
2921 moreElementsVectorSrc(MI, MoreTy, 3);
2922 moreElementsVectorDst(MI, MoreTy, 0);
2923 Observer.changedInstr(MI);
2924 return Legalized;
Matt Arsenault72bcf152019-02-28 00:01:05 +00002925 case TargetOpcode::G_PHI:
2926 return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
Matt Arsenault18ec3822019-02-11 22:00:39 +00002927 default:
2928 return UnableToLegalize;
2929 }
2930}
2931
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002932void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
2933 ArrayRef<Register> Src1Regs,
2934 ArrayRef<Register> Src2Regs,
Petar Avramovic0b17e592019-03-11 10:00:17 +00002935 LLT NarrowTy) {
2936 MachineIRBuilder &B = MIRBuilder;
2937 unsigned SrcParts = Src1Regs.size();
2938 unsigned DstParts = DstRegs.size();
2939
2940 unsigned DstIdx = 0; // Low bits of the result.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002941 Register FactorSum =
Petar Avramovic0b17e592019-03-11 10:00:17 +00002942 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
2943 DstRegs[DstIdx] = FactorSum;
2944
2945 unsigned CarrySumPrevDstIdx;
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002946 SmallVector<Register, 4> Factors;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002947
2948 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
2949 // Collect low parts of muls for DstIdx.
2950 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
2951 i <= std::min(DstIdx, SrcParts - 1); ++i) {
2952 MachineInstrBuilder Mul =
2953 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
2954 Factors.push_back(Mul.getReg(0));
2955 }
2956 // Collect high parts of muls from previous DstIdx.
2957 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
2958 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
2959 MachineInstrBuilder Umulh =
2960 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
2961 Factors.push_back(Umulh.getReg(0));
2962 }
2963 // Add CarrySum from additons calculated for previous DstIdx.
2964 if (DstIdx != 1) {
2965 Factors.push_back(CarrySumPrevDstIdx);
2966 }
2967
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00002968 Register CarrySum;
Petar Avramovic0b17e592019-03-11 10:00:17 +00002969 // Add all factors and accumulate all carries into CarrySum.
2970 if (DstIdx != DstParts - 1) {
2971 MachineInstrBuilder Uaddo =
2972 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]);
2973 FactorSum = Uaddo.getReg(0);
2974 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0);
2975 for (unsigned i = 2; i < Factors.size(); ++i) {
2976 MachineInstrBuilder Uaddo =
2977 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]);
2978 FactorSum = Uaddo.getReg(0);
2979 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1));
2980 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
2981 }
2982 } else {
2983 // Since value for the next index is not calculated, neither is CarrySum.
2984 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
2985 for (unsigned i = 2; i < Factors.size(); ++i)
2986 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
2987 }
2988
2989 CarrySumPrevDstIdx = CarrySum;
2990 DstRegs[DstIdx] = FactorSum;
2991 Factors.clear();
2992 }
2993}
2994
Matt Arsenault18ec3822019-02-11 22:00:39 +00002995LegalizerHelper::LegalizeResult
Petar Avramovic0b17e592019-03-11 10:00:17 +00002996LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) {
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00002997 Register DstReg = MI.getOperand(0).getReg();
2998 Register Src1 = MI.getOperand(1).getReg();
2999 Register Src2 = MI.getOperand(2).getReg();
Petar Avramovic0b17e592019-03-11 10:00:17 +00003000
Matt Arsenault211e89d2019-01-27 00:52:51 +00003001 LLT Ty = MRI.getType(DstReg);
3002 if (Ty.isVector())
3003 return UnableToLegalize;
3004
Petar Avramovic0b17e592019-03-11 10:00:17 +00003005 unsigned SrcSize = MRI.getType(Src1).getSizeInBits();
3006 unsigned DstSize = Ty.getSizeInBits();
3007 unsigned NarrowSize = NarrowTy.getSizeInBits();
3008 if (DstSize % NarrowSize != 0 || SrcSize % NarrowSize != 0)
Matt Arsenault211e89d2019-01-27 00:52:51 +00003009 return UnableToLegalize;
3010
Petar Avramovic0b17e592019-03-11 10:00:17 +00003011 unsigned NumDstParts = DstSize / NarrowSize;
3012 unsigned NumSrcParts = SrcSize / NarrowSize;
Petar Avramovic5229f472019-03-11 10:08:44 +00003013 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH;
3014 unsigned DstTmpParts = NumDstParts * (IsMulHigh ? 2 : 1);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003015
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003016 SmallVector<Register, 2> Src1Parts, Src2Parts, DstTmpRegs;
Petar Avramovic0b17e592019-03-11 10:00:17 +00003017 extractParts(Src1, NarrowTy, NumSrcParts, Src1Parts);
3018 extractParts(Src2, NarrowTy, NumSrcParts, Src2Parts);
Petar Avramovic5229f472019-03-11 10:08:44 +00003019 DstTmpRegs.resize(DstTmpParts);
3020 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003021
Petar Avramovic5229f472019-03-11 10:08:44 +00003022 // Take only high half of registers if this is high mul.
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003023 ArrayRef<Register> DstRegs(
Petar Avramovic5229f472019-03-11 10:08:44 +00003024 IsMulHigh ? &DstTmpRegs[DstTmpParts / 2] : &DstTmpRegs[0], NumDstParts);
Petar Avramovic0b17e592019-03-11 10:00:17 +00003025 MIRBuilder.buildMerge(DstReg, DstRegs);
Matt Arsenault211e89d2019-01-27 00:52:51 +00003026 MI.eraseFromParent();
3027 return Legalized;
3028}
3029
Matt Arsenault1cf71362019-02-12 14:54:52 +00003030LegalizerHelper::LegalizeResult
3031LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
3032 LLT NarrowTy) {
3033 if (TypeIdx != 1)
3034 return UnableToLegalize;
3035
3036 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3037
3038 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
3039 // FIXME: add support for when SizeOp1 isn't an exact multiple of
3040 // NarrowSize.
3041 if (SizeOp1 % NarrowSize != 0)
3042 return UnableToLegalize;
3043 int NumParts = SizeOp1 / NarrowSize;
3044
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003045 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003046 SmallVector<uint64_t, 2> Indexes;
3047 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3048
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003049 Register OpReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003050 uint64_t OpStart = MI.getOperand(2).getImm();
3051 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3052 for (int i = 0; i < NumParts; ++i) {
3053 unsigned SrcStart = i * NarrowSize;
3054
3055 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
3056 // No part of the extract uses this subregister, ignore it.
3057 continue;
3058 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3059 // The entire subregister is extracted, forward the value.
3060 DstRegs.push_back(SrcRegs[i]);
3061 continue;
3062 }
3063
3064 // OpSegStart is where this destination segment would start in OpReg if it
3065 // extended infinitely in both directions.
3066 int64_t ExtractOffset;
3067 uint64_t SegSize;
3068 if (OpStart < SrcStart) {
3069 ExtractOffset = 0;
3070 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
3071 } else {
3072 ExtractOffset = OpStart - SrcStart;
3073 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
3074 }
3075
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003076 Register SegReg = SrcRegs[i];
Matt Arsenault1cf71362019-02-12 14:54:52 +00003077 if (ExtractOffset != 0 || SegSize != NarrowSize) {
3078 // A genuine extract is needed.
3079 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3080 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
3081 }
3082
3083 DstRegs.push_back(SegReg);
3084 }
3085
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003086 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003087 if(MRI.getType(DstReg).isVector())
3088 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3089 else
3090 MIRBuilder.buildMerge(DstReg, DstRegs);
3091 MI.eraseFromParent();
3092 return Legalized;
3093}
3094
3095LegalizerHelper::LegalizeResult
3096LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
3097 LLT NarrowTy) {
3098 // FIXME: Don't know how to handle secondary types yet.
3099 if (TypeIdx != 0)
3100 return UnableToLegalize;
3101
3102 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
3103 uint64_t NarrowSize = NarrowTy.getSizeInBits();
3104
3105 // FIXME: add support for when SizeOp0 isn't an exact multiple of
3106 // NarrowSize.
3107 if (SizeOp0 % NarrowSize != 0)
3108 return UnableToLegalize;
3109
3110 int NumParts = SizeOp0 / NarrowSize;
3111
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003112 SmallVector<Register, 2> SrcRegs, DstRegs;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003113 SmallVector<uint64_t, 2> Indexes;
3114 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
3115
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003116 Register OpReg = MI.getOperand(2).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003117 uint64_t OpStart = MI.getOperand(3).getImm();
3118 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
3119 for (int i = 0; i < NumParts; ++i) {
3120 unsigned DstStart = i * NarrowSize;
3121
3122 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
3123 // No part of the insert affects this subregister, forward the original.
3124 DstRegs.push_back(SrcRegs[i]);
3125 continue;
3126 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
3127 // The entire subregister is defined by this insert, forward the new
3128 // value.
3129 DstRegs.push_back(OpReg);
3130 continue;
3131 }
3132
3133 // OpSegStart is where this destination segment would start in OpReg if it
3134 // extended infinitely in both directions.
3135 int64_t ExtractOffset, InsertOffset;
3136 uint64_t SegSize;
3137 if (OpStart < DstStart) {
3138 InsertOffset = 0;
3139 ExtractOffset = DstStart - OpStart;
3140 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
3141 } else {
3142 InsertOffset = OpStart - DstStart;
3143 ExtractOffset = 0;
3144 SegSize =
3145 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
3146 }
3147
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003148 Register SegReg = OpReg;
Matt Arsenault1cf71362019-02-12 14:54:52 +00003149 if (ExtractOffset != 0 || SegSize != OpSize) {
3150 // A genuine extract is needed.
3151 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
3152 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
3153 }
3154
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003155 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
Matt Arsenault1cf71362019-02-12 14:54:52 +00003156 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
3157 DstRegs.push_back(DstReg);
3158 }
3159
3160 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003161 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault1cf71362019-02-12 14:54:52 +00003162 if(MRI.getType(DstReg).isVector())
3163 MIRBuilder.buildBuildVector(DstReg, DstRegs);
3164 else
3165 MIRBuilder.buildMerge(DstReg, DstRegs);
3166 MI.eraseFromParent();
3167 return Legalized;
3168}
3169
Matt Arsenault211e89d2019-01-27 00:52:51 +00003170LegalizerHelper::LegalizeResult
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003171LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx,
3172 LLT NarrowTy) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003173 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003174 LLT DstTy = MRI.getType(DstReg);
3175
3176 assert(MI.getNumOperands() == 3 && TypeIdx == 0);
3177
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003178 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3179 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs;
3180 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
Matt Arsenault9e0eeba2019-04-10 17:07:56 +00003181 LLT LeftoverTy;
3182 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
3183 Src0Regs, Src0LeftoverRegs))
3184 return UnableToLegalize;
3185
3186 LLT Unused;
3187 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
3188 Src1Regs, Src1LeftoverRegs))
3189 llvm_unreachable("inconsistent extractParts result");
3190
3191 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3192 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
3193 {Src0Regs[I], Src1Regs[I]});
3194 DstRegs.push_back(Inst->getOperand(0).getReg());
3195 }
3196
3197 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3198 auto Inst = MIRBuilder.buildInstr(
3199 MI.getOpcode(),
3200 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
3201 DstLeftoverRegs.push_back(Inst->getOperand(0).getReg());
3202 }
3203
3204 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3205 LeftoverTy, DstLeftoverRegs);
3206
3207 MI.eraseFromParent();
3208 return Legalized;
3209}
3210
3211LegalizerHelper::LegalizeResult
Matt Arsenault81511e52019-02-05 00:13:44 +00003212LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
3213 LLT NarrowTy) {
3214 if (TypeIdx != 0)
3215 return UnableToLegalize;
3216
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003217 Register CondReg = MI.getOperand(1).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003218 LLT CondTy = MRI.getType(CondReg);
3219 if (CondTy.isVector()) // TODO: Handle vselect
3220 return UnableToLegalize;
3221
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003222 Register DstReg = MI.getOperand(0).getReg();
Matt Arsenault81511e52019-02-05 00:13:44 +00003223 LLT DstTy = MRI.getType(DstReg);
3224
Matt Arsenaulte3a676e2019-06-24 15:50:29 +00003225 SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
3226 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
3227 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs;
Matt Arsenault81511e52019-02-05 00:13:44 +00003228 LLT LeftoverTy;
3229 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
3230 Src1Regs, Src1LeftoverRegs))
3231 return UnableToLegalize;
3232
3233 LLT Unused;
3234 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
3235 Src2Regs, Src2LeftoverRegs))
3236 llvm_unreachable("inconsistent extractParts result");
3237
3238 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
3239 auto Select = MIRBuilder.buildSelect(NarrowTy,
3240 CondReg, Src1Regs[I], Src2Regs[I]);
3241 DstRegs.push_back(Select->getOperand(0).getReg());
3242 }
3243
3244 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
3245 auto Select = MIRBuilder.buildSelect(
3246 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
3247 DstLeftoverRegs.push_back(Select->getOperand(0).getReg());
3248 }
3249
3250 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
3251 LeftoverTy, DstLeftoverRegs);
3252
3253 MI.eraseFromParent();
3254 return Legalized;
3255}
3256
3257LegalizerHelper::LegalizeResult
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003258LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3259 unsigned Opc = MI.getOpcode();
3260 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo();
Diana Picus0528e2c2018-11-26 11:07:02 +00003261 auto isSupported = [this](const LegalityQuery &Q) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003262 auto QAction = LI.getAction(Q).Action;
Diana Picus0528e2c2018-11-26 11:07:02 +00003263 return QAction == Legal || QAction == Libcall || QAction == Custom;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003264 };
3265 switch (Opc) {
3266 default:
3267 return UnableToLegalize;
3268 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
3269 // This trivially expands to CTLZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003270 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003271 MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003272 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003273 return Legalized;
3274 }
3275 case TargetOpcode::G_CTLZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003276 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003277 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003278 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) {
Diana Picus0528e2c2018-11-26 11:07:02 +00003279 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003280 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF,
3281 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003282 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3283 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3284 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3285 SrcReg, MIBZero);
3286 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3287 MIBCtlzZU);
3288 MI.eraseFromParent();
3289 return Legalized;
3290 }
3291 // for now, we do this:
3292 // NewLen = NextPowerOf2(Len);
3293 // x = x | (x >> 1);
3294 // x = x | (x >> 2);
3295 // ...
3296 // x = x | (x >>16);
3297 // x = x | (x >>32); // for 64-bit input
3298 // Upto NewLen/2
3299 // return Len - popcount(x);
3300 //
3301 // Ref: "Hacker's Delight" by Henry Warren
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003302 Register Op = SrcReg;
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003303 unsigned NewLen = PowerOf2Ceil(Len);
3304 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
3305 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i);
3306 auto MIBOp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003307 TargetOpcode::G_OR, {Ty},
3308 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty},
3309 {Op, MIBShiftAmt})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003310 Op = MIBOp->getOperand(0).getReg();
3311 }
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003312 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op});
3313 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3314 {MIRBuilder.buildConstant(Ty, Len), MIBPop});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003315 MI.eraseFromParent();
3316 return Legalized;
3317 }
3318 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
3319 // This trivially expands to CTTZ.
Daniel Sandersd001e0e2018-12-12 23:48:13 +00003320 Observer.changingInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003321 MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +00003322 Observer.changedInstr(MI);
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003323 return Legalized;
3324 }
3325 case TargetOpcode::G_CTTZ: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003326 Register SrcReg = MI.getOperand(1).getReg();
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003327 unsigned Len = Ty.getSizeInBits();
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003328 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003329 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with
3330 // zero.
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003331 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF,
3332 {Ty}, {SrcReg});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003333 auto MIBZero = MIRBuilder.buildConstant(Ty, 0);
3334 auto MIBLen = MIRBuilder.buildConstant(Ty, Len);
3335 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
3336 SrcReg, MIBZero);
3337 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen,
3338 MIBCttzZU);
3339 MI.eraseFromParent();
3340 return Legalized;
3341 }
3342 // for now, we use: { return popcount(~x & (x - 1)); }
3343 // unless the target has ctlz but not ctpop, in which case we use:
3344 // { return 32 - nlz(~x & (x-1)); }
3345 // Ref: "Hacker's Delight" by Henry Warren
3346 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1);
3347 auto MIBNot =
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003348 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003349 auto MIBTmp = MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003350 TargetOpcode::G_AND, {Ty},
3351 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty},
3352 {SrcReg, MIBCstNeg1})});
Matt Arsenaultd5684f72019-01-31 02:09:57 +00003353 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) &&
3354 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) {
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003355 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len);
3356 MIRBuilder.buildInstr(
Aditya Nandakumarcef44a22018-12-11 00:48:50 +00003357 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()},
3358 {MIBCstLen,
3359 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})});
Aditya Nandakumarc0333f72018-08-21 17:30:31 +00003360 MI.eraseFromParent();
3361 return Legalized;
3362 }
3363 MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
3364 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg());
3365 return Legalized;
3366 }
3367 }
3368}
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003369
3370// Expand s32 = G_UITOFP s64 using bit operations to an IEEE float
3371// representation.
3372LegalizerHelper::LegalizeResult
3373LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003374 Register Dst = MI.getOperand(0).getReg();
3375 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003376 const LLT S64 = LLT::scalar(64);
3377 const LLT S32 = LLT::scalar(32);
3378 const LLT S1 = LLT::scalar(1);
3379
3380 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);
3381
3382 // unsigned cul2f(ulong u) {
3383 // uint lz = clz(u);
3384 // uint e = (u != 0) ? 127U + 63U - lz : 0;
3385 // u = (u << lz) & 0x7fffffffffffffffUL;
3386 // ulong t = u & 0xffffffffffUL;
3387 // uint v = (e << 23) | (uint)(u >> 40);
3388 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
3389 // return as_float(v + r);
3390 // }
3391
3392 auto Zero32 = MIRBuilder.buildConstant(S32, 0);
3393 auto Zero64 = MIRBuilder.buildConstant(S64, 0);
3394
3395 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src);
3396
3397 auto K = MIRBuilder.buildConstant(S32, 127U + 63U);
3398 auto Sub = MIRBuilder.buildSub(S32, K, LZ);
3399
3400 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64);
3401 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32);
3402
3403 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1);
3404 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ);
3405
3406 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0);
3407
3408 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL);
3409 auto T = MIRBuilder.buildAnd(S64, U, Mask1);
3410
3411 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40));
3412 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23));
3413 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl));
3414
3415 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL);
3416 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C);
3417 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C);
3418 auto One = MIRBuilder.buildConstant(S32, 1);
3419
3420 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One);
3421 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32);
3422 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0);
3423 MIRBuilder.buildAdd(Dst, V, R);
3424
3425 return Legalized;
3426}
3427
3428LegalizerHelper::LegalizeResult
3429LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003430 Register Dst = MI.getOperand(0).getReg();
3431 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003432 LLT DstTy = MRI.getType(Dst);
3433 LLT SrcTy = MRI.getType(Src);
3434
3435 if (SrcTy != LLT::scalar(64))
3436 return UnableToLegalize;
3437
3438 if (DstTy == LLT::scalar(32)) {
3439 // TODO: SelectionDAG has several alternative expansions to port which may
3440 // be more reasonble depending on the available instructions. If a target
3441 // has sitofp, does not have CTLZ, or can efficiently use f64 as an
3442 // intermediate type, this is probably worse.
3443 return lowerU64ToF32BitOps(MI);
3444 }
3445
3446 return UnableToLegalize;
3447}
3448
3449LegalizerHelper::LegalizeResult
3450LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003451 Register Dst = MI.getOperand(0).getReg();
3452 Register Src = MI.getOperand(1).getReg();
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003453 LLT DstTy = MRI.getType(Dst);
3454 LLT SrcTy = MRI.getType(Src);
3455
3456 const LLT S64 = LLT::scalar(64);
3457 const LLT S32 = LLT::scalar(32);
3458 const LLT S1 = LLT::scalar(1);
3459
3460 if (SrcTy != S64)
3461 return UnableToLegalize;
3462
3463 if (DstTy == S32) {
3464 // signed cl2f(long l) {
3465 // long s = l >> 63;
3466 // float r = cul2f((l + s) ^ s);
3467 // return s ? -r : r;
3468 // }
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +00003469 Register L = Src;
Matt Arsenault02b5ca82019-05-17 23:05:13 +00003470 auto SignBit = MIRBuilder.buildConstant(S64, 63);
3471 auto S = MIRBuilder.buildAShr(S64, L, SignBit);
3472
3473 auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
3474 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
3475 auto R = MIRBuilder.buildUITOFP(S32, Xor);
3476
3477 auto RNeg = MIRBuilder.buildFNeg(S32, R);
3478 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
3479 MIRBuilder.buildConstant(S64, 0));
3480 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
3481 return Legalized;
3482 }
3483
3484 return UnableToLegalize;
3485}
Matt Arsenault6f74f552019-07-01 17:18:03 +00003486
3487static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
3488 switch (Opc) {
3489 case TargetOpcode::G_SMIN:
3490 return CmpInst::ICMP_SLT;
3491 case TargetOpcode::G_SMAX:
3492 return CmpInst::ICMP_SGT;
3493 case TargetOpcode::G_UMIN:
3494 return CmpInst::ICMP_ULT;
3495 case TargetOpcode::G_UMAX:
3496 return CmpInst::ICMP_UGT;
3497 default:
3498 llvm_unreachable("not in integer min/max");
3499 }
3500}
3501
3502LegalizerHelper::LegalizeResult
3503LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3504 Register Dst = MI.getOperand(0).getReg();
3505 Register Src0 = MI.getOperand(1).getReg();
3506 Register Src1 = MI.getOperand(2).getReg();
3507
3508 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
3509 LLT CmpType = MRI.getType(Dst).changeElementSize(1);
3510
3511 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
3512 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
3513
3514 MI.eraseFromParent();
3515 return Legalized;
3516}
Matt Arsenaultb1843e12019-07-09 23:34:29 +00003517
3518LegalizerHelper::LegalizeResult
3519LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
3520 Register Dst = MI.getOperand(0).getReg();
3521 Register Src0 = MI.getOperand(1).getReg();
3522 Register Src1 = MI.getOperand(2).getReg();
3523
3524 const LLT Src0Ty = MRI.getType(Src0);
3525 const LLT Src1Ty = MRI.getType(Src1);
3526
3527 const int Src0Size = Src0Ty.getScalarSizeInBits();
3528 const int Src1Size = Src1Ty.getScalarSizeInBits();
3529
3530 auto SignBitMask = MIRBuilder.buildConstant(
3531 Src0Ty, APInt::getSignMask(Src0Size));
3532
3533 auto NotSignBitMask = MIRBuilder.buildConstant(
3534 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
3535
3536 auto And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask);
3537 MachineInstr *Or;
3538
3539 if (Src0Ty == Src1Ty) {
3540 auto And1 = MIRBuilder.buildAnd(Src1Ty, Src0, SignBitMask);
3541 Or = MIRBuilder.buildOr(Dst, And0, And1);
3542 } else if (Src0Size > Src1Size) {
3543 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
3544 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
3545 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
3546 auto And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask);
3547 Or = MIRBuilder.buildOr(Dst, And0, And1);
3548 } else {
3549 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
3550 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
3551 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
3552 auto And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask);
3553 Or = MIRBuilder.buildOr(Dst, And0, And1);
3554 }
3555
3556 // Be careful about setting nsz/nnan/ninf on every instruction, since the
3557 // constants are a nan and -0.0, but the final result should preserve
3558 // everything.
3559 if (unsigned Flags = MI.getFlags())
3560 Or->setFlags(Flags);
3561
3562 MI.eraseFromParent();
3563 return Legalized;
3564}
Matt Arsenault6ce1b4f2019-07-10 16:31:19 +00003565
3566LegalizerHelper::LegalizeResult
3567LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
3568 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ?
3569 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE;
3570
3571 Register Dst = MI.getOperand(0).getReg();
3572 Register Src0 = MI.getOperand(1).getReg();
3573 Register Src1 = MI.getOperand(2).getReg();
3574 LLT Ty = MRI.getType(Dst);
3575
3576 if (!MI.getFlag(MachineInstr::FmNoNans)) {
3577 // Insert canonicalizes if it's possible we need to quiet to get correct
3578 // sNaN behavior.
3579
3580 // Note this must be done here, and not as an optimization combine in the
3581 // absence of a dedicate quiet-snan instruction as we're using an
3582 // omni-purpose G_FCANONICALIZE.
3583 if (!isKnownNeverSNaN(Src0, MRI))
3584 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);
3585
3586 if (!isKnownNeverSNaN(Src1, MRI))
3587 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
3588 }
3589
3590 // If there are no nans, it's safe to simply replace this with the non-IEEE
3591 // version.
3592 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags());
3593 MI.eraseFromParent();
3594 return Legalized;
3595}
Matt Arsenaultd9d30a42019-08-01 19:10:05 +00003596
3597LegalizerHelper::LegalizeResult
3598LegalizerHelper::lowerUnmergeValues(MachineInstr &MI) {
3599 const unsigned NumDst = MI.getNumOperands() - 1;
3600 const Register SrcReg = MI.getOperand(NumDst).getReg();
3601 LLT SrcTy = MRI.getType(SrcReg);
3602
3603 Register Dst0Reg = MI.getOperand(0).getReg();
3604 LLT DstTy = MRI.getType(Dst0Reg);
3605
3606
3607 // Expand scalarizing unmerge as bitcast to integer and shift.
3608 if (!DstTy.isVector() && SrcTy.isVector() &&
3609 SrcTy.getElementType() == DstTy) {
3610 LLT IntTy = LLT::scalar(SrcTy.getSizeInBits());
3611 Register Cast = MIRBuilder.buildBitcast(IntTy, SrcReg).getReg(0);
3612
3613 MIRBuilder.buildTrunc(Dst0Reg, Cast);
3614
3615 const unsigned DstSize = DstTy.getSizeInBits();
3616 unsigned Offset = DstSize;
3617 for (unsigned I = 1; I != NumDst; ++I, Offset += DstSize) {
3618 auto ShiftAmt = MIRBuilder.buildConstant(IntTy, Offset);
3619 auto Shift = MIRBuilder.buildLShr(IntTy, Cast, ShiftAmt);
3620 MIRBuilder.buildTrunc(MI.getOperand(I), Shift);
3621 }
3622
3623 MI.eraseFromParent();
3624 return Legalized;
3625 }
3626
3627 return UnableToLegalize;
3628}