[Alignment] Move OffsetToAlignment to Alignment.h
[llvm-complete.git] / lib / Target / Mips / MipsLegalizerInfo.cpp
blob2c9fc8ea4ad75aa79b65a717f63bbb003b5451b9
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 // FP instructions
126 getActionDefinitionsBuilder(G_FCONSTANT)
127 .legalFor({s32, s64});
129 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT})
130 .legalFor({s32, s64});
132 getActionDefinitionsBuilder(G_FCMP)
133 .legalFor({{s32, s32}, {s32, s64}})
134 .minScalar(0, s32);
136 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR})
137 .libcallFor({s32, s64});
139 getActionDefinitionsBuilder(G_FPEXT)
140 .legalFor({{s64, s32}});
142 getActionDefinitionsBuilder(G_FPTRUNC)
143 .legalFor({{s32, s64}});
145 // FP to int conversion instructions
146 getActionDefinitionsBuilder(G_FPTOSI)
147 .legalForCartesianProduct({s32}, {s64, s32})
148 .libcallForCartesianProduct({s64}, {s64, s32})
149 .minScalar(0, s32);
151 getActionDefinitionsBuilder(G_FPTOUI)
152 .libcallForCartesianProduct({s64}, {s64, s32})
153 .lowerForCartesianProduct({s32}, {s64, s32})
154 .minScalar(0, s32);
156 // Int to FP conversion instructions
157 getActionDefinitionsBuilder(G_SITOFP)
158 .legalForCartesianProduct({s64, s32}, {s32})
159 .libcallForCartesianProduct({s64, s32}, {s64})
160 .minScalar(1, s32);
162 getActionDefinitionsBuilder(G_UITOFP)
163 .libcallForCartesianProduct({s64, s32}, {s64})
164 .customForCartesianProduct({s64, s32}, {s32})
165 .minScalar(1, s32);
167 getActionDefinitionsBuilder(G_SEXT_INREG).lower();
169 computeTables();
170 verify(*ST.getInstrInfo());
173 bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
174 MachineRegisterInfo &MRI,
175 MachineIRBuilder &MIRBuilder,
176 GISelChangeObserver &Observer) const {
178 using namespace TargetOpcode;
180 MIRBuilder.setInstr(MI);
181 const MipsSubtarget &STI =
182 static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
183 const LLT s32 = LLT::scalar(32);
184 const LLT s64 = LLT::scalar(64);
186 switch (MI.getOpcode()) {
187 case G_UITOFP: {
188 Register Dst = MI.getOperand(0).getReg();
189 Register Src = MI.getOperand(1).getReg();
190 LLT DstTy = MRI.getType(Dst);
191 LLT SrcTy = MRI.getType(Src);
193 if (SrcTy != s32)
194 return false;
195 if (DstTy != s32 && DstTy != s64)
196 return false;
198 // Let 0xABCDEFGH be given unsigned in MI.getOperand(1). First let's convert
199 // unsigned to double. Mantissa has 52 bits so we use following trick:
200 // First make floating point bit mask 0x43300000ABCDEFGH.
201 // Mask represents 2^52 * 0x1.00000ABCDEFGH i.e. 0x100000ABCDEFGH.0 .
202 // Next, subtract 2^52 * 0x1.0000000000000 i.e. 0x10000000000000.0 from it.
203 // Done. Trunc double to float if needed.
205 MachineInstrBuilder Bitcast = MIRBuilder.buildInstr(
206 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, {s64},
207 {Src, MIRBuilder.buildConstant(s32, UINT32_C(0x43300000))});
208 Bitcast.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
209 *STI.getRegBankInfo());
211 MachineInstrBuilder TwoP52FP = MIRBuilder.buildFConstant(
212 s64, BitsToDouble(UINT64_C(0x4330000000000000)));
214 if (DstTy == s64)
215 MIRBuilder.buildFSub(Dst, Bitcast, TwoP52FP);
216 else {
217 MachineInstrBuilder ResF64 = MIRBuilder.buildFSub(s64, Bitcast, TwoP52FP);
218 MIRBuilder.buildFPTrunc(Dst, ResF64);
221 MI.eraseFromParent();
222 break;
224 default:
225 return false;
228 return true;
231 bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
232 MachineRegisterInfo &MRI,
233 MachineIRBuilder &MIRBuilder) const {
234 const MipsSubtarget &ST =
235 static_cast<const MipsSubtarget &>(MI.getMF()->getSubtarget());
236 const MipsInstrInfo &TII = *ST.getInstrInfo();
237 const MipsRegisterInfo &TRI = *ST.getRegisterInfo();
238 const RegisterBankInfo &RBI = *ST.getRegBankInfo();
239 MIRBuilder.setInstr(MI);
241 switch (MI.getIntrinsicID()) {
242 case Intrinsic::memcpy:
243 case Intrinsic::memset:
244 case Intrinsic::memmove:
245 if (createMemLibcall(MIRBuilder, MRI, MI) ==
246 LegalizerHelper::UnableToLegalize)
247 return false;
248 MI.eraseFromParent();
249 return true;
250 case Intrinsic::trap: {
251 MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
252 MI.eraseFromParent();
253 return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
255 default:
256 break;
258 return true;