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 //===----------------------------------------------------------------------===// 12 13 #include "MipsLegalizerInfo.h" 14 #include "MipsTargetMachine.h" 15 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 16 17 using namespace llvm; 18 19 MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { 20 using namespace TargetOpcode; 21 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); 26 27 getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL}) 28 .legalFor({s32}) 29 .clampScalar(0, s32, s32); 30 31 getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO}) 32 .lowerFor({{s32, s1}}); 33 34 getActionDefinitionsBuilder(G_UMULH) 35 .legalFor({s32}) 36 .maxScalar(0, s32); 37 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); 45 46 getActionDefinitionsBuilder(G_IMPLICIT_DEF) 47 .legalFor({s32, s64}); 48 49 getActionDefinitionsBuilder(G_UNMERGE_VALUES) 50 .legalFor({{s32, s64}}); 51 52 getActionDefinitionsBuilder(G_MERGE_VALUES) 53 .legalFor({{s64, s32}}); 54 55 getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD}) 56 .legalForTypesWithMemDesc({{s32, p0, 8, 8}, 57 {s32, p0, 16, 8}}) 58 .clampScalar(0, s32, s32); 59 60 getActionDefinitionsBuilder({G_ZEXT, G_SEXT}) 61 .legalIf([](const LegalityQuery &Query) { return false; }) 62 .maxScalar(0, s32); 63 64 getActionDefinitionsBuilder(G_TRUNC) 65 .legalIf([](const LegalityQuery &Query) { return false; }) 66 .maxScalar(1, s32); 67 68 getActionDefinitionsBuilder(G_SELECT) 69 .legalForCartesianProduct({p0, s32, s64}, {s32}) 70 .minScalar(0, s32) 71 .minScalar(1, s32); 72 73 getActionDefinitionsBuilder(G_BRCOND) 74 .legalFor({s32}) 75 .minScalar(0, s32); 76 77 getActionDefinitionsBuilder(G_BRJT) 78 .legalFor({{p0, s32}}); 79 80 getActionDefinitionsBuilder(G_BRINDIRECT) 81 .legalFor({p0}); 82 83 getActionDefinitionsBuilder(G_PHI) 84 .legalFor({p0, s32, s64}) 85 .minScalar(0, s32); 86 87 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR}) 88 .legalFor({s32}) 89 .clampScalar(0, s32, s32); 90 91 getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV}) 92 .legalFor({s32}) 93 .minScalar(0, s32) 94 .libcallFor({s64}); 95 96 getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR}) 97 .legalFor({{s32, s32}}) 98 .clampScalar(1, s32, s32) 99 .clampScalar(0, s32, s32); 100 101 getActionDefinitionsBuilder(G_ICMP) 102 .legalForCartesianProduct({s32}, {s32, p0}) 103 .clampScalar(1, s32, s32) 104 .minScalar(0, s32); 105 106 getActionDefinitionsBuilder(G_CONSTANT) 107 .legalFor({s32}) 108 .clampScalar(0, s32, s32); 109 110 getActionDefinitionsBuilder({G_GEP, G_INTTOPTR}) 111 .legalFor({{p0, s32}}); 112 113 getActionDefinitionsBuilder(G_PTRTOINT) 114 .legalFor({{s32, p0}}); 115 116 getActionDefinitionsBuilder(G_FRAME_INDEX) 117 .legalFor({p0}); 118 119 getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE}) 120 .legalFor({p0}); 121 122 getActionDefinitionsBuilder(G_DYN_STACKALLOC) 123 .lowerFor({{p0, s32}}); 124 125 // FP instructions 126 getActionDefinitionsBuilder(G_FCONSTANT) 127 .legalFor({s32, s64}); 128 129 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT}) 130 .legalFor({s32, s64}); 131 132 getActionDefinitionsBuilder(G_FCMP) 133 .legalFor({{s32, s32}, {s32, s64}}) 134 .minScalar(0, s32); 135 136 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR}) 137 .libcallFor({s32, s64}); 138 139 getActionDefinitionsBuilder(G_FPEXT) 140 .legalFor({{s64, s32}}); 141 142 getActionDefinitionsBuilder(G_FPTRUNC) 143 .legalFor({{s32, s64}}); 144 145 // FP to int conversion instructions 146 getActionDefinitionsBuilder(G_FPTOSI) 147 .legalForCartesianProduct({s32}, {s64, s32}) 148 .libcallForCartesianProduct({s64}, {s64, s32}) 149 .minScalar(0, s32); 150 151 getActionDefinitionsBuilder(G_FPTOUI) 152 .libcallForCartesianProduct({s64}, {s64, s32}) 153 .lowerForCartesianProduct({s32}, {s64, s32}) 154 .minScalar(0, s32); 155 156 // Int to FP conversion instructions 157 getActionDefinitionsBuilder(G_SITOFP) 158 .legalForCartesianProduct({s64, s32}, {s32}) 159 .libcallForCartesianProduct({s64, s32}, {s64}) 160 .minScalar(1, s32); 161 162 getActionDefinitionsBuilder(G_UITOFP) 163 .libcallForCartesianProduct({s64, s32}, {s64}) 164 .customForCartesianProduct({s64, s32}, {s32}) 165 .minScalar(1, s32); 166 167 getActionDefinitionsBuilder(G_SEXT_INREG).lower(); 168 169 computeTables(); 170 verify(*ST.getInstrInfo()); 171 } 172 173 bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI, 174 MachineRegisterInfo &MRI, 175 MachineIRBuilder &MIRBuilder, 176 GISelChangeObserver &Observer) const { 177 178 using namespace TargetOpcode; 179 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); 185 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); 192 193 if (SrcTy != s32) 194 return false; 195 if (DstTy != s32 && DstTy != s64) 196 return false; 197 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. 204 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()); 210 211 MachineInstrBuilder TwoP52FP = MIRBuilder.buildFConstant( 212 s64, BitsToDouble(UINT64_C(0x4330000000000000))); 213 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); 219 } 220 221 MI.eraseFromParent(); 222 break; 223 } 224 default: 225 return false; 226 } 227 228 return true; 229 } 230 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); 240 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); 254 } 255 default: 256 break; 257 } 258 return true; 259 } 260