blob: 3186b1b59c1ba0d20adec4657c00731ebad0e9c9 [file] [log] [blame]
Petar Jovanovicfac93e22018-02-23 11:06:40 +00001//===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===//
2//
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
Petar Jovanovicfac93e22018-02-23 11:06:40 +00006//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements the targeting of the Machinelegalizer class for Mips.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
13#include "MipsLegalizerInfo.h"
Roman Tereshinf34d7ec2018-05-31 16:16:49 +000014#include "MipsTargetMachine.h"
Petar Jovanovicaa978902018-10-08 23:59:37 +000015#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000016
17using namespace llvm;
18
19MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
Petar Jovanovic366857a2018-04-11 15:12:32 +000020 using namespace TargetOpcode;
21
Petar Avramovicb8276f22018-12-17 12:31:07 +000022 const LLT s1 = LLT::scalar(1);
Petar Jovanovic366857a2018-04-11 15:12:32 +000023 const LLT s32 = LLT::scalar(32);
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000024 const LLT s64 = LLT::scalar(64);
Petar Jovanovic021e4c82018-07-16 13:29:32 +000025 const LLT p0 = LLT::pointer(0, 32);
Petar Jovanovic366857a2018-04-11 15:12:32 +000026
Petar Avramovic0b17e592019-03-11 10:00:17 +000027 getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
Petar Jovanovic1fa50512018-08-26 07:25:33 +000028 .legalFor({s32})
Petar Avramovicb8276f22018-12-17 12:31:07 +000029 .clampScalar(0, s32, s32);
30
Petar Avramovica48285a2019-03-01 07:25:44 +000031 getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO})
Petar Avramovicb8276f22018-12-17 12:31:07 +000032 .lowerFor({{s32, s1}});
Petar Jovanovic366857a2018-04-11 15:12:32 +000033
Petar Avramovica48285a2019-03-01 07:25:44 +000034 getActionDefinitionsBuilder(G_UMULH)
Petar Avramovic5229f472019-03-11 10:08:44 +000035 .legalFor({s32})
36 .maxScalar(0, s32);
Petar Avramovica48285a2019-03-01 07:25:44 +000037
Petar Jovanovic021e4c82018-07-16 13:29:32 +000038 getActionDefinitionsBuilder({G_LOAD, G_STORE})
Matt Arsenault530d05e2019-02-14 22:41:09 +000039 .legalForTypesWithMemDesc({{s32, p0, 8, 8},
40 {s32, p0, 16, 8},
41 {s32, p0, 32, 8},
Petar Avramovicec575f62019-07-08 14:36:36 +000042 {s64, p0, 64, 8},
Matt Arsenault530d05e2019-02-14 22:41:09 +000043 {p0, p0, 32, 8}})
Petar Avramovicc98b26d2019-02-08 14:27:23 +000044 .minScalar(0, s32);
Petar Jovanovic021e4c82018-07-16 13:29:32 +000045
Petar Avramovic75e43a62019-09-12 11:32:38 +000046 getActionDefinitionsBuilder(G_IMPLICIT_DEF)
47 .legalFor({s32, s64});
48
Petar Avramovicaa699b22019-07-08 14:45:52 +000049 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
50 .legalFor({{s32, s64}});
51
Petar Avramovicec575f62019-07-08 14:36:36 +000052 getActionDefinitionsBuilder(G_MERGE_VALUES)
53 .legalFor({{s64, s32}});
54
Petar Avramovic79df8592019-01-24 10:27:21 +000055 getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
Petar Avramovic7f581df2019-08-21 09:43:20 +000056 .legalForTypesWithMemDesc({{s32, p0, 8, 8},
57 {s32, p0, 16, 8}})
58 .clampScalar(0, s32, s32);
Petar Avramovic79df8592019-01-24 10:27:21 +000059
Petar Avramovice406aa72019-08-21 09:35:02 +000060 getActionDefinitionsBuilder({G_ZEXT, G_SEXT})
61 .legalIf([](const LegalityQuery &Query) { return false; })
62 .maxScalar(0, s32);
63
Petar Avramovic5b4c5c22019-08-21 09:26:39 +000064 getActionDefinitionsBuilder(G_TRUNC)
65 .legalIf([](const LegalityQuery &Query) { return false; })
66 .maxScalar(1, s32);
67
Petar Avramovic09dff332018-12-25 14:42:30 +000068 getActionDefinitionsBuilder(G_SELECT)
Petar Avramovicdbb6d012019-07-09 14:30:29 +000069 .legalForCartesianProduct({p0, s32, s64}, {s32})
Petar Avramovic09dff332018-12-25 14:42:30 +000070 .minScalar(0, s32)
71 .minScalar(1, s32);
72
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +000073 getActionDefinitionsBuilder(G_BRCOND)
74 .legalFor({s32})
75 .minScalar(0, s32);
76
Petar Avramoviccaef9302019-08-08 10:21:12 +000077 getActionDefinitionsBuilder(G_BRJT)
78 .legalFor({{p0, s32}});
79
Petar Avramovicff6ac1e2019-09-12 11:44:36 +000080 getActionDefinitionsBuilder(G_BRINDIRECT)
81 .legalFor({p0});
82
Petar Avramovic14c7ecf2019-02-14 12:36:19 +000083 getActionDefinitionsBuilder(G_PHI)
Petar Avramovicbe20e362019-07-09 14:36:17 +000084 .legalFor({p0, s32, s64})
Petar Avramovic14c7ecf2019-02-14 12:36:19 +000085 .minScalar(0, s32);
86
Petar Avramovic150fd432018-12-18 11:36:14 +000087 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
88 .legalFor({s32})
89 .clampScalar(0, s32, s32);
90
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +000091 getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV})
92 .legalFor({s32})
93 .minScalar(0, s32)
94 .libcallFor({s64});
95
Matt Arsenault30989e42019-01-22 21:42:11 +000096 getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
Petar Avramovic61bf2672019-08-21 09:31:29 +000097 .legalFor({{s32, s32}})
Petar Avramovic4a2a6532019-08-27 14:41:44 +000098 .clampScalar(1, s32, s32)
99 .clampScalar(0, s32, s32);
Matt Arsenault30989e42019-01-22 21:42:11 +0000100
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000101 getActionDefinitionsBuilder(G_ICMP)
Petar Avramovic1e626352019-07-17 12:08:01 +0000102 .legalForCartesianProduct({s32}, {s32, p0})
103 .clampScalar(1, s32, s32)
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000104 .minScalar(0, s32);
105
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000106 getActionDefinitionsBuilder(G_CONSTANT)
Petar Jovanovic8a084122018-10-17 10:30:03 +0000107 .legalFor({s32})
Petar Avramovic2cefaa22018-11-09 14:21:16 +0000108 .clampScalar(0, s32, s32);
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000109
Petar Avramovicb1fc6f62019-07-26 13:08:06 +0000110 getActionDefinitionsBuilder({G_GEP, G_INTTOPTR})
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000111 .legalFor({{p0, s32}});
112
Petar Avramovicb1fc6f62019-07-26 13:08:06 +0000113 getActionDefinitionsBuilder(G_PTRTOINT)
114 .legalFor({{s32, p0}});
115
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000116 getActionDefinitionsBuilder(G_FRAME_INDEX)
117 .legalFor({p0});
118
Petar Avramoviccaef9302019-08-08 10:21:12 +0000119 getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE})
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000120 .legalFor({p0});
121
Petar Avramovic646e1f72019-09-12 11:39:50 +0000122 getActionDefinitionsBuilder(G_DYN_STACKALLOC)
123 .lowerFor({{p0, s32}});
124
Petar Avramovicc063b0b2019-09-23 08:11:41 +0000125 getActionDefinitionsBuilder(G_VASTART)
126 .legalFor({p0});
127
Petar Avramovicafa3afa2019-04-03 14:12:59 +0000128 // FP instructions
129 getActionDefinitionsBuilder(G_FCONSTANT)
130 .legalFor({s32, s64});
131
Petar Avramovic81132ce2019-06-06 10:00:41 +0000132 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT})
Petar Avramovicafa3afa2019-04-03 14:12:59 +0000133 .legalFor({s32, s64});
134
Petar Avramovic22e99c42019-06-05 14:03:13 +0000135 getActionDefinitionsBuilder(G_FCMP)
136 .legalFor({{s32, s32}, {s32, s64}})
137 .minScalar(0, s32);
138
Petar Avramovicfaaa2b52019-06-06 09:02:24 +0000139 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR})
140 .libcallFor({s32, s64});
141
Petar Avramovica7d00062019-06-06 09:16:58 +0000142 getActionDefinitionsBuilder(G_FPEXT)
143 .legalFor({{s64, s32}});
144
145 getActionDefinitionsBuilder(G_FPTRUNC)
146 .legalFor({{s32, s64}});
147
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000148 // FP to int conversion instructions
149 getActionDefinitionsBuilder(G_FPTOSI)
150 .legalForCartesianProduct({s32}, {s64, s32})
151 .libcallForCartesianProduct({s64}, {s64, s32})
152 .minScalar(0, s32);
153
154 getActionDefinitionsBuilder(G_FPTOUI)
155 .libcallForCartesianProduct({s64}, {s64, s32})
Petar Avramovic6412b562019-08-30 05:44:02 +0000156 .lowerForCartesianProduct({s32}, {s64, s32})
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000157 .minScalar(0, s32);
158
Petar Avramovic153bd242019-06-20 09:05:02 +0000159 // Int to FP conversion instructions
160 getActionDefinitionsBuilder(G_SITOFP)
161 .legalForCartesianProduct({s64, s32}, {s32})
162 .libcallForCartesianProduct({s64, s32}, {s64})
163 .minScalar(1, s32);
164
165 getActionDefinitionsBuilder(G_UITOFP)
166 .libcallForCartesianProduct({s64, s32}, {s64})
Petar Avramovice96892a2019-08-30 05:51:12 +0000167 .customForCartesianProduct({s64, s32}, {s32})
Petar Avramovic153bd242019-06-20 09:05:02 +0000168 .minScalar(1, s32);
169
Daniel Sanderse9a57c22019-08-09 21:11:20 +0000170 getActionDefinitionsBuilder(G_SEXT_INREG).lower();
171
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000172 computeTables();
Roman Tereshinf34d7ec2018-05-31 16:16:49 +0000173 verify(*ST.getInstrInfo());
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000174}
Petar Jovanovicaa978902018-10-08 23:59:37 +0000175
176bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
177 MachineRegisterInfo &MRI,
Aditya Nandakumarf75d4f32018-12-05 20:14:52 +0000178 MachineIRBuilder &MIRBuilder,
179 GISelChangeObserver &Observer) const {
Petar Jovanovicaa978902018-10-08 23:59:37 +0000180
181 using namespace TargetOpcode;
182
183 MIRBuilder.setInstr(MI);
Petar Avramovice96892a2019-08-30 05:51:12 +0000184 const MipsSubtarget &STI =
185 static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
186 const LLT s32 = LLT::scalar(32);
187 const LLT s64 = LLT::scalar(64);
Petar Jovanovicaa978902018-10-08 23:59:37 +0000188
Petar Avramovice96892a2019-08-30 05:51:12 +0000189 switch (MI.getOpcode()) {
190 case G_UITOFP: {
191 Register Dst = MI.getOperand(0).getReg();
192 Register Src = MI.getOperand(1).getReg();
193 LLT DstTy = MRI.getType(Dst);
194 LLT SrcTy = MRI.getType(Src);
195
196 if (SrcTy != s32)
197 return false;
198 if (DstTy != s32 && DstTy != s64)
199 return false;
200
201 // Let 0xABCDEFGH be given unsigned in MI.getOperand(1). First let's convert
202 // unsigned to double. Mantissa has 52 bits so we use following trick:
203 // First make floating point bit mask 0x43300000ABCDEFGH.
204 // Mask represents 2^52 * 0x1.00000ABCDEFGH i.e. 0x100000ABCDEFGH.0 .
205 // Next, subtract 2^52 * 0x1.0000000000000 i.e. 0x10000000000000.0 from it.
206 // Done. Trunc double to float if needed.
207
208 MachineInstrBuilder Bitcast = MIRBuilder.buildInstr(
209 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, {s64},
210 {Src, MIRBuilder.buildConstant(s32, UINT32_C(0x43300000))});
211 Bitcast.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
212 *STI.getRegBankInfo());
213
214 MachineInstrBuilder TwoP52FP = MIRBuilder.buildFConstant(
215 s64, BitsToDouble(UINT64_C(0x4330000000000000)));
216
217 if (DstTy == s64)
218 MIRBuilder.buildFSub(Dst, Bitcast, TwoP52FP);
219 else {
220 MachineInstrBuilder ResF64 = MIRBuilder.buildFSub(s64, Bitcast, TwoP52FP);
221 MIRBuilder.buildFPTrunc(Dst, ResF64);
222 }
223
224 MI.eraseFromParent();
225 break;
226 }
227 default:
228 return false;
229 }
230
231 return true;
Petar Jovanovicaa978902018-10-08 23:59:37 +0000232}
Amara Emersoncf12c782019-07-19 00:24:45 +0000233
Petar Avramovicf5c7fe02019-09-05 11:16:37 +0000234bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
235 MachineRegisterInfo &MRI,
Amara Emersoncf12c782019-07-19 00:24:45 +0000236 MachineIRBuilder &MIRBuilder) const {
Petar Avramovicf5c7fe02019-09-05 11:16:37 +0000237 const MipsSubtarget &ST =
238 static_cast<const MipsSubtarget &>(MI.getMF()->getSubtarget());
239 const MipsInstrInfo &TII = *ST.getInstrInfo();
240 const MipsRegisterInfo &TRI = *ST.getRegisterInfo();
241 const RegisterBankInfo &RBI = *ST.getRegBankInfo();
242 MIRBuilder.setInstr(MI);
243
Amara Emersoncf12c782019-07-19 00:24:45 +0000244 switch (MI.getIntrinsicID()) {
245 case Intrinsic::memcpy:
246 case Intrinsic::memset:
247 case Intrinsic::memmove:
248 if (createMemLibcall(MIRBuilder, MRI, MI) ==
249 LegalizerHelper::UnableToLegalize)
250 return false;
251 MI.eraseFromParent();
252 return true;
Petar Avramovicf5c7fe02019-09-05 11:16:37 +0000253 case Intrinsic::trap: {
254 MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
255 MI.eraseFromParent();
256 return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
257 }
Petar Avramovicc063b0b2019-09-23 08:11:41 +0000258 case Intrinsic::vacopy: {
259 Register Tmp = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
260 MachinePointerInfo MPO;
261 MIRBuilder.buildLoad(Tmp, MI.getOperand(2),
262 *MI.getMF()->getMachineMemOperand(
263 MPO, MachineMemOperand::MOLoad, 4, 4));
264 MIRBuilder.buildStore(Tmp, MI.getOperand(1),
265 *MI.getMF()->getMachineMemOperand(
266 MPO, MachineMemOperand::MOStore, 4, 4));
267 MI.eraseFromParent();
268 return true;
269 }
Amara Emersoncf12c782019-07-19 00:24:45 +0000270 default:
271 break;
272 }
273 return true;
274}