[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
[llvm-complete.git] / lib / Target / Mips / MipsLegalizerInfo.cpp
blob3186b1b59c1ba0d20adec4657c00731ebad0e9c9
1 //===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the targeting of the Machinelegalizer class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
13 #include "MipsLegalizerInfo.h"
14 #include "MipsTargetMachine.h"
15 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17 using namespace llvm;
19 MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
20 using namespace TargetOpcode;
22 const LLT s1 = LLT::scalar(1);
23 const LLT s32 = LLT::scalar(32);
24 const LLT s64 = LLT::scalar(64);
25 const LLT p0 = LLT::pointer(0, 32);
27 getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
28 .legalFor({s32})
29 .clampScalar(0, s32, s32);
31 getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO})
32 .lowerFor({{s32, s1}});
34 getActionDefinitionsBuilder(G_UMULH)
35 .legalFor({s32})
36 .maxScalar(0, s32);
38 getActionDefinitionsBuilder({G_LOAD, G_STORE})
39 .legalForTypesWithMemDesc({{s32, p0, 8, 8},
40 {s32, p0, 16, 8},
41 {s32, p0, 32, 8},
42 {s64, p0, 64, 8},
43 {p0, p0, 32, 8}})
44 .minScalar(0, s32);
46 getActionDefinitionsBuilder(G_IMPLICIT_DEF)
47 .legalFor({s32, s64});
49 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
50 .legalFor({{s32, s64}});
52 getActionDefinitionsBuilder(G_MERGE_VALUES)
53 .legalFor({{s64, s32}});
55 getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
56 .legalForTypesWithMemDesc({{s32, p0, 8, 8},
57 {s32, p0, 16, 8}})
58 .clampScalar(0, s32, s32);
60 getActionDefinitionsBuilder({G_ZEXT, G_SEXT})
61 .legalIf([](const LegalityQuery &Query) { return false; })
62 .maxScalar(0, s32);
64 getActionDefinitionsBuilder(G_TRUNC)
65 .legalIf([](const LegalityQuery &Query) { return false; })
66 .maxScalar(1, s32);
68 getActionDefinitionsBuilder(G_SELECT)
69 .legalForCartesianProduct({p0, s32, s64}, {s32})
70 .minScalar(0, s32)
71 .minScalar(1, s32);
73 getActionDefinitionsBuilder(G_BRCOND)
74 .legalFor({s32})
75 .minScalar(0, s32);
77 getActionDefinitionsBuilder(G_BRJT)
78 .legalFor({{p0, s32}});
80 getActionDefinitionsBuilder(G_BRINDIRECT)
81 .legalFor({p0});
83 getActionDefinitionsBuilder(G_PHI)
84 .legalFor({p0, s32, s64})
85 .minScalar(0, s32);
87 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
88 .legalFor({s32})
89 .clampScalar(0, s32, s32);
91 getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV})
92 .legalFor({s32})
93 .minScalar(0, s32)
94 .libcallFor({s64});
96 getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
97 .legalFor({{s32, s32}})
98 .clampScalar(1, s32, s32)
99 .clampScalar(0, s32, s32);
101 getActionDefinitionsBuilder(G_ICMP)
102 .legalForCartesianProduct({s32}, {s32, p0})
103 .clampScalar(1, s32, s32)
104 .minScalar(0, s32);
106 getActionDefinitionsBuilder(G_CONSTANT)
107 .legalFor({s32})
108 .clampScalar(0, s32, s32);
110 getActionDefinitionsBuilder({G_GEP, G_INTTOPTR})
111 .legalFor({{p0, s32}});
113 getActionDefinitionsBuilder(G_PTRTOINT)
114 .legalFor({{s32, p0}});
116 getActionDefinitionsBuilder(G_FRAME_INDEX)
117 .legalFor({p0});
119 getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE})
120 .legalFor({p0});
122 getActionDefinitionsBuilder(G_DYN_STACKALLOC)
123 .lowerFor({{p0, s32}});
125 getActionDefinitionsBuilder(G_VASTART)
126 .legalFor({p0});
128 // FP instructions
129 getActionDefinitionsBuilder(G_FCONSTANT)
130 .legalFor({s32, s64});
132 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT})
133 .legalFor({s32, s64});
135 getActionDefinitionsBuilder(G_FCMP)
136 .legalFor({{s32, s32}, {s32, s64}})
137 .minScalar(0, s32);
139 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR})
140 .libcallFor({s32, s64});
142 getActionDefinitionsBuilder(G_FPEXT)
143 .legalFor({{s64, s32}});
145 getActionDefinitionsBuilder(G_FPTRUNC)
146 .legalFor({{s32, s64}});
148 // FP to int conversion instructions
149 getActionDefinitionsBuilder(G_FPTOSI)
150 .legalForCartesianProduct({s32}, {s64, s32})
151 .libcallForCartesianProduct({s64}, {s64, s32})
152 .minScalar(0, s32);
154 getActionDefinitionsBuilder(G_FPTOUI)
155 .libcallForCartesianProduct({s64}, {s64, s32})
156 .lowerForCartesianProduct({s32}, {s64, s32})
157 .minScalar(0, s32);
159 // Int to FP conversion instructions
160 getActionDefinitionsBuilder(G_SITOFP)
161 .legalForCartesianProduct({s64, s32}, {s32})
162 .libcallForCartesianProduct({s64, s32}, {s64})
163 .minScalar(1, s32);
165 getActionDefinitionsBuilder(G_UITOFP)
166 .libcallForCartesianProduct({s64, s32}, {s64})
167 .customForCartesianProduct({s64, s32}, {s32})
168 .minScalar(1, s32);
170 getActionDefinitionsBuilder(G_SEXT_INREG).lower();
172 computeTables();
173 verify(*ST.getInstrInfo());
176 bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
177 MachineRegisterInfo &MRI,
178 MachineIRBuilder &MIRBuilder,
179 GISelChangeObserver &Observer) const {
181 using namespace TargetOpcode;
183 MIRBuilder.setInstr(MI);
184 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);
189 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);
196 if (SrcTy != s32)
197 return false;
198 if (DstTy != s32 && DstTy != s64)
199 return false;
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.
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());
214 MachineInstrBuilder TwoP52FP = MIRBuilder.buildFConstant(
215 s64, BitsToDouble(UINT64_C(0x4330000000000000)));
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);
224 MI.eraseFromParent();
225 break;
227 default:
228 return false;
231 return true;
234 bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
235 MachineRegisterInfo &MRI,
236 MachineIRBuilder &MIRBuilder) const {
237 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);
244 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;
253 case Intrinsic::trap: {
254 MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
255 MI.eraseFromParent();
256 return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
258 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;
270 default:
271 break;
273 return true;