1*0b57cec5SDimitry Andric //===- MipsFastISel.cpp - Mips FastISel implementation --------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// 9*0b57cec5SDimitry Andric /// \file 10*0b57cec5SDimitry Andric /// This file defines the MIPS-specific support for the FastISel class. 11*0b57cec5SDimitry Andric /// Some of the target-specific code is generated by tablegen in the file 12*0b57cec5SDimitry Andric /// MipsGenFastISel.inc, which is #included here. 13*0b57cec5SDimitry Andric /// 14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h" 17*0b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h" 18*0b57cec5SDimitry Andric #include "MipsCCState.h" 19*0b57cec5SDimitry Andric #include "MipsISelLowering.h" 20*0b57cec5SDimitry Andric #include "MipsInstrInfo.h" 21*0b57cec5SDimitry Andric #include "MipsMachineFunction.h" 22*0b57cec5SDimitry Andric #include "MipsSubtarget.h" 23*0b57cec5SDimitry Andric #include "MipsTargetMachine.h" 24*0b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 25*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 26*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 27*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 28*0b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 29*0b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 30*0b57cec5SDimitry Andric #include "llvm/CodeGen/FastISel.h" 31*0b57cec5SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h" 32*0b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h" 33*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 34*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 35*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 36*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 37*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 38*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 39*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 40*0b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h" 41*0b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 42*0b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 43*0b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 44*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 45*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 46*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 47*0b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h" 48*0b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 49*0b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 50*0b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 51*0b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 52*0b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 53*0b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 54*0b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 55*0b57cec5SDimitry Andric #include "llvm/IR/Type.h" 56*0b57cec5SDimitry Andric #include "llvm/IR/User.h" 57*0b57cec5SDimitry Andric #include "llvm/IR/Value.h" 58*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 59*0b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 60*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 61*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 62*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 63*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 64*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 65*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 66*0b57cec5SDimitry Andric #include "llvm/Support/MachineValueType.h" 67*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 68*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 69*0b57cec5SDimitry Andric #include <algorithm> 70*0b57cec5SDimitry Andric #include <array> 71*0b57cec5SDimitry Andric #include <cassert> 72*0b57cec5SDimitry Andric #include <cstdint> 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric #define DEBUG_TYPE "mips-fastisel" 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric using namespace llvm; 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric extern cl::opt<bool> EmitJalrReloc; 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric namespace { 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric class MipsFastISel final : public FastISel { 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric // All possible address modes. 85*0b57cec5SDimitry Andric class Address { 86*0b57cec5SDimitry Andric public: 87*0b57cec5SDimitry Andric using BaseKind = enum { RegBase, FrameIndexBase }; 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric private: 90*0b57cec5SDimitry Andric BaseKind Kind = RegBase; 91*0b57cec5SDimitry Andric union { 92*0b57cec5SDimitry Andric unsigned Reg; 93*0b57cec5SDimitry Andric int FI; 94*0b57cec5SDimitry Andric } Base; 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric int64_t Offset = 0; 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric const GlobalValue *GV = nullptr; 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric public: 101*0b57cec5SDimitry Andric // Innocuous defaults for our address. 102*0b57cec5SDimitry Andric Address() { Base.Reg = 0; } 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric void setKind(BaseKind K) { Kind = K; } 105*0b57cec5SDimitry Andric BaseKind getKind() const { return Kind; } 106*0b57cec5SDimitry Andric bool isRegBase() const { return Kind == RegBase; } 107*0b57cec5SDimitry Andric bool isFIBase() const { return Kind == FrameIndexBase; } 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric void setReg(unsigned Reg) { 110*0b57cec5SDimitry Andric assert(isRegBase() && "Invalid base register access!"); 111*0b57cec5SDimitry Andric Base.Reg = Reg; 112*0b57cec5SDimitry Andric } 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric unsigned getReg() const { 115*0b57cec5SDimitry Andric assert(isRegBase() && "Invalid base register access!"); 116*0b57cec5SDimitry Andric return Base.Reg; 117*0b57cec5SDimitry Andric } 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric void setFI(unsigned FI) { 120*0b57cec5SDimitry Andric assert(isFIBase() && "Invalid base frame index access!"); 121*0b57cec5SDimitry Andric Base.FI = FI; 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric unsigned getFI() const { 125*0b57cec5SDimitry Andric assert(isFIBase() && "Invalid base frame index access!"); 126*0b57cec5SDimitry Andric return Base.FI; 127*0b57cec5SDimitry Andric } 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric void setOffset(int64_t Offset_) { Offset = Offset_; } 130*0b57cec5SDimitry Andric int64_t getOffset() const { return Offset; } 131*0b57cec5SDimitry Andric void setGlobalValue(const GlobalValue *G) { GV = G; } 132*0b57cec5SDimitry Andric const GlobalValue *getGlobalValue() { return GV; } 133*0b57cec5SDimitry Andric }; 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can 136*0b57cec5SDimitry Andric /// make the right decision when generating code for different targets. 137*0b57cec5SDimitry Andric const TargetMachine &TM; 138*0b57cec5SDimitry Andric const MipsSubtarget *Subtarget; 139*0b57cec5SDimitry Andric const TargetInstrInfo &TII; 140*0b57cec5SDimitry Andric const TargetLowering &TLI; 141*0b57cec5SDimitry Andric MipsFunctionInfo *MFI; 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric // Convenience variables to avoid some queries. 144*0b57cec5SDimitry Andric LLVMContext *Context; 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric bool fastLowerArguments() override; 147*0b57cec5SDimitry Andric bool fastLowerCall(CallLoweringInfo &CLI) override; 148*0b57cec5SDimitry Andric bool fastLowerIntrinsicCall(const IntrinsicInst *II) override; 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle 151*0b57cec5SDimitry Andric // floating point but not reject doing fast-isel in other 152*0b57cec5SDimitry Andric // situations 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric private: 155*0b57cec5SDimitry Andric // Selection routines. 156*0b57cec5SDimitry Andric bool selectLogicalOp(const Instruction *I); 157*0b57cec5SDimitry Andric bool selectLoad(const Instruction *I); 158*0b57cec5SDimitry Andric bool selectStore(const Instruction *I); 159*0b57cec5SDimitry Andric bool selectBranch(const Instruction *I); 160*0b57cec5SDimitry Andric bool selectSelect(const Instruction *I); 161*0b57cec5SDimitry Andric bool selectCmp(const Instruction *I); 162*0b57cec5SDimitry Andric bool selectFPExt(const Instruction *I); 163*0b57cec5SDimitry Andric bool selectFPTrunc(const Instruction *I); 164*0b57cec5SDimitry Andric bool selectFPToInt(const Instruction *I, bool IsSigned); 165*0b57cec5SDimitry Andric bool selectRet(const Instruction *I); 166*0b57cec5SDimitry Andric bool selectTrunc(const Instruction *I); 167*0b57cec5SDimitry Andric bool selectIntExt(const Instruction *I); 168*0b57cec5SDimitry Andric bool selectShift(const Instruction *I); 169*0b57cec5SDimitry Andric bool selectDivRem(const Instruction *I, unsigned ISDOpcode); 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric // Utility helper routines. 172*0b57cec5SDimitry Andric bool isTypeLegal(Type *Ty, MVT &VT); 173*0b57cec5SDimitry Andric bool isTypeSupported(Type *Ty, MVT &VT); 174*0b57cec5SDimitry Andric bool isLoadTypeLegal(Type *Ty, MVT &VT); 175*0b57cec5SDimitry Andric bool computeAddress(const Value *Obj, Address &Addr); 176*0b57cec5SDimitry Andric bool computeCallAddress(const Value *V, Address &Addr); 177*0b57cec5SDimitry Andric void simplifyAddress(Address &Addr); 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric // Emit helper routines. 180*0b57cec5SDimitry Andric bool emitCmp(unsigned DestReg, const CmpInst *CI); 181*0b57cec5SDimitry Andric bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, 182*0b57cec5SDimitry Andric unsigned Alignment = 0); 183*0b57cec5SDimitry Andric bool emitStore(MVT VT, unsigned SrcReg, Address Addr, 184*0b57cec5SDimitry Andric MachineMemOperand *MMO = nullptr); 185*0b57cec5SDimitry Andric bool emitStore(MVT VT, unsigned SrcReg, Address &Addr, 186*0b57cec5SDimitry Andric unsigned Alignment = 0); 187*0b57cec5SDimitry Andric unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt); 188*0b57cec5SDimitry Andric bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric bool IsZExt); 191*0b57cec5SDimitry Andric bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); 194*0b57cec5SDimitry Andric bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, 195*0b57cec5SDimitry Andric unsigned DestReg); 196*0b57cec5SDimitry Andric bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, 197*0b57cec5SDimitry Andric unsigned DestReg); 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned); 200*0b57cec5SDimitry Andric 201*0b57cec5SDimitry Andric unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS, 202*0b57cec5SDimitry Andric const Value *RHS); 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric unsigned materializeFP(const ConstantFP *CFP, MVT VT); 205*0b57cec5SDimitry Andric unsigned materializeGV(const GlobalValue *GV, MVT VT); 206*0b57cec5SDimitry Andric unsigned materializeInt(const Constant *C, MVT VT); 207*0b57cec5SDimitry Andric unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); 208*0b57cec5SDimitry Andric unsigned materializeExternalCallSym(MCSymbol *Syn); 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric MachineInstrBuilder emitInst(unsigned Opc) { 211*0b57cec5SDimitry Andric return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) { 215*0b57cec5SDimitry Andric return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), 216*0b57cec5SDimitry Andric DstReg); 217*0b57cec5SDimitry Andric } 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg, 220*0b57cec5SDimitry Andric unsigned MemReg, int64_t MemOffset) { 221*0b57cec5SDimitry Andric return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset); 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg, 225*0b57cec5SDimitry Andric unsigned MemReg, int64_t MemOffset) { 226*0b57cec5SDimitry Andric return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric unsigned fastEmitInst_rr(unsigned MachineInstOpcode, 230*0b57cec5SDimitry Andric const TargetRegisterClass *RC, 231*0b57cec5SDimitry Andric unsigned Op0, bool Op0IsKill, 232*0b57cec5SDimitry Andric unsigned Op1, bool Op1IsKill); 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric // for some reason, this default is not generated by tablegen 235*0b57cec5SDimitry Andric // so we explicitly generate it here. 236*0b57cec5SDimitry Andric unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC, 237*0b57cec5SDimitry Andric unsigned Op0, bool Op0IsKill, uint64_t imm1, 238*0b57cec5SDimitry Andric uint64_t imm2, unsigned Op3, bool Op3IsKill) { 239*0b57cec5SDimitry Andric return 0; 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric // Call handling routines. 243*0b57cec5SDimitry Andric private: 244*0b57cec5SDimitry Andric CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const; 245*0b57cec5SDimitry Andric bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs, 246*0b57cec5SDimitry Andric unsigned &NumBytes); 247*0b57cec5SDimitry Andric bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes); 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric const MipsABIInfo &getABI() const { 250*0b57cec5SDimitry Andric return static_cast<const MipsTargetMachine &>(TM).getABI(); 251*0b57cec5SDimitry Andric } 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric public: 254*0b57cec5SDimitry Andric // Backend specific FastISel code. 255*0b57cec5SDimitry Andric explicit MipsFastISel(FunctionLoweringInfo &funcInfo, 256*0b57cec5SDimitry Andric const TargetLibraryInfo *libInfo) 257*0b57cec5SDimitry Andric : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()), 258*0b57cec5SDimitry Andric Subtarget(&funcInfo.MF->getSubtarget<MipsSubtarget>()), 259*0b57cec5SDimitry Andric TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) { 260*0b57cec5SDimitry Andric MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); 261*0b57cec5SDimitry Andric Context = &funcInfo.Fn->getContext(); 262*0b57cec5SDimitry Andric UnsupportedFPMode = Subtarget->isFP64bit() || Subtarget->useSoftFloat(); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric unsigned fastMaterializeAlloca(const AllocaInst *AI) override; 266*0b57cec5SDimitry Andric unsigned fastMaterializeConstant(const Constant *C) override; 267*0b57cec5SDimitry Andric bool fastSelectInstruction(const Instruction *I) override; 268*0b57cec5SDimitry Andric 269*0b57cec5SDimitry Andric #include "MipsGenFastISel.inc" 270*0b57cec5SDimitry Andric }; 271*0b57cec5SDimitry Andric 272*0b57cec5SDimitry Andric } // end anonymous namespace 273*0b57cec5SDimitry Andric 274*0b57cec5SDimitry Andric static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT, 275*0b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, 276*0b57cec5SDimitry Andric CCState &State) LLVM_ATTRIBUTE_UNUSED; 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, 279*0b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo, 280*0b57cec5SDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State) { 281*0b57cec5SDimitry Andric llvm_unreachable("should not be called"); 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, 285*0b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo, 286*0b57cec5SDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State) { 287*0b57cec5SDimitry Andric llvm_unreachable("should not be called"); 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric #include "MipsGenCallingConv.inc" 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { 293*0b57cec5SDimitry Andric return CC_MipsO32; 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric unsigned MipsFastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT, 297*0b57cec5SDimitry Andric const Value *LHS, const Value *RHS) { 298*0b57cec5SDimitry Andric // Canonicalize immediates to the RHS first. 299*0b57cec5SDimitry Andric if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS)) 300*0b57cec5SDimitry Andric std::swap(LHS, RHS); 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andric unsigned Opc; 303*0b57cec5SDimitry Andric switch (ISDOpc) { 304*0b57cec5SDimitry Andric case ISD::AND: 305*0b57cec5SDimitry Andric Opc = Mips::AND; 306*0b57cec5SDimitry Andric break; 307*0b57cec5SDimitry Andric case ISD::OR: 308*0b57cec5SDimitry Andric Opc = Mips::OR; 309*0b57cec5SDimitry Andric break; 310*0b57cec5SDimitry Andric case ISD::XOR: 311*0b57cec5SDimitry Andric Opc = Mips::XOR; 312*0b57cec5SDimitry Andric break; 313*0b57cec5SDimitry Andric default: 314*0b57cec5SDimitry Andric llvm_unreachable("unexpected opcode"); 315*0b57cec5SDimitry Andric } 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric unsigned LHSReg = getRegForValue(LHS); 318*0b57cec5SDimitry Andric if (!LHSReg) 319*0b57cec5SDimitry Andric return 0; 320*0b57cec5SDimitry Andric 321*0b57cec5SDimitry Andric unsigned RHSReg; 322*0b57cec5SDimitry Andric if (const auto *C = dyn_cast<ConstantInt>(RHS)) 323*0b57cec5SDimitry Andric RHSReg = materializeInt(C, MVT::i32); 324*0b57cec5SDimitry Andric else 325*0b57cec5SDimitry Andric RHSReg = getRegForValue(RHS); 326*0b57cec5SDimitry Andric if (!RHSReg) 327*0b57cec5SDimitry Andric return 0; 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 330*0b57cec5SDimitry Andric if (!ResultReg) 331*0b57cec5SDimitry Andric return 0; 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric emitInst(Opc, ResultReg).addReg(LHSReg).addReg(RHSReg); 334*0b57cec5SDimitry Andric return ResultReg; 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric unsigned MipsFastISel::fastMaterializeAlloca(const AllocaInst *AI) { 338*0b57cec5SDimitry Andric assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i32 && 339*0b57cec5SDimitry Andric "Alloca should always return a pointer."); 340*0b57cec5SDimitry Andric 341*0b57cec5SDimitry Andric DenseMap<const AllocaInst *, int>::iterator SI = 342*0b57cec5SDimitry Andric FuncInfo.StaticAllocaMap.find(AI); 343*0b57cec5SDimitry Andric 344*0b57cec5SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) { 345*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 346*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LEA_ADDiu), 347*0b57cec5SDimitry Andric ResultReg) 348*0b57cec5SDimitry Andric .addFrameIndex(SI->second) 349*0b57cec5SDimitry Andric .addImm(0); 350*0b57cec5SDimitry Andric return ResultReg; 351*0b57cec5SDimitry Andric } 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric return 0; 354*0b57cec5SDimitry Andric } 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) { 357*0b57cec5SDimitry Andric if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) 358*0b57cec5SDimitry Andric return 0; 359*0b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass; 360*0b57cec5SDimitry Andric const ConstantInt *CI = cast<ConstantInt>(C); 361*0b57cec5SDimitry Andric return materialize32BitInt(CI->getZExtValue(), RC); 362*0b57cec5SDimitry Andric } 363*0b57cec5SDimitry Andric 364*0b57cec5SDimitry Andric unsigned MipsFastISel::materialize32BitInt(int64_t Imm, 365*0b57cec5SDimitry Andric const TargetRegisterClass *RC) { 366*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(RC); 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric if (isInt<16>(Imm)) { 369*0b57cec5SDimitry Andric unsigned Opc = Mips::ADDiu; 370*0b57cec5SDimitry Andric emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm); 371*0b57cec5SDimitry Andric return ResultReg; 372*0b57cec5SDimitry Andric } else if (isUInt<16>(Imm)) { 373*0b57cec5SDimitry Andric emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm); 374*0b57cec5SDimitry Andric return ResultReg; 375*0b57cec5SDimitry Andric } 376*0b57cec5SDimitry Andric unsigned Lo = Imm & 0xFFFF; 377*0b57cec5SDimitry Andric unsigned Hi = (Imm >> 16) & 0xFFFF; 378*0b57cec5SDimitry Andric if (Lo) { 379*0b57cec5SDimitry Andric // Both Lo and Hi have nonzero bits. 380*0b57cec5SDimitry Andric unsigned TmpReg = createResultReg(RC); 381*0b57cec5SDimitry Andric emitInst(Mips::LUi, TmpReg).addImm(Hi); 382*0b57cec5SDimitry Andric emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo); 383*0b57cec5SDimitry Andric } else { 384*0b57cec5SDimitry Andric emitInst(Mips::LUi, ResultReg).addImm(Hi); 385*0b57cec5SDimitry Andric } 386*0b57cec5SDimitry Andric return ResultReg; 387*0b57cec5SDimitry Andric } 388*0b57cec5SDimitry Andric 389*0b57cec5SDimitry Andric unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) { 390*0b57cec5SDimitry Andric if (UnsupportedFPMode) 391*0b57cec5SDimitry Andric return 0; 392*0b57cec5SDimitry Andric int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); 393*0b57cec5SDimitry Andric if (VT == MVT::f32) { 394*0b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::FGR32RegClass; 395*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 396*0b57cec5SDimitry Andric unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass); 397*0b57cec5SDimitry Andric emitInst(Mips::MTC1, DestReg).addReg(TempReg); 398*0b57cec5SDimitry Andric return DestReg; 399*0b57cec5SDimitry Andric } else if (VT == MVT::f64) { 400*0b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::AFGR64RegClass; 401*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 402*0b57cec5SDimitry Andric unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass); 403*0b57cec5SDimitry Andric unsigned TempReg2 = 404*0b57cec5SDimitry Andric materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass); 405*0b57cec5SDimitry Andric emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1); 406*0b57cec5SDimitry Andric return DestReg; 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric return 0; 409*0b57cec5SDimitry Andric } 410*0b57cec5SDimitry Andric 411*0b57cec5SDimitry Andric unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) { 412*0b57cec5SDimitry Andric // For now 32-bit only. 413*0b57cec5SDimitry Andric if (VT != MVT::i32) 414*0b57cec5SDimitry Andric return 0; 415*0b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass; 416*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 417*0b57cec5SDimitry Andric const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); 418*0b57cec5SDimitry Andric bool IsThreadLocal = GVar && GVar->isThreadLocal(); 419*0b57cec5SDimitry Andric // TLS not supported at this time. 420*0b57cec5SDimitry Andric if (IsThreadLocal) 421*0b57cec5SDimitry Andric return 0; 422*0b57cec5SDimitry Andric emitInst(Mips::LW, DestReg) 423*0b57cec5SDimitry Andric .addReg(MFI->getGlobalBaseReg()) 424*0b57cec5SDimitry Andric .addGlobalAddress(GV, 0, MipsII::MO_GOT); 425*0b57cec5SDimitry Andric if ((GV->hasInternalLinkage() || 426*0b57cec5SDimitry Andric (GV->hasLocalLinkage() && !isa<Function>(GV)))) { 427*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(RC); 428*0b57cec5SDimitry Andric emitInst(Mips::ADDiu, TempReg) 429*0b57cec5SDimitry Andric .addReg(DestReg) 430*0b57cec5SDimitry Andric .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO); 431*0b57cec5SDimitry Andric DestReg = TempReg; 432*0b57cec5SDimitry Andric } 433*0b57cec5SDimitry Andric return DestReg; 434*0b57cec5SDimitry Andric } 435*0b57cec5SDimitry Andric 436*0b57cec5SDimitry Andric unsigned MipsFastISel::materializeExternalCallSym(MCSymbol *Sym) { 437*0b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass; 438*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 439*0b57cec5SDimitry Andric emitInst(Mips::LW, DestReg) 440*0b57cec5SDimitry Andric .addReg(MFI->getGlobalBaseReg()) 441*0b57cec5SDimitry Andric .addSym(Sym, MipsII::MO_GOT); 442*0b57cec5SDimitry Andric return DestReg; 443*0b57cec5SDimitry Andric } 444*0b57cec5SDimitry Andric 445*0b57cec5SDimitry Andric // Materialize a constant into a register, and return the register 446*0b57cec5SDimitry Andric // number (or zero if we failed to handle it). 447*0b57cec5SDimitry Andric unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { 448*0b57cec5SDimitry Andric EVT CEVT = TLI.getValueType(DL, C->getType(), true); 449*0b57cec5SDimitry Andric 450*0b57cec5SDimitry Andric // Only handle simple types. 451*0b57cec5SDimitry Andric if (!CEVT.isSimple()) 452*0b57cec5SDimitry Andric return 0; 453*0b57cec5SDimitry Andric MVT VT = CEVT.getSimpleVT(); 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) 456*0b57cec5SDimitry Andric return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT); 457*0b57cec5SDimitry Andric else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) 458*0b57cec5SDimitry Andric return materializeGV(GV, VT); 459*0b57cec5SDimitry Andric else if (isa<ConstantInt>(C)) 460*0b57cec5SDimitry Andric return materializeInt(C, VT); 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric return 0; 463*0b57cec5SDimitry Andric } 464*0b57cec5SDimitry Andric 465*0b57cec5SDimitry Andric bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { 466*0b57cec5SDimitry Andric const User *U = nullptr; 467*0b57cec5SDimitry Andric unsigned Opcode = Instruction::UserOp1; 468*0b57cec5SDimitry Andric if (const Instruction *I = dyn_cast<Instruction>(Obj)) { 469*0b57cec5SDimitry Andric // Don't walk into other basic blocks unless the object is an alloca from 470*0b57cec5SDimitry Andric // another block, otherwise it may not have a virtual register assigned. 471*0b57cec5SDimitry Andric if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) || 472*0b57cec5SDimitry Andric FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { 473*0b57cec5SDimitry Andric Opcode = I->getOpcode(); 474*0b57cec5SDimitry Andric U = I; 475*0b57cec5SDimitry Andric } 476*0b57cec5SDimitry Andric } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) { 477*0b57cec5SDimitry Andric Opcode = C->getOpcode(); 478*0b57cec5SDimitry Andric U = C; 479*0b57cec5SDimitry Andric } 480*0b57cec5SDimitry Andric switch (Opcode) { 481*0b57cec5SDimitry Andric default: 482*0b57cec5SDimitry Andric break; 483*0b57cec5SDimitry Andric case Instruction::BitCast: 484*0b57cec5SDimitry Andric // Look through bitcasts. 485*0b57cec5SDimitry Andric return computeAddress(U->getOperand(0), Addr); 486*0b57cec5SDimitry Andric case Instruction::GetElementPtr: { 487*0b57cec5SDimitry Andric Address SavedAddr = Addr; 488*0b57cec5SDimitry Andric int64_t TmpOffset = Addr.getOffset(); 489*0b57cec5SDimitry Andric // Iterate through the GEP folding the constants into offsets where 490*0b57cec5SDimitry Andric // we can. 491*0b57cec5SDimitry Andric gep_type_iterator GTI = gep_type_begin(U); 492*0b57cec5SDimitry Andric for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; 493*0b57cec5SDimitry Andric ++i, ++GTI) { 494*0b57cec5SDimitry Andric const Value *Op = *i; 495*0b57cec5SDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 496*0b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 497*0b57cec5SDimitry Andric unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); 498*0b57cec5SDimitry Andric TmpOffset += SL->getElementOffset(Idx); 499*0b57cec5SDimitry Andric } else { 500*0b57cec5SDimitry Andric uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); 501*0b57cec5SDimitry Andric while (true) { 502*0b57cec5SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { 503*0b57cec5SDimitry Andric // Constant-offset addressing. 504*0b57cec5SDimitry Andric TmpOffset += CI->getSExtValue() * S; 505*0b57cec5SDimitry Andric break; 506*0b57cec5SDimitry Andric } 507*0b57cec5SDimitry Andric if (canFoldAddIntoGEP(U, Op)) { 508*0b57cec5SDimitry Andric // A compatible add with a constant operand. Fold the constant. 509*0b57cec5SDimitry Andric ConstantInt *CI = 510*0b57cec5SDimitry Andric cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); 511*0b57cec5SDimitry Andric TmpOffset += CI->getSExtValue() * S; 512*0b57cec5SDimitry Andric // Iterate on the other operand. 513*0b57cec5SDimitry Andric Op = cast<AddOperator>(Op)->getOperand(0); 514*0b57cec5SDimitry Andric continue; 515*0b57cec5SDimitry Andric } 516*0b57cec5SDimitry Andric // Unsupported 517*0b57cec5SDimitry Andric goto unsupported_gep; 518*0b57cec5SDimitry Andric } 519*0b57cec5SDimitry Andric } 520*0b57cec5SDimitry Andric } 521*0b57cec5SDimitry Andric // Try to grab the base operand now. 522*0b57cec5SDimitry Andric Addr.setOffset(TmpOffset); 523*0b57cec5SDimitry Andric if (computeAddress(U->getOperand(0), Addr)) 524*0b57cec5SDimitry Andric return true; 525*0b57cec5SDimitry Andric // We failed, restore everything and try the other options. 526*0b57cec5SDimitry Andric Addr = SavedAddr; 527*0b57cec5SDimitry Andric unsupported_gep: 528*0b57cec5SDimitry Andric break; 529*0b57cec5SDimitry Andric } 530*0b57cec5SDimitry Andric case Instruction::Alloca: { 531*0b57cec5SDimitry Andric const AllocaInst *AI = cast<AllocaInst>(Obj); 532*0b57cec5SDimitry Andric DenseMap<const AllocaInst *, int>::iterator SI = 533*0b57cec5SDimitry Andric FuncInfo.StaticAllocaMap.find(AI); 534*0b57cec5SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) { 535*0b57cec5SDimitry Andric Addr.setKind(Address::FrameIndexBase); 536*0b57cec5SDimitry Andric Addr.setFI(SI->second); 537*0b57cec5SDimitry Andric return true; 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric break; 540*0b57cec5SDimitry Andric } 541*0b57cec5SDimitry Andric } 542*0b57cec5SDimitry Andric Addr.setReg(getRegForValue(Obj)); 543*0b57cec5SDimitry Andric return Addr.getReg() != 0; 544*0b57cec5SDimitry Andric } 545*0b57cec5SDimitry Andric 546*0b57cec5SDimitry Andric bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) { 547*0b57cec5SDimitry Andric const User *U = nullptr; 548*0b57cec5SDimitry Andric unsigned Opcode = Instruction::UserOp1; 549*0b57cec5SDimitry Andric 550*0b57cec5SDimitry Andric if (const auto *I = dyn_cast<Instruction>(V)) { 551*0b57cec5SDimitry Andric // Check if the value is defined in the same basic block. This information 552*0b57cec5SDimitry Andric // is crucial to know whether or not folding an operand is valid. 553*0b57cec5SDimitry Andric if (I->getParent() == FuncInfo.MBB->getBasicBlock()) { 554*0b57cec5SDimitry Andric Opcode = I->getOpcode(); 555*0b57cec5SDimitry Andric U = I; 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric } else if (const auto *C = dyn_cast<ConstantExpr>(V)) { 558*0b57cec5SDimitry Andric Opcode = C->getOpcode(); 559*0b57cec5SDimitry Andric U = C; 560*0b57cec5SDimitry Andric } 561*0b57cec5SDimitry Andric 562*0b57cec5SDimitry Andric switch (Opcode) { 563*0b57cec5SDimitry Andric default: 564*0b57cec5SDimitry Andric break; 565*0b57cec5SDimitry Andric case Instruction::BitCast: 566*0b57cec5SDimitry Andric // Look past bitcasts if its operand is in the same BB. 567*0b57cec5SDimitry Andric return computeCallAddress(U->getOperand(0), Addr); 568*0b57cec5SDimitry Andric break; 569*0b57cec5SDimitry Andric case Instruction::IntToPtr: 570*0b57cec5SDimitry Andric // Look past no-op inttoptrs if its operand is in the same BB. 571*0b57cec5SDimitry Andric if (TLI.getValueType(DL, U->getOperand(0)->getType()) == 572*0b57cec5SDimitry Andric TLI.getPointerTy(DL)) 573*0b57cec5SDimitry Andric return computeCallAddress(U->getOperand(0), Addr); 574*0b57cec5SDimitry Andric break; 575*0b57cec5SDimitry Andric case Instruction::PtrToInt: 576*0b57cec5SDimitry Andric // Look past no-op ptrtoints if its operand is in the same BB. 577*0b57cec5SDimitry Andric if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL)) 578*0b57cec5SDimitry Andric return computeCallAddress(U->getOperand(0), Addr); 579*0b57cec5SDimitry Andric break; 580*0b57cec5SDimitry Andric } 581*0b57cec5SDimitry Andric 582*0b57cec5SDimitry Andric if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { 583*0b57cec5SDimitry Andric Addr.setGlobalValue(GV); 584*0b57cec5SDimitry Andric return true; 585*0b57cec5SDimitry Andric } 586*0b57cec5SDimitry Andric 587*0b57cec5SDimitry Andric // If all else fails, try to materialize the value in a register. 588*0b57cec5SDimitry Andric if (!Addr.getGlobalValue()) { 589*0b57cec5SDimitry Andric Addr.setReg(getRegForValue(V)); 590*0b57cec5SDimitry Andric return Addr.getReg() != 0; 591*0b57cec5SDimitry Andric } 592*0b57cec5SDimitry Andric 593*0b57cec5SDimitry Andric return false; 594*0b57cec5SDimitry Andric } 595*0b57cec5SDimitry Andric 596*0b57cec5SDimitry Andric bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { 597*0b57cec5SDimitry Andric EVT evt = TLI.getValueType(DL, Ty, true); 598*0b57cec5SDimitry Andric // Only handle simple types. 599*0b57cec5SDimitry Andric if (evt == MVT::Other || !evt.isSimple()) 600*0b57cec5SDimitry Andric return false; 601*0b57cec5SDimitry Andric VT = evt.getSimpleVT(); 602*0b57cec5SDimitry Andric 603*0b57cec5SDimitry Andric // Handle all legal types, i.e. a register that will directly hold this 604*0b57cec5SDimitry Andric // value. 605*0b57cec5SDimitry Andric return TLI.isTypeLegal(VT); 606*0b57cec5SDimitry Andric } 607*0b57cec5SDimitry Andric 608*0b57cec5SDimitry Andric bool MipsFastISel::isTypeSupported(Type *Ty, MVT &VT) { 609*0b57cec5SDimitry Andric if (Ty->isVectorTy()) 610*0b57cec5SDimitry Andric return false; 611*0b57cec5SDimitry Andric 612*0b57cec5SDimitry Andric if (isTypeLegal(Ty, VT)) 613*0b57cec5SDimitry Andric return true; 614*0b57cec5SDimitry Andric 615*0b57cec5SDimitry Andric // If this is a type than can be sign or zero-extended to a basic operation 616*0b57cec5SDimitry Andric // go ahead and accept it now. 617*0b57cec5SDimitry Andric if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16) 618*0b57cec5SDimitry Andric return true; 619*0b57cec5SDimitry Andric 620*0b57cec5SDimitry Andric return false; 621*0b57cec5SDimitry Andric } 622*0b57cec5SDimitry Andric 623*0b57cec5SDimitry Andric bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { 624*0b57cec5SDimitry Andric if (isTypeLegal(Ty, VT)) 625*0b57cec5SDimitry Andric return true; 626*0b57cec5SDimitry Andric // We will extend this in a later patch: 627*0b57cec5SDimitry Andric // If this is a type than can be sign or zero-extended to a basic operation 628*0b57cec5SDimitry Andric // go ahead and accept it now. 629*0b57cec5SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 630*0b57cec5SDimitry Andric return true; 631*0b57cec5SDimitry Andric return false; 632*0b57cec5SDimitry Andric } 633*0b57cec5SDimitry Andric 634*0b57cec5SDimitry Andric // Because of how EmitCmp is called with fast-isel, you can 635*0b57cec5SDimitry Andric // end up with redundant "andi" instructions after the sequences emitted below. 636*0b57cec5SDimitry Andric // We should try and solve this issue in the future. 637*0b57cec5SDimitry Andric // 638*0b57cec5SDimitry Andric bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { 639*0b57cec5SDimitry Andric const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1); 640*0b57cec5SDimitry Andric bool IsUnsigned = CI->isUnsigned(); 641*0b57cec5SDimitry Andric unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned); 642*0b57cec5SDimitry Andric if (LeftReg == 0) 643*0b57cec5SDimitry Andric return false; 644*0b57cec5SDimitry Andric unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned); 645*0b57cec5SDimitry Andric if (RightReg == 0) 646*0b57cec5SDimitry Andric return false; 647*0b57cec5SDimitry Andric CmpInst::Predicate P = CI->getPredicate(); 648*0b57cec5SDimitry Andric 649*0b57cec5SDimitry Andric switch (P) { 650*0b57cec5SDimitry Andric default: 651*0b57cec5SDimitry Andric return false; 652*0b57cec5SDimitry Andric case CmpInst::ICMP_EQ: { 653*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 654*0b57cec5SDimitry Andric emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); 655*0b57cec5SDimitry Andric emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1); 656*0b57cec5SDimitry Andric break; 657*0b57cec5SDimitry Andric } 658*0b57cec5SDimitry Andric case CmpInst::ICMP_NE: { 659*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 660*0b57cec5SDimitry Andric emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); 661*0b57cec5SDimitry Andric emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg); 662*0b57cec5SDimitry Andric break; 663*0b57cec5SDimitry Andric } 664*0b57cec5SDimitry Andric case CmpInst::ICMP_UGT: 665*0b57cec5SDimitry Andric emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg); 666*0b57cec5SDimitry Andric break; 667*0b57cec5SDimitry Andric case CmpInst::ICMP_ULT: 668*0b57cec5SDimitry Andric emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg); 669*0b57cec5SDimitry Andric break; 670*0b57cec5SDimitry Andric case CmpInst::ICMP_UGE: { 671*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 672*0b57cec5SDimitry Andric emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg); 673*0b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 674*0b57cec5SDimitry Andric break; 675*0b57cec5SDimitry Andric } 676*0b57cec5SDimitry Andric case CmpInst::ICMP_ULE: { 677*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 678*0b57cec5SDimitry Andric emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg); 679*0b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 680*0b57cec5SDimitry Andric break; 681*0b57cec5SDimitry Andric } 682*0b57cec5SDimitry Andric case CmpInst::ICMP_SGT: 683*0b57cec5SDimitry Andric emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg); 684*0b57cec5SDimitry Andric break; 685*0b57cec5SDimitry Andric case CmpInst::ICMP_SLT: 686*0b57cec5SDimitry Andric emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg); 687*0b57cec5SDimitry Andric break; 688*0b57cec5SDimitry Andric case CmpInst::ICMP_SGE: { 689*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 690*0b57cec5SDimitry Andric emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg); 691*0b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 692*0b57cec5SDimitry Andric break; 693*0b57cec5SDimitry Andric } 694*0b57cec5SDimitry Andric case CmpInst::ICMP_SLE: { 695*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 696*0b57cec5SDimitry Andric emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg); 697*0b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 698*0b57cec5SDimitry Andric break; 699*0b57cec5SDimitry Andric } 700*0b57cec5SDimitry Andric case CmpInst::FCMP_OEQ: 701*0b57cec5SDimitry Andric case CmpInst::FCMP_UNE: 702*0b57cec5SDimitry Andric case CmpInst::FCMP_OLT: 703*0b57cec5SDimitry Andric case CmpInst::FCMP_OLE: 704*0b57cec5SDimitry Andric case CmpInst::FCMP_OGT: 705*0b57cec5SDimitry Andric case CmpInst::FCMP_OGE: { 706*0b57cec5SDimitry Andric if (UnsupportedFPMode) 707*0b57cec5SDimitry Andric return false; 708*0b57cec5SDimitry Andric bool IsFloat = Left->getType()->isFloatTy(); 709*0b57cec5SDimitry Andric bool IsDouble = Left->getType()->isDoubleTy(); 710*0b57cec5SDimitry Andric if (!IsFloat && !IsDouble) 711*0b57cec5SDimitry Andric return false; 712*0b57cec5SDimitry Andric unsigned Opc, CondMovOpc; 713*0b57cec5SDimitry Andric switch (P) { 714*0b57cec5SDimitry Andric case CmpInst::FCMP_OEQ: 715*0b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; 716*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVT_I; 717*0b57cec5SDimitry Andric break; 718*0b57cec5SDimitry Andric case CmpInst::FCMP_UNE: 719*0b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; 720*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVF_I; 721*0b57cec5SDimitry Andric break; 722*0b57cec5SDimitry Andric case CmpInst::FCMP_OLT: 723*0b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32; 724*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVT_I; 725*0b57cec5SDimitry Andric break; 726*0b57cec5SDimitry Andric case CmpInst::FCMP_OLE: 727*0b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32; 728*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVT_I; 729*0b57cec5SDimitry Andric break; 730*0b57cec5SDimitry Andric case CmpInst::FCMP_OGT: 731*0b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32; 732*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVF_I; 733*0b57cec5SDimitry Andric break; 734*0b57cec5SDimitry Andric case CmpInst::FCMP_OGE: 735*0b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32; 736*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVF_I; 737*0b57cec5SDimitry Andric break; 738*0b57cec5SDimitry Andric default: 739*0b57cec5SDimitry Andric llvm_unreachable("Only switching of a subset of CCs."); 740*0b57cec5SDimitry Andric } 741*0b57cec5SDimitry Andric unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass); 742*0b57cec5SDimitry Andric unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass); 743*0b57cec5SDimitry Andric emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0); 744*0b57cec5SDimitry Andric emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1); 745*0b57cec5SDimitry Andric emitInst(Opc).addReg(Mips::FCC0, RegState::Define).addReg(LeftReg) 746*0b57cec5SDimitry Andric .addReg(RightReg); 747*0b57cec5SDimitry Andric emitInst(CondMovOpc, ResultReg) 748*0b57cec5SDimitry Andric .addReg(RegWithOne) 749*0b57cec5SDimitry Andric .addReg(Mips::FCC0) 750*0b57cec5SDimitry Andric .addReg(RegWithZero); 751*0b57cec5SDimitry Andric break; 752*0b57cec5SDimitry Andric } 753*0b57cec5SDimitry Andric } 754*0b57cec5SDimitry Andric return true; 755*0b57cec5SDimitry Andric } 756*0b57cec5SDimitry Andric 757*0b57cec5SDimitry Andric bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, 758*0b57cec5SDimitry Andric unsigned Alignment) { 759*0b57cec5SDimitry Andric // 760*0b57cec5SDimitry Andric // more cases will be handled here in following patches. 761*0b57cec5SDimitry Andric // 762*0b57cec5SDimitry Andric unsigned Opc; 763*0b57cec5SDimitry Andric switch (VT.SimpleTy) { 764*0b57cec5SDimitry Andric case MVT::i32: 765*0b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::GPR32RegClass); 766*0b57cec5SDimitry Andric Opc = Mips::LW; 767*0b57cec5SDimitry Andric break; 768*0b57cec5SDimitry Andric case MVT::i16: 769*0b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::GPR32RegClass); 770*0b57cec5SDimitry Andric Opc = Mips::LHu; 771*0b57cec5SDimitry Andric break; 772*0b57cec5SDimitry Andric case MVT::i8: 773*0b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::GPR32RegClass); 774*0b57cec5SDimitry Andric Opc = Mips::LBu; 775*0b57cec5SDimitry Andric break; 776*0b57cec5SDimitry Andric case MVT::f32: 777*0b57cec5SDimitry Andric if (UnsupportedFPMode) 778*0b57cec5SDimitry Andric return false; 779*0b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::FGR32RegClass); 780*0b57cec5SDimitry Andric Opc = Mips::LWC1; 781*0b57cec5SDimitry Andric break; 782*0b57cec5SDimitry Andric case MVT::f64: 783*0b57cec5SDimitry Andric if (UnsupportedFPMode) 784*0b57cec5SDimitry Andric return false; 785*0b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::AFGR64RegClass); 786*0b57cec5SDimitry Andric Opc = Mips::LDC1; 787*0b57cec5SDimitry Andric break; 788*0b57cec5SDimitry Andric default: 789*0b57cec5SDimitry Andric return false; 790*0b57cec5SDimitry Andric } 791*0b57cec5SDimitry Andric if (Addr.isRegBase()) { 792*0b57cec5SDimitry Andric simplifyAddress(Addr); 793*0b57cec5SDimitry Andric emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); 794*0b57cec5SDimitry Andric return true; 795*0b57cec5SDimitry Andric } 796*0b57cec5SDimitry Andric if (Addr.isFIBase()) { 797*0b57cec5SDimitry Andric unsigned FI = Addr.getFI(); 798*0b57cec5SDimitry Andric unsigned Align = 4; 799*0b57cec5SDimitry Andric int64_t Offset = Addr.getOffset(); 800*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF->getFrameInfo(); 801*0b57cec5SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 802*0b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, 803*0b57cec5SDimitry Andric MFI.getObjectSize(FI), Align); 804*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 805*0b57cec5SDimitry Andric .addFrameIndex(FI) 806*0b57cec5SDimitry Andric .addImm(Offset) 807*0b57cec5SDimitry Andric .addMemOperand(MMO); 808*0b57cec5SDimitry Andric return true; 809*0b57cec5SDimitry Andric } 810*0b57cec5SDimitry Andric return false; 811*0b57cec5SDimitry Andric } 812*0b57cec5SDimitry Andric 813*0b57cec5SDimitry Andric bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, 814*0b57cec5SDimitry Andric unsigned Alignment) { 815*0b57cec5SDimitry Andric // 816*0b57cec5SDimitry Andric // more cases will be handled here in following patches. 817*0b57cec5SDimitry Andric // 818*0b57cec5SDimitry Andric unsigned Opc; 819*0b57cec5SDimitry Andric switch (VT.SimpleTy) { 820*0b57cec5SDimitry Andric case MVT::i8: 821*0b57cec5SDimitry Andric Opc = Mips::SB; 822*0b57cec5SDimitry Andric break; 823*0b57cec5SDimitry Andric case MVT::i16: 824*0b57cec5SDimitry Andric Opc = Mips::SH; 825*0b57cec5SDimitry Andric break; 826*0b57cec5SDimitry Andric case MVT::i32: 827*0b57cec5SDimitry Andric Opc = Mips::SW; 828*0b57cec5SDimitry Andric break; 829*0b57cec5SDimitry Andric case MVT::f32: 830*0b57cec5SDimitry Andric if (UnsupportedFPMode) 831*0b57cec5SDimitry Andric return false; 832*0b57cec5SDimitry Andric Opc = Mips::SWC1; 833*0b57cec5SDimitry Andric break; 834*0b57cec5SDimitry Andric case MVT::f64: 835*0b57cec5SDimitry Andric if (UnsupportedFPMode) 836*0b57cec5SDimitry Andric return false; 837*0b57cec5SDimitry Andric Opc = Mips::SDC1; 838*0b57cec5SDimitry Andric break; 839*0b57cec5SDimitry Andric default: 840*0b57cec5SDimitry Andric return false; 841*0b57cec5SDimitry Andric } 842*0b57cec5SDimitry Andric if (Addr.isRegBase()) { 843*0b57cec5SDimitry Andric simplifyAddress(Addr); 844*0b57cec5SDimitry Andric emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); 845*0b57cec5SDimitry Andric return true; 846*0b57cec5SDimitry Andric } 847*0b57cec5SDimitry Andric if (Addr.isFIBase()) { 848*0b57cec5SDimitry Andric unsigned FI = Addr.getFI(); 849*0b57cec5SDimitry Andric unsigned Align = 4; 850*0b57cec5SDimitry Andric int64_t Offset = Addr.getOffset(); 851*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF->getFrameInfo(); 852*0b57cec5SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 853*0b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, 854*0b57cec5SDimitry Andric MFI.getObjectSize(FI), Align); 855*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) 856*0b57cec5SDimitry Andric .addReg(SrcReg) 857*0b57cec5SDimitry Andric .addFrameIndex(FI) 858*0b57cec5SDimitry Andric .addImm(Offset) 859*0b57cec5SDimitry Andric .addMemOperand(MMO); 860*0b57cec5SDimitry Andric return true; 861*0b57cec5SDimitry Andric } 862*0b57cec5SDimitry Andric return false; 863*0b57cec5SDimitry Andric } 864*0b57cec5SDimitry Andric 865*0b57cec5SDimitry Andric bool MipsFastISel::selectLogicalOp(const Instruction *I) { 866*0b57cec5SDimitry Andric MVT VT; 867*0b57cec5SDimitry Andric if (!isTypeSupported(I->getType(), VT)) 868*0b57cec5SDimitry Andric return false; 869*0b57cec5SDimitry Andric 870*0b57cec5SDimitry Andric unsigned ResultReg; 871*0b57cec5SDimitry Andric switch (I->getOpcode()) { 872*0b57cec5SDimitry Andric default: 873*0b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction."); 874*0b57cec5SDimitry Andric case Instruction::And: 875*0b57cec5SDimitry Andric ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1)); 876*0b57cec5SDimitry Andric break; 877*0b57cec5SDimitry Andric case Instruction::Or: 878*0b57cec5SDimitry Andric ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1)); 879*0b57cec5SDimitry Andric break; 880*0b57cec5SDimitry Andric case Instruction::Xor: 881*0b57cec5SDimitry Andric ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1)); 882*0b57cec5SDimitry Andric break; 883*0b57cec5SDimitry Andric } 884*0b57cec5SDimitry Andric 885*0b57cec5SDimitry Andric if (!ResultReg) 886*0b57cec5SDimitry Andric return false; 887*0b57cec5SDimitry Andric 888*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 889*0b57cec5SDimitry Andric return true; 890*0b57cec5SDimitry Andric } 891*0b57cec5SDimitry Andric 892*0b57cec5SDimitry Andric bool MipsFastISel::selectLoad(const Instruction *I) { 893*0b57cec5SDimitry Andric // Atomic loads need special handling. 894*0b57cec5SDimitry Andric if (cast<LoadInst>(I)->isAtomic()) 895*0b57cec5SDimitry Andric return false; 896*0b57cec5SDimitry Andric 897*0b57cec5SDimitry Andric // Verify we have a legal type before going any further. 898*0b57cec5SDimitry Andric MVT VT; 899*0b57cec5SDimitry Andric if (!isLoadTypeLegal(I->getType(), VT)) 900*0b57cec5SDimitry Andric return false; 901*0b57cec5SDimitry Andric 902*0b57cec5SDimitry Andric // See if we can handle this address. 903*0b57cec5SDimitry Andric Address Addr; 904*0b57cec5SDimitry Andric if (!computeAddress(I->getOperand(0), Addr)) 905*0b57cec5SDimitry Andric return false; 906*0b57cec5SDimitry Andric 907*0b57cec5SDimitry Andric unsigned ResultReg; 908*0b57cec5SDimitry Andric if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment())) 909*0b57cec5SDimitry Andric return false; 910*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 911*0b57cec5SDimitry Andric return true; 912*0b57cec5SDimitry Andric } 913*0b57cec5SDimitry Andric 914*0b57cec5SDimitry Andric bool MipsFastISel::selectStore(const Instruction *I) { 915*0b57cec5SDimitry Andric Value *Op0 = I->getOperand(0); 916*0b57cec5SDimitry Andric unsigned SrcReg = 0; 917*0b57cec5SDimitry Andric 918*0b57cec5SDimitry Andric // Atomic stores need special handling. 919*0b57cec5SDimitry Andric if (cast<StoreInst>(I)->isAtomic()) 920*0b57cec5SDimitry Andric return false; 921*0b57cec5SDimitry Andric 922*0b57cec5SDimitry Andric // Verify we have a legal type before going any further. 923*0b57cec5SDimitry Andric MVT VT; 924*0b57cec5SDimitry Andric if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT)) 925*0b57cec5SDimitry Andric return false; 926*0b57cec5SDimitry Andric 927*0b57cec5SDimitry Andric // Get the value to be stored into a register. 928*0b57cec5SDimitry Andric SrcReg = getRegForValue(Op0); 929*0b57cec5SDimitry Andric if (SrcReg == 0) 930*0b57cec5SDimitry Andric return false; 931*0b57cec5SDimitry Andric 932*0b57cec5SDimitry Andric // See if we can handle this address. 933*0b57cec5SDimitry Andric Address Addr; 934*0b57cec5SDimitry Andric if (!computeAddress(I->getOperand(1), Addr)) 935*0b57cec5SDimitry Andric return false; 936*0b57cec5SDimitry Andric 937*0b57cec5SDimitry Andric if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment())) 938*0b57cec5SDimitry Andric return false; 939*0b57cec5SDimitry Andric return true; 940*0b57cec5SDimitry Andric } 941*0b57cec5SDimitry Andric 942*0b57cec5SDimitry Andric // This can cause a redundant sltiu to be generated. 943*0b57cec5SDimitry Andric // FIXME: try and eliminate this in a future patch. 944*0b57cec5SDimitry Andric bool MipsFastISel::selectBranch(const Instruction *I) { 945*0b57cec5SDimitry Andric const BranchInst *BI = cast<BranchInst>(I); 946*0b57cec5SDimitry Andric MachineBasicBlock *BrBB = FuncInfo.MBB; 947*0b57cec5SDimitry Andric // 948*0b57cec5SDimitry Andric // TBB is the basic block for the case where the comparison is true. 949*0b57cec5SDimitry Andric // FBB is the basic block for the case where the comparison is false. 950*0b57cec5SDimitry Andric // if (cond) goto TBB 951*0b57cec5SDimitry Andric // goto FBB 952*0b57cec5SDimitry Andric // TBB: 953*0b57cec5SDimitry Andric // 954*0b57cec5SDimitry Andric MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; 955*0b57cec5SDimitry Andric MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; 956*0b57cec5SDimitry Andric 957*0b57cec5SDimitry Andric // Fold the common case of a conditional branch with a comparison 958*0b57cec5SDimitry Andric // in the same block. 959*0b57cec5SDimitry Andric unsigned ZExtCondReg = 0; 960*0b57cec5SDimitry Andric if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { 961*0b57cec5SDimitry Andric if (CI->hasOneUse() && CI->getParent() == I->getParent()) { 962*0b57cec5SDimitry Andric ZExtCondReg = createResultReg(&Mips::GPR32RegClass); 963*0b57cec5SDimitry Andric if (!emitCmp(ZExtCondReg, CI)) 964*0b57cec5SDimitry Andric return false; 965*0b57cec5SDimitry Andric } 966*0b57cec5SDimitry Andric } 967*0b57cec5SDimitry Andric 968*0b57cec5SDimitry Andric // For the general case, we need to mask with 1. 969*0b57cec5SDimitry Andric if (ZExtCondReg == 0) { 970*0b57cec5SDimitry Andric unsigned CondReg = getRegForValue(BI->getCondition()); 971*0b57cec5SDimitry Andric if (CondReg == 0) 972*0b57cec5SDimitry Andric return false; 973*0b57cec5SDimitry Andric 974*0b57cec5SDimitry Andric ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true); 975*0b57cec5SDimitry Andric if (ZExtCondReg == 0) 976*0b57cec5SDimitry Andric return false; 977*0b57cec5SDimitry Andric } 978*0b57cec5SDimitry Andric 979*0b57cec5SDimitry Andric BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) 980*0b57cec5SDimitry Andric .addReg(ZExtCondReg) 981*0b57cec5SDimitry Andric .addMBB(TBB); 982*0b57cec5SDimitry Andric finishCondBranch(BI->getParent(), TBB, FBB); 983*0b57cec5SDimitry Andric return true; 984*0b57cec5SDimitry Andric } 985*0b57cec5SDimitry Andric 986*0b57cec5SDimitry Andric bool MipsFastISel::selectCmp(const Instruction *I) { 987*0b57cec5SDimitry Andric const CmpInst *CI = cast<CmpInst>(I); 988*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 989*0b57cec5SDimitry Andric if (!emitCmp(ResultReg, CI)) 990*0b57cec5SDimitry Andric return false; 991*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 992*0b57cec5SDimitry Andric return true; 993*0b57cec5SDimitry Andric } 994*0b57cec5SDimitry Andric 995*0b57cec5SDimitry Andric // Attempt to fast-select a floating-point extend instruction. 996*0b57cec5SDimitry Andric bool MipsFastISel::selectFPExt(const Instruction *I) { 997*0b57cec5SDimitry Andric if (UnsupportedFPMode) 998*0b57cec5SDimitry Andric return false; 999*0b57cec5SDimitry Andric Value *Src = I->getOperand(0); 1000*0b57cec5SDimitry Andric EVT SrcVT = TLI.getValueType(DL, Src->getType(), true); 1001*0b57cec5SDimitry Andric EVT DestVT = TLI.getValueType(DL, I->getType(), true); 1002*0b57cec5SDimitry Andric 1003*0b57cec5SDimitry Andric if (SrcVT != MVT::f32 || DestVT != MVT::f64) 1004*0b57cec5SDimitry Andric return false; 1005*0b57cec5SDimitry Andric 1006*0b57cec5SDimitry Andric unsigned SrcReg = 1007*0b57cec5SDimitry Andric getRegForValue(Src); // this must be a 32bit floating point register class 1008*0b57cec5SDimitry Andric // maybe we should handle this differently 1009*0b57cec5SDimitry Andric if (!SrcReg) 1010*0b57cec5SDimitry Andric return false; 1011*0b57cec5SDimitry Andric 1012*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::AFGR64RegClass); 1013*0b57cec5SDimitry Andric emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg); 1014*0b57cec5SDimitry Andric updateValueMap(I, DestReg); 1015*0b57cec5SDimitry Andric return true; 1016*0b57cec5SDimitry Andric } 1017*0b57cec5SDimitry Andric 1018*0b57cec5SDimitry Andric bool MipsFastISel::selectSelect(const Instruction *I) { 1019*0b57cec5SDimitry Andric assert(isa<SelectInst>(I) && "Expected a select instruction."); 1020*0b57cec5SDimitry Andric 1021*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "selectSelect\n"); 1022*0b57cec5SDimitry Andric 1023*0b57cec5SDimitry Andric MVT VT; 1024*0b57cec5SDimitry Andric if (!isTypeSupported(I->getType(), VT) || UnsupportedFPMode) { 1025*0b57cec5SDimitry Andric LLVM_DEBUG( 1026*0b57cec5SDimitry Andric dbgs() << ".. .. gave up (!isTypeSupported || UnsupportedFPMode)\n"); 1027*0b57cec5SDimitry Andric return false; 1028*0b57cec5SDimitry Andric } 1029*0b57cec5SDimitry Andric 1030*0b57cec5SDimitry Andric unsigned CondMovOpc; 1031*0b57cec5SDimitry Andric const TargetRegisterClass *RC; 1032*0b57cec5SDimitry Andric 1033*0b57cec5SDimitry Andric if (VT.isInteger() && !VT.isVector() && VT.getSizeInBits() <= 32) { 1034*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVN_I_I; 1035*0b57cec5SDimitry Andric RC = &Mips::GPR32RegClass; 1036*0b57cec5SDimitry Andric } else if (VT == MVT::f32) { 1037*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVN_I_S; 1038*0b57cec5SDimitry Andric RC = &Mips::FGR32RegClass; 1039*0b57cec5SDimitry Andric } else if (VT == MVT::f64) { 1040*0b57cec5SDimitry Andric CondMovOpc = Mips::MOVN_I_D32; 1041*0b57cec5SDimitry Andric RC = &Mips::AFGR64RegClass; 1042*0b57cec5SDimitry Andric } else 1043*0b57cec5SDimitry Andric return false; 1044*0b57cec5SDimitry Andric 1045*0b57cec5SDimitry Andric const SelectInst *SI = cast<SelectInst>(I); 1046*0b57cec5SDimitry Andric const Value *Cond = SI->getCondition(); 1047*0b57cec5SDimitry Andric unsigned Src1Reg = getRegForValue(SI->getTrueValue()); 1048*0b57cec5SDimitry Andric unsigned Src2Reg = getRegForValue(SI->getFalseValue()); 1049*0b57cec5SDimitry Andric unsigned CondReg = getRegForValue(Cond); 1050*0b57cec5SDimitry Andric 1051*0b57cec5SDimitry Andric if (!Src1Reg || !Src2Reg || !CondReg) 1052*0b57cec5SDimitry Andric return false; 1053*0b57cec5SDimitry Andric 1054*0b57cec5SDimitry Andric unsigned ZExtCondReg = createResultReg(&Mips::GPR32RegClass); 1055*0b57cec5SDimitry Andric if (!ZExtCondReg) 1056*0b57cec5SDimitry Andric return false; 1057*0b57cec5SDimitry Andric 1058*0b57cec5SDimitry Andric if (!emitIntExt(MVT::i1, CondReg, MVT::i32, ZExtCondReg, true)) 1059*0b57cec5SDimitry Andric return false; 1060*0b57cec5SDimitry Andric 1061*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(RC); 1062*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(RC); 1063*0b57cec5SDimitry Andric 1064*0b57cec5SDimitry Andric if (!ResultReg || !TempReg) 1065*0b57cec5SDimitry Andric return false; 1066*0b57cec5SDimitry Andric 1067*0b57cec5SDimitry Andric emitInst(TargetOpcode::COPY, TempReg).addReg(Src2Reg); 1068*0b57cec5SDimitry Andric emitInst(CondMovOpc, ResultReg) 1069*0b57cec5SDimitry Andric .addReg(Src1Reg).addReg(ZExtCondReg).addReg(TempReg); 1070*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 1071*0b57cec5SDimitry Andric return true; 1072*0b57cec5SDimitry Andric } 1073*0b57cec5SDimitry Andric 1074*0b57cec5SDimitry Andric // Attempt to fast-select a floating-point truncate instruction. 1075*0b57cec5SDimitry Andric bool MipsFastISel::selectFPTrunc(const Instruction *I) { 1076*0b57cec5SDimitry Andric if (UnsupportedFPMode) 1077*0b57cec5SDimitry Andric return false; 1078*0b57cec5SDimitry Andric Value *Src = I->getOperand(0); 1079*0b57cec5SDimitry Andric EVT SrcVT = TLI.getValueType(DL, Src->getType(), true); 1080*0b57cec5SDimitry Andric EVT DestVT = TLI.getValueType(DL, I->getType(), true); 1081*0b57cec5SDimitry Andric 1082*0b57cec5SDimitry Andric if (SrcVT != MVT::f64 || DestVT != MVT::f32) 1083*0b57cec5SDimitry Andric return false; 1084*0b57cec5SDimitry Andric 1085*0b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Src); 1086*0b57cec5SDimitry Andric if (!SrcReg) 1087*0b57cec5SDimitry Andric return false; 1088*0b57cec5SDimitry Andric 1089*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::FGR32RegClass); 1090*0b57cec5SDimitry Andric if (!DestReg) 1091*0b57cec5SDimitry Andric return false; 1092*0b57cec5SDimitry Andric 1093*0b57cec5SDimitry Andric emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg); 1094*0b57cec5SDimitry Andric updateValueMap(I, DestReg); 1095*0b57cec5SDimitry Andric return true; 1096*0b57cec5SDimitry Andric } 1097*0b57cec5SDimitry Andric 1098*0b57cec5SDimitry Andric // Attempt to fast-select a floating-point-to-integer conversion. 1099*0b57cec5SDimitry Andric bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) { 1100*0b57cec5SDimitry Andric if (UnsupportedFPMode) 1101*0b57cec5SDimitry Andric return false; 1102*0b57cec5SDimitry Andric MVT DstVT, SrcVT; 1103*0b57cec5SDimitry Andric if (!IsSigned) 1104*0b57cec5SDimitry Andric return false; // We don't handle this case yet. There is no native 1105*0b57cec5SDimitry Andric // instruction for this but it can be synthesized. 1106*0b57cec5SDimitry Andric Type *DstTy = I->getType(); 1107*0b57cec5SDimitry Andric if (!isTypeLegal(DstTy, DstVT)) 1108*0b57cec5SDimitry Andric return false; 1109*0b57cec5SDimitry Andric 1110*0b57cec5SDimitry Andric if (DstVT != MVT::i32) 1111*0b57cec5SDimitry Andric return false; 1112*0b57cec5SDimitry Andric 1113*0b57cec5SDimitry Andric Value *Src = I->getOperand(0); 1114*0b57cec5SDimitry Andric Type *SrcTy = Src->getType(); 1115*0b57cec5SDimitry Andric if (!isTypeLegal(SrcTy, SrcVT)) 1116*0b57cec5SDimitry Andric return false; 1117*0b57cec5SDimitry Andric 1118*0b57cec5SDimitry Andric if (SrcVT != MVT::f32 && SrcVT != MVT::f64) 1119*0b57cec5SDimitry Andric return false; 1120*0b57cec5SDimitry Andric 1121*0b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Src); 1122*0b57cec5SDimitry Andric if (SrcReg == 0) 1123*0b57cec5SDimitry Andric return false; 1124*0b57cec5SDimitry Andric 1125*0b57cec5SDimitry Andric // Determine the opcode for the conversion, which takes place 1126*0b57cec5SDimitry Andric // entirely within FPRs. 1127*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 1128*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::FGR32RegClass); 1129*0b57cec5SDimitry Andric unsigned Opc = (SrcVT == MVT::f32) ? Mips::TRUNC_W_S : Mips::TRUNC_W_D32; 1130*0b57cec5SDimitry Andric 1131*0b57cec5SDimitry Andric // Generate the convert. 1132*0b57cec5SDimitry Andric emitInst(Opc, TempReg).addReg(SrcReg); 1133*0b57cec5SDimitry Andric emitInst(Mips::MFC1, DestReg).addReg(TempReg); 1134*0b57cec5SDimitry Andric 1135*0b57cec5SDimitry Andric updateValueMap(I, DestReg); 1136*0b57cec5SDimitry Andric return true; 1137*0b57cec5SDimitry Andric } 1138*0b57cec5SDimitry Andric 1139*0b57cec5SDimitry Andric bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, 1140*0b57cec5SDimitry Andric SmallVectorImpl<MVT> &OutVTs, 1141*0b57cec5SDimitry Andric unsigned &NumBytes) { 1142*0b57cec5SDimitry Andric CallingConv::ID CC = CLI.CallConv; 1143*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 1144*0b57cec5SDimitry Andric CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context); 1145*0b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC)); 1146*0b57cec5SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 1147*0b57cec5SDimitry Andric NumBytes = CCInfo.getNextStackOffset(); 1148*0b57cec5SDimitry Andric // This is the minimum argument area used for A0-A3. 1149*0b57cec5SDimitry Andric if (NumBytes < 16) 1150*0b57cec5SDimitry Andric NumBytes = 16; 1151*0b57cec5SDimitry Andric 1152*0b57cec5SDimitry Andric emitInst(Mips::ADJCALLSTACKDOWN).addImm(16).addImm(0); 1153*0b57cec5SDimitry Andric // Process the args. 1154*0b57cec5SDimitry Andric MVT firstMVT; 1155*0b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1156*0b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 1157*0b57cec5SDimitry Andric const Value *ArgVal = CLI.OutVals[VA.getValNo()]; 1158*0b57cec5SDimitry Andric MVT ArgVT = OutVTs[VA.getValNo()]; 1159*0b57cec5SDimitry Andric 1160*0b57cec5SDimitry Andric if (i == 0) { 1161*0b57cec5SDimitry Andric firstMVT = ArgVT; 1162*0b57cec5SDimitry Andric if (ArgVT == MVT::f32) { 1163*0b57cec5SDimitry Andric VA.convertToReg(Mips::F12); 1164*0b57cec5SDimitry Andric } else if (ArgVT == MVT::f64) { 1165*0b57cec5SDimitry Andric VA.convertToReg(Mips::D6); 1166*0b57cec5SDimitry Andric } 1167*0b57cec5SDimitry Andric } else if (i == 1) { 1168*0b57cec5SDimitry Andric if ((firstMVT == MVT::f32) || (firstMVT == MVT::f64)) { 1169*0b57cec5SDimitry Andric if (ArgVT == MVT::f32) { 1170*0b57cec5SDimitry Andric VA.convertToReg(Mips::F14); 1171*0b57cec5SDimitry Andric } else if (ArgVT == MVT::f64) { 1172*0b57cec5SDimitry Andric VA.convertToReg(Mips::D7); 1173*0b57cec5SDimitry Andric } 1174*0b57cec5SDimitry Andric } 1175*0b57cec5SDimitry Andric } 1176*0b57cec5SDimitry Andric if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32) || (ArgVT == MVT::i16) || 1177*0b57cec5SDimitry Andric (ArgVT == MVT::i8)) && 1178*0b57cec5SDimitry Andric VA.isMemLoc()) { 1179*0b57cec5SDimitry Andric switch (VA.getLocMemOffset()) { 1180*0b57cec5SDimitry Andric case 0: 1181*0b57cec5SDimitry Andric VA.convertToReg(Mips::A0); 1182*0b57cec5SDimitry Andric break; 1183*0b57cec5SDimitry Andric case 4: 1184*0b57cec5SDimitry Andric VA.convertToReg(Mips::A1); 1185*0b57cec5SDimitry Andric break; 1186*0b57cec5SDimitry Andric case 8: 1187*0b57cec5SDimitry Andric VA.convertToReg(Mips::A2); 1188*0b57cec5SDimitry Andric break; 1189*0b57cec5SDimitry Andric case 12: 1190*0b57cec5SDimitry Andric VA.convertToReg(Mips::A3); 1191*0b57cec5SDimitry Andric break; 1192*0b57cec5SDimitry Andric default: 1193*0b57cec5SDimitry Andric break; 1194*0b57cec5SDimitry Andric } 1195*0b57cec5SDimitry Andric } 1196*0b57cec5SDimitry Andric unsigned ArgReg = getRegForValue(ArgVal); 1197*0b57cec5SDimitry Andric if (!ArgReg) 1198*0b57cec5SDimitry Andric return false; 1199*0b57cec5SDimitry Andric 1200*0b57cec5SDimitry Andric // Handle arg promotion: SExt, ZExt, AExt. 1201*0b57cec5SDimitry Andric switch (VA.getLocInfo()) { 1202*0b57cec5SDimitry Andric case CCValAssign::Full: 1203*0b57cec5SDimitry Andric break; 1204*0b57cec5SDimitry Andric case CCValAssign::AExt: 1205*0b57cec5SDimitry Andric case CCValAssign::SExt: { 1206*0b57cec5SDimitry Andric MVT DestVT = VA.getLocVT(); 1207*0b57cec5SDimitry Andric MVT SrcVT = ArgVT; 1208*0b57cec5SDimitry Andric ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false); 1209*0b57cec5SDimitry Andric if (!ArgReg) 1210*0b57cec5SDimitry Andric return false; 1211*0b57cec5SDimitry Andric break; 1212*0b57cec5SDimitry Andric } 1213*0b57cec5SDimitry Andric case CCValAssign::ZExt: { 1214*0b57cec5SDimitry Andric MVT DestVT = VA.getLocVT(); 1215*0b57cec5SDimitry Andric MVT SrcVT = ArgVT; 1216*0b57cec5SDimitry Andric ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true); 1217*0b57cec5SDimitry Andric if (!ArgReg) 1218*0b57cec5SDimitry Andric return false; 1219*0b57cec5SDimitry Andric break; 1220*0b57cec5SDimitry Andric } 1221*0b57cec5SDimitry Andric default: 1222*0b57cec5SDimitry Andric llvm_unreachable("Unknown arg promotion!"); 1223*0b57cec5SDimitry Andric } 1224*0b57cec5SDimitry Andric 1225*0b57cec5SDimitry Andric // Now copy/store arg to correct locations. 1226*0b57cec5SDimitry Andric if (VA.isRegLoc() && !VA.needsCustom()) { 1227*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 1228*0b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg); 1229*0b57cec5SDimitry Andric CLI.OutRegs.push_back(VA.getLocReg()); 1230*0b57cec5SDimitry Andric } else if (VA.needsCustom()) { 1231*0b57cec5SDimitry Andric llvm_unreachable("Mips does not use custom args."); 1232*0b57cec5SDimitry Andric return false; 1233*0b57cec5SDimitry Andric } else { 1234*0b57cec5SDimitry Andric // 1235*0b57cec5SDimitry Andric // FIXME: This path will currently return false. It was copied 1236*0b57cec5SDimitry Andric // from the AArch64 port and should be essentially fine for Mips too. 1237*0b57cec5SDimitry Andric // The work to finish up this path will be done in a follow-on patch. 1238*0b57cec5SDimitry Andric // 1239*0b57cec5SDimitry Andric assert(VA.isMemLoc() && "Assuming store on stack."); 1240*0b57cec5SDimitry Andric // Don't emit stores for undef values. 1241*0b57cec5SDimitry Andric if (isa<UndefValue>(ArgVal)) 1242*0b57cec5SDimitry Andric continue; 1243*0b57cec5SDimitry Andric 1244*0b57cec5SDimitry Andric // Need to store on the stack. 1245*0b57cec5SDimitry Andric // FIXME: This alignment is incorrect but this path is disabled 1246*0b57cec5SDimitry Andric // for now (will return false). We need to determine the right alignment 1247*0b57cec5SDimitry Andric // based on the normal alignment for the underlying machine type. 1248*0b57cec5SDimitry Andric // 1249*0b57cec5SDimitry Andric unsigned ArgSize = alignTo(ArgVT.getSizeInBits(), 4); 1250*0b57cec5SDimitry Andric 1251*0b57cec5SDimitry Andric unsigned BEAlign = 0; 1252*0b57cec5SDimitry Andric if (ArgSize < 8 && !Subtarget->isLittle()) 1253*0b57cec5SDimitry Andric BEAlign = 8 - ArgSize; 1254*0b57cec5SDimitry Andric 1255*0b57cec5SDimitry Andric Address Addr; 1256*0b57cec5SDimitry Andric Addr.setKind(Address::RegBase); 1257*0b57cec5SDimitry Andric Addr.setReg(Mips::SP); 1258*0b57cec5SDimitry Andric Addr.setOffset(VA.getLocMemOffset() + BEAlign); 1259*0b57cec5SDimitry Andric 1260*0b57cec5SDimitry Andric unsigned Alignment = DL.getABITypeAlignment(ArgVal->getType()); 1261*0b57cec5SDimitry Andric MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand( 1262*0b57cec5SDimitry Andric MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()), 1263*0b57cec5SDimitry Andric MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment); 1264*0b57cec5SDimitry Andric (void)(MMO); 1265*0b57cec5SDimitry Andric // if (!emitStore(ArgVT, ArgReg, Addr, MMO)) 1266*0b57cec5SDimitry Andric return false; // can't store on the stack yet. 1267*0b57cec5SDimitry Andric } 1268*0b57cec5SDimitry Andric } 1269*0b57cec5SDimitry Andric 1270*0b57cec5SDimitry Andric return true; 1271*0b57cec5SDimitry Andric } 1272*0b57cec5SDimitry Andric 1273*0b57cec5SDimitry Andric bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, 1274*0b57cec5SDimitry Andric unsigned NumBytes) { 1275*0b57cec5SDimitry Andric CallingConv::ID CC = CLI.CallConv; 1276*0b57cec5SDimitry Andric emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0); 1277*0b57cec5SDimitry Andric if (RetVT != MVT::isVoid) { 1278*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 1279*0b57cec5SDimitry Andric MipsCCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context); 1280*0b57cec5SDimitry Andric 1281*0b57cec5SDimitry Andric CCInfo.AnalyzeCallResult(CLI.Ins, RetCC_Mips, CLI.RetTy, 1282*0b57cec5SDimitry Andric CLI.Symbol ? CLI.Symbol->getName().data() 1283*0b57cec5SDimitry Andric : nullptr); 1284*0b57cec5SDimitry Andric 1285*0b57cec5SDimitry Andric // Only handle a single return value. 1286*0b57cec5SDimitry Andric if (RVLocs.size() != 1) 1287*0b57cec5SDimitry Andric return false; 1288*0b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg. 1289*0b57cec5SDimitry Andric MVT CopyVT = RVLocs[0].getValVT(); 1290*0b57cec5SDimitry Andric // Special handling for extended integers. 1291*0b57cec5SDimitry Andric if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16) 1292*0b57cec5SDimitry Andric CopyVT = MVT::i32; 1293*0b57cec5SDimitry Andric 1294*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT)); 1295*0b57cec5SDimitry Andric if (!ResultReg) 1296*0b57cec5SDimitry Andric return false; 1297*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 1298*0b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), 1299*0b57cec5SDimitry Andric ResultReg).addReg(RVLocs[0].getLocReg()); 1300*0b57cec5SDimitry Andric CLI.InRegs.push_back(RVLocs[0].getLocReg()); 1301*0b57cec5SDimitry Andric 1302*0b57cec5SDimitry Andric CLI.ResultReg = ResultReg; 1303*0b57cec5SDimitry Andric CLI.NumResultRegs = 1; 1304*0b57cec5SDimitry Andric } 1305*0b57cec5SDimitry Andric return true; 1306*0b57cec5SDimitry Andric } 1307*0b57cec5SDimitry Andric 1308*0b57cec5SDimitry Andric bool MipsFastISel::fastLowerArguments() { 1309*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "fastLowerArguments\n"); 1310*0b57cec5SDimitry Andric 1311*0b57cec5SDimitry Andric if (!FuncInfo.CanLowerReturn) { 1312*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (!CanLowerReturn)\n"); 1313*0b57cec5SDimitry Andric return false; 1314*0b57cec5SDimitry Andric } 1315*0b57cec5SDimitry Andric 1316*0b57cec5SDimitry Andric const Function *F = FuncInfo.Fn; 1317*0b57cec5SDimitry Andric if (F->isVarArg()) { 1318*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (varargs)\n"); 1319*0b57cec5SDimitry Andric return false; 1320*0b57cec5SDimitry Andric } 1321*0b57cec5SDimitry Andric 1322*0b57cec5SDimitry Andric CallingConv::ID CC = F->getCallingConv(); 1323*0b57cec5SDimitry Andric if (CC != CallingConv::C) { 1324*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (calling convention is not C)\n"); 1325*0b57cec5SDimitry Andric return false; 1326*0b57cec5SDimitry Andric } 1327*0b57cec5SDimitry Andric 1328*0b57cec5SDimitry Andric std::array<MCPhysReg, 4> GPR32ArgRegs = {{Mips::A0, Mips::A1, Mips::A2, 1329*0b57cec5SDimitry Andric Mips::A3}}; 1330*0b57cec5SDimitry Andric std::array<MCPhysReg, 2> FGR32ArgRegs = {{Mips::F12, Mips::F14}}; 1331*0b57cec5SDimitry Andric std::array<MCPhysReg, 2> AFGR64ArgRegs = {{Mips::D6, Mips::D7}}; 1332*0b57cec5SDimitry Andric auto NextGPR32 = GPR32ArgRegs.begin(); 1333*0b57cec5SDimitry Andric auto NextFGR32 = FGR32ArgRegs.begin(); 1334*0b57cec5SDimitry Andric auto NextAFGR64 = AFGR64ArgRegs.begin(); 1335*0b57cec5SDimitry Andric 1336*0b57cec5SDimitry Andric struct AllocatedReg { 1337*0b57cec5SDimitry Andric const TargetRegisterClass *RC; 1338*0b57cec5SDimitry Andric unsigned Reg; 1339*0b57cec5SDimitry Andric AllocatedReg(const TargetRegisterClass *RC, unsigned Reg) 1340*0b57cec5SDimitry Andric : RC(RC), Reg(Reg) {} 1341*0b57cec5SDimitry Andric }; 1342*0b57cec5SDimitry Andric 1343*0b57cec5SDimitry Andric // Only handle simple cases. i.e. All arguments are directly mapped to 1344*0b57cec5SDimitry Andric // registers of the appropriate type. 1345*0b57cec5SDimitry Andric SmallVector<AllocatedReg, 4> Allocation; 1346*0b57cec5SDimitry Andric for (const auto &FormalArg : F->args()) { 1347*0b57cec5SDimitry Andric if (FormalArg.hasAttribute(Attribute::InReg) || 1348*0b57cec5SDimitry Andric FormalArg.hasAttribute(Attribute::StructRet) || 1349*0b57cec5SDimitry Andric FormalArg.hasAttribute(Attribute::ByVal)) { 1350*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n"); 1351*0b57cec5SDimitry Andric return false; 1352*0b57cec5SDimitry Andric } 1353*0b57cec5SDimitry Andric 1354*0b57cec5SDimitry Andric Type *ArgTy = FormalArg.getType(); 1355*0b57cec5SDimitry Andric if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy()) { 1356*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (struct, array, or vector)\n"); 1357*0b57cec5SDimitry Andric return false; 1358*0b57cec5SDimitry Andric } 1359*0b57cec5SDimitry Andric 1360*0b57cec5SDimitry Andric EVT ArgVT = TLI.getValueType(DL, ArgTy); 1361*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": " 1362*0b57cec5SDimitry Andric << ArgVT.getEVTString() << "\n"); 1363*0b57cec5SDimitry Andric if (!ArgVT.isSimple()) { 1364*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (not a simple type)\n"); 1365*0b57cec5SDimitry Andric return false; 1366*0b57cec5SDimitry Andric } 1367*0b57cec5SDimitry Andric 1368*0b57cec5SDimitry Andric switch (ArgVT.getSimpleVT().SimpleTy) { 1369*0b57cec5SDimitry Andric case MVT::i1: 1370*0b57cec5SDimitry Andric case MVT::i8: 1371*0b57cec5SDimitry Andric case MVT::i16: 1372*0b57cec5SDimitry Andric if (!FormalArg.hasAttribute(Attribute::SExt) && 1373*0b57cec5SDimitry Andric !FormalArg.hasAttribute(Attribute::ZExt)) { 1374*0b57cec5SDimitry Andric // It must be any extend, this shouldn't happen for clang-generated IR 1375*0b57cec5SDimitry Andric // so just fall back on SelectionDAG. 1376*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n"); 1377*0b57cec5SDimitry Andric return false; 1378*0b57cec5SDimitry Andric } 1379*0b57cec5SDimitry Andric 1380*0b57cec5SDimitry Andric if (NextGPR32 == GPR32ArgRegs.end()) { 1381*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); 1382*0b57cec5SDimitry Andric return false; 1383*0b57cec5SDimitry Andric } 1384*0b57cec5SDimitry Andric 1385*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); 1386*0b57cec5SDimitry Andric Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); 1387*0b57cec5SDimitry Andric 1388*0b57cec5SDimitry Andric // Allocating any GPR32 prohibits further use of floating point arguments. 1389*0b57cec5SDimitry Andric NextFGR32 = FGR32ArgRegs.end(); 1390*0b57cec5SDimitry Andric NextAFGR64 = AFGR64ArgRegs.end(); 1391*0b57cec5SDimitry Andric break; 1392*0b57cec5SDimitry Andric 1393*0b57cec5SDimitry Andric case MVT::i32: 1394*0b57cec5SDimitry Andric if (FormalArg.hasAttribute(Attribute::ZExt)) { 1395*0b57cec5SDimitry Andric // The O32 ABI does not permit a zero-extended i32. 1396*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n"); 1397*0b57cec5SDimitry Andric return false; 1398*0b57cec5SDimitry Andric } 1399*0b57cec5SDimitry Andric 1400*0b57cec5SDimitry Andric if (NextGPR32 == GPR32ArgRegs.end()) { 1401*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); 1402*0b57cec5SDimitry Andric return false; 1403*0b57cec5SDimitry Andric } 1404*0b57cec5SDimitry Andric 1405*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); 1406*0b57cec5SDimitry Andric Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); 1407*0b57cec5SDimitry Andric 1408*0b57cec5SDimitry Andric // Allocating any GPR32 prohibits further use of floating point arguments. 1409*0b57cec5SDimitry Andric NextFGR32 = FGR32ArgRegs.end(); 1410*0b57cec5SDimitry Andric NextAFGR64 = AFGR64ArgRegs.end(); 1411*0b57cec5SDimitry Andric break; 1412*0b57cec5SDimitry Andric 1413*0b57cec5SDimitry Andric case MVT::f32: 1414*0b57cec5SDimitry Andric if (UnsupportedFPMode) { 1415*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); 1416*0b57cec5SDimitry Andric return false; 1417*0b57cec5SDimitry Andric } 1418*0b57cec5SDimitry Andric if (NextFGR32 == FGR32ArgRegs.end()) { 1419*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n"); 1420*0b57cec5SDimitry Andric return false; 1421*0b57cec5SDimitry Andric } 1422*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n"); 1423*0b57cec5SDimitry Andric Allocation.emplace_back(&Mips::FGR32RegClass, *NextFGR32++); 1424*0b57cec5SDimitry Andric // Allocating an FGR32 also allocates the super-register AFGR64, and 1425*0b57cec5SDimitry Andric // ABI rules require us to skip the corresponding GPR32. 1426*0b57cec5SDimitry Andric if (NextGPR32 != GPR32ArgRegs.end()) 1427*0b57cec5SDimitry Andric NextGPR32++; 1428*0b57cec5SDimitry Andric if (NextAFGR64 != AFGR64ArgRegs.end()) 1429*0b57cec5SDimitry Andric NextAFGR64++; 1430*0b57cec5SDimitry Andric break; 1431*0b57cec5SDimitry Andric 1432*0b57cec5SDimitry Andric case MVT::f64: 1433*0b57cec5SDimitry Andric if (UnsupportedFPMode) { 1434*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); 1435*0b57cec5SDimitry Andric return false; 1436*0b57cec5SDimitry Andric } 1437*0b57cec5SDimitry Andric if (NextAFGR64 == AFGR64ArgRegs.end()) { 1438*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n"); 1439*0b57cec5SDimitry Andric return false; 1440*0b57cec5SDimitry Andric } 1441*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n"); 1442*0b57cec5SDimitry Andric Allocation.emplace_back(&Mips::AFGR64RegClass, *NextAFGR64++); 1443*0b57cec5SDimitry Andric // Allocating an FGR32 also allocates the super-register AFGR64, and 1444*0b57cec5SDimitry Andric // ABI rules require us to skip the corresponding GPR32 pair. 1445*0b57cec5SDimitry Andric if (NextGPR32 != GPR32ArgRegs.end()) 1446*0b57cec5SDimitry Andric NextGPR32++; 1447*0b57cec5SDimitry Andric if (NextGPR32 != GPR32ArgRegs.end()) 1448*0b57cec5SDimitry Andric NextGPR32++; 1449*0b57cec5SDimitry Andric if (NextFGR32 != FGR32ArgRegs.end()) 1450*0b57cec5SDimitry Andric NextFGR32++; 1451*0b57cec5SDimitry Andric break; 1452*0b57cec5SDimitry Andric 1453*0b57cec5SDimitry Andric default: 1454*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (unknown type)\n"); 1455*0b57cec5SDimitry Andric return false; 1456*0b57cec5SDimitry Andric } 1457*0b57cec5SDimitry Andric } 1458*0b57cec5SDimitry Andric 1459*0b57cec5SDimitry Andric for (const auto &FormalArg : F->args()) { 1460*0b57cec5SDimitry Andric unsigned ArgNo = FormalArg.getArgNo(); 1461*0b57cec5SDimitry Andric unsigned SrcReg = Allocation[ArgNo].Reg; 1462*0b57cec5SDimitry Andric unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, Allocation[ArgNo].RC); 1463*0b57cec5SDimitry Andric // FIXME: Unfortunately it's necessary to emit a copy from the livein copy. 1464*0b57cec5SDimitry Andric // Without this, EmitLiveInCopies may eliminate the livein if its only 1465*0b57cec5SDimitry Andric // use is a bitcast (which isn't turned into an instruction). 1466*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(Allocation[ArgNo].RC); 1467*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 1468*0b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), ResultReg) 1469*0b57cec5SDimitry Andric .addReg(DstReg, getKillRegState(true)); 1470*0b57cec5SDimitry Andric updateValueMap(&FormalArg, ResultReg); 1471*0b57cec5SDimitry Andric } 1472*0b57cec5SDimitry Andric 1473*0b57cec5SDimitry Andric // Calculate the size of the incoming arguments area. 1474*0b57cec5SDimitry Andric // We currently reject all the cases where this would be non-zero. 1475*0b57cec5SDimitry Andric unsigned IncomingArgSizeInBytes = 0; 1476*0b57cec5SDimitry Andric 1477*0b57cec5SDimitry Andric // Account for the reserved argument area on ABI's that have one (O32). 1478*0b57cec5SDimitry Andric // It seems strange to do this on the caller side but it's necessary in 1479*0b57cec5SDimitry Andric // SelectionDAG's implementation. 1480*0b57cec5SDimitry Andric IncomingArgSizeInBytes = std::min(getABI().GetCalleeAllocdArgSizeInBytes(CC), 1481*0b57cec5SDimitry Andric IncomingArgSizeInBytes); 1482*0b57cec5SDimitry Andric 1483*0b57cec5SDimitry Andric MF->getInfo<MipsFunctionInfo>()->setFormalArgInfo(IncomingArgSizeInBytes, 1484*0b57cec5SDimitry Andric false); 1485*0b57cec5SDimitry Andric 1486*0b57cec5SDimitry Andric return true; 1487*0b57cec5SDimitry Andric } 1488*0b57cec5SDimitry Andric 1489*0b57cec5SDimitry Andric bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { 1490*0b57cec5SDimitry Andric CallingConv::ID CC = CLI.CallConv; 1491*0b57cec5SDimitry Andric bool IsTailCall = CLI.IsTailCall; 1492*0b57cec5SDimitry Andric bool IsVarArg = CLI.IsVarArg; 1493*0b57cec5SDimitry Andric const Value *Callee = CLI.Callee; 1494*0b57cec5SDimitry Andric MCSymbol *Symbol = CLI.Symbol; 1495*0b57cec5SDimitry Andric 1496*0b57cec5SDimitry Andric // Do not handle FastCC. 1497*0b57cec5SDimitry Andric if (CC == CallingConv::Fast) 1498*0b57cec5SDimitry Andric return false; 1499*0b57cec5SDimitry Andric 1500*0b57cec5SDimitry Andric // Allow SelectionDAG isel to handle tail calls. 1501*0b57cec5SDimitry Andric if (IsTailCall) 1502*0b57cec5SDimitry Andric return false; 1503*0b57cec5SDimitry Andric 1504*0b57cec5SDimitry Andric // Let SDISel handle vararg functions. 1505*0b57cec5SDimitry Andric if (IsVarArg) 1506*0b57cec5SDimitry Andric return false; 1507*0b57cec5SDimitry Andric 1508*0b57cec5SDimitry Andric // FIXME: Only handle *simple* calls for now. 1509*0b57cec5SDimitry Andric MVT RetVT; 1510*0b57cec5SDimitry Andric if (CLI.RetTy->isVoidTy()) 1511*0b57cec5SDimitry Andric RetVT = MVT::isVoid; 1512*0b57cec5SDimitry Andric else if (!isTypeSupported(CLI.RetTy, RetVT)) 1513*0b57cec5SDimitry Andric return false; 1514*0b57cec5SDimitry Andric 1515*0b57cec5SDimitry Andric for (auto Flag : CLI.OutFlags) 1516*0b57cec5SDimitry Andric if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal()) 1517*0b57cec5SDimitry Andric return false; 1518*0b57cec5SDimitry Andric 1519*0b57cec5SDimitry Andric // Set up the argument vectors. 1520*0b57cec5SDimitry Andric SmallVector<MVT, 16> OutVTs; 1521*0b57cec5SDimitry Andric OutVTs.reserve(CLI.OutVals.size()); 1522*0b57cec5SDimitry Andric 1523*0b57cec5SDimitry Andric for (auto *Val : CLI.OutVals) { 1524*0b57cec5SDimitry Andric MVT VT; 1525*0b57cec5SDimitry Andric if (!isTypeLegal(Val->getType(), VT) && 1526*0b57cec5SDimitry Andric !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)) 1527*0b57cec5SDimitry Andric return false; 1528*0b57cec5SDimitry Andric 1529*0b57cec5SDimitry Andric // We don't handle vector parameters yet. 1530*0b57cec5SDimitry Andric if (VT.isVector() || VT.getSizeInBits() > 64) 1531*0b57cec5SDimitry Andric return false; 1532*0b57cec5SDimitry Andric 1533*0b57cec5SDimitry Andric OutVTs.push_back(VT); 1534*0b57cec5SDimitry Andric } 1535*0b57cec5SDimitry Andric 1536*0b57cec5SDimitry Andric Address Addr; 1537*0b57cec5SDimitry Andric if (!computeCallAddress(Callee, Addr)) 1538*0b57cec5SDimitry Andric return false; 1539*0b57cec5SDimitry Andric 1540*0b57cec5SDimitry Andric // Handle the arguments now that we've gotten them. 1541*0b57cec5SDimitry Andric unsigned NumBytes; 1542*0b57cec5SDimitry Andric if (!processCallArgs(CLI, OutVTs, NumBytes)) 1543*0b57cec5SDimitry Andric return false; 1544*0b57cec5SDimitry Andric 1545*0b57cec5SDimitry Andric if (!Addr.getGlobalValue()) 1546*0b57cec5SDimitry Andric return false; 1547*0b57cec5SDimitry Andric 1548*0b57cec5SDimitry Andric // Issue the call. 1549*0b57cec5SDimitry Andric unsigned DestAddress; 1550*0b57cec5SDimitry Andric if (Symbol) 1551*0b57cec5SDimitry Andric DestAddress = materializeExternalCallSym(Symbol); 1552*0b57cec5SDimitry Andric else 1553*0b57cec5SDimitry Andric DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); 1554*0b57cec5SDimitry Andric emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress); 1555*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 1556*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR), 1557*0b57cec5SDimitry Andric Mips::RA).addReg(Mips::T9); 1558*0b57cec5SDimitry Andric 1559*0b57cec5SDimitry Andric // Add implicit physical register uses to the call. 1560*0b57cec5SDimitry Andric for (auto Reg : CLI.OutRegs) 1561*0b57cec5SDimitry Andric MIB.addReg(Reg, RegState::Implicit); 1562*0b57cec5SDimitry Andric 1563*0b57cec5SDimitry Andric // Add a register mask with the call-preserved registers. 1564*0b57cec5SDimitry Andric // Proper defs for return values will be added by setPhysRegsDeadExcept(). 1565*0b57cec5SDimitry Andric MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC)); 1566*0b57cec5SDimitry Andric 1567*0b57cec5SDimitry Andric CLI.Call = MIB; 1568*0b57cec5SDimitry Andric 1569*0b57cec5SDimitry Andric if (EmitJalrReloc && !Subtarget->inMips16Mode()) { 1570*0b57cec5SDimitry Andric // Attach callee address to the instruction, let asm printer emit 1571*0b57cec5SDimitry Andric // .reloc R_MIPS_JALR. 1572*0b57cec5SDimitry Andric if (Symbol) 1573*0b57cec5SDimitry Andric MIB.addSym(Symbol, MipsII::MO_JALR); 1574*0b57cec5SDimitry Andric else 1575*0b57cec5SDimitry Andric MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol( 1576*0b57cec5SDimitry Andric Addr.getGlobalValue()->getName()), MipsII::MO_JALR); 1577*0b57cec5SDimitry Andric } 1578*0b57cec5SDimitry Andric 1579*0b57cec5SDimitry Andric // Finish off the call including any return values. 1580*0b57cec5SDimitry Andric return finishCall(CLI, RetVT, NumBytes); 1581*0b57cec5SDimitry Andric } 1582*0b57cec5SDimitry Andric 1583*0b57cec5SDimitry Andric bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) { 1584*0b57cec5SDimitry Andric switch (II->getIntrinsicID()) { 1585*0b57cec5SDimitry Andric default: 1586*0b57cec5SDimitry Andric return false; 1587*0b57cec5SDimitry Andric case Intrinsic::bswap: { 1588*0b57cec5SDimitry Andric Type *RetTy = II->getCalledFunction()->getReturnType(); 1589*0b57cec5SDimitry Andric 1590*0b57cec5SDimitry Andric MVT VT; 1591*0b57cec5SDimitry Andric if (!isTypeSupported(RetTy, VT)) 1592*0b57cec5SDimitry Andric return false; 1593*0b57cec5SDimitry Andric 1594*0b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(II->getOperand(0)); 1595*0b57cec5SDimitry Andric if (SrcReg == 0) 1596*0b57cec5SDimitry Andric return false; 1597*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 1598*0b57cec5SDimitry Andric if (DestReg == 0) 1599*0b57cec5SDimitry Andric return false; 1600*0b57cec5SDimitry Andric if (VT == MVT::i16) { 1601*0b57cec5SDimitry Andric if (Subtarget->hasMips32r2()) { 1602*0b57cec5SDimitry Andric emitInst(Mips::WSBH, DestReg).addReg(SrcReg); 1603*0b57cec5SDimitry Andric updateValueMap(II, DestReg); 1604*0b57cec5SDimitry Andric return true; 1605*0b57cec5SDimitry Andric } else { 1606*0b57cec5SDimitry Andric unsigned TempReg[3]; 1607*0b57cec5SDimitry Andric for (int i = 0; i < 3; i++) { 1608*0b57cec5SDimitry Andric TempReg[i] = createResultReg(&Mips::GPR32RegClass); 1609*0b57cec5SDimitry Andric if (TempReg[i] == 0) 1610*0b57cec5SDimitry Andric return false; 1611*0b57cec5SDimitry Andric } 1612*0b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8); 1613*0b57cec5SDimitry Andric emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8); 1614*0b57cec5SDimitry Andric emitInst(Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]); 1615*0b57cec5SDimitry Andric emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF); 1616*0b57cec5SDimitry Andric updateValueMap(II, DestReg); 1617*0b57cec5SDimitry Andric return true; 1618*0b57cec5SDimitry Andric } 1619*0b57cec5SDimitry Andric } else if (VT == MVT::i32) { 1620*0b57cec5SDimitry Andric if (Subtarget->hasMips32r2()) { 1621*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 1622*0b57cec5SDimitry Andric emitInst(Mips::WSBH, TempReg).addReg(SrcReg); 1623*0b57cec5SDimitry Andric emitInst(Mips::ROTR, DestReg).addReg(TempReg).addImm(16); 1624*0b57cec5SDimitry Andric updateValueMap(II, DestReg); 1625*0b57cec5SDimitry Andric return true; 1626*0b57cec5SDimitry Andric } else { 1627*0b57cec5SDimitry Andric unsigned TempReg[8]; 1628*0b57cec5SDimitry Andric for (int i = 0; i < 8; i++) { 1629*0b57cec5SDimitry Andric TempReg[i] = createResultReg(&Mips::GPR32RegClass); 1630*0b57cec5SDimitry Andric if (TempReg[i] == 0) 1631*0b57cec5SDimitry Andric return false; 1632*0b57cec5SDimitry Andric } 1633*0b57cec5SDimitry Andric 1634*0b57cec5SDimitry Andric emitInst(Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8); 1635*0b57cec5SDimitry Andric emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24); 1636*0b57cec5SDimitry Andric emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00); 1637*0b57cec5SDimitry Andric emitInst(Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]); 1638*0b57cec5SDimitry Andric 1639*0b57cec5SDimitry Andric emitInst(Mips::ANDi, TempReg[4]).addReg(SrcReg).addImm(0xFF00); 1640*0b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg[5]).addReg(TempReg[4]).addImm(8); 1641*0b57cec5SDimitry Andric 1642*0b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg[6]).addReg(SrcReg).addImm(24); 1643*0b57cec5SDimitry Andric emitInst(Mips::OR, TempReg[7]).addReg(TempReg[3]).addReg(TempReg[5]); 1644*0b57cec5SDimitry Andric emitInst(Mips::OR, DestReg).addReg(TempReg[6]).addReg(TempReg[7]); 1645*0b57cec5SDimitry Andric updateValueMap(II, DestReg); 1646*0b57cec5SDimitry Andric return true; 1647*0b57cec5SDimitry Andric } 1648*0b57cec5SDimitry Andric } 1649*0b57cec5SDimitry Andric return false; 1650*0b57cec5SDimitry Andric } 1651*0b57cec5SDimitry Andric case Intrinsic::memcpy: 1652*0b57cec5SDimitry Andric case Intrinsic::memmove: { 1653*0b57cec5SDimitry Andric const auto *MTI = cast<MemTransferInst>(II); 1654*0b57cec5SDimitry Andric // Don't handle volatile. 1655*0b57cec5SDimitry Andric if (MTI->isVolatile()) 1656*0b57cec5SDimitry Andric return false; 1657*0b57cec5SDimitry Andric if (!MTI->getLength()->getType()->isIntegerTy(32)) 1658*0b57cec5SDimitry Andric return false; 1659*0b57cec5SDimitry Andric const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove"; 1660*0b57cec5SDimitry Andric return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 1); 1661*0b57cec5SDimitry Andric } 1662*0b57cec5SDimitry Andric case Intrinsic::memset: { 1663*0b57cec5SDimitry Andric const MemSetInst *MSI = cast<MemSetInst>(II); 1664*0b57cec5SDimitry Andric // Don't handle volatile. 1665*0b57cec5SDimitry Andric if (MSI->isVolatile()) 1666*0b57cec5SDimitry Andric return false; 1667*0b57cec5SDimitry Andric if (!MSI->getLength()->getType()->isIntegerTy(32)) 1668*0b57cec5SDimitry Andric return false; 1669*0b57cec5SDimitry Andric return lowerCallTo(II, "memset", II->getNumArgOperands() - 1); 1670*0b57cec5SDimitry Andric } 1671*0b57cec5SDimitry Andric } 1672*0b57cec5SDimitry Andric return false; 1673*0b57cec5SDimitry Andric } 1674*0b57cec5SDimitry Andric 1675*0b57cec5SDimitry Andric bool MipsFastISel::selectRet(const Instruction *I) { 1676*0b57cec5SDimitry Andric const Function &F = *I->getParent()->getParent(); 1677*0b57cec5SDimitry Andric const ReturnInst *Ret = cast<ReturnInst>(I); 1678*0b57cec5SDimitry Andric 1679*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "selectRet\n"); 1680*0b57cec5SDimitry Andric 1681*0b57cec5SDimitry Andric if (!FuncInfo.CanLowerReturn) 1682*0b57cec5SDimitry Andric return false; 1683*0b57cec5SDimitry Andric 1684*0b57cec5SDimitry Andric // Build a list of return value registers. 1685*0b57cec5SDimitry Andric SmallVector<unsigned, 4> RetRegs; 1686*0b57cec5SDimitry Andric 1687*0b57cec5SDimitry Andric if (Ret->getNumOperands() > 0) { 1688*0b57cec5SDimitry Andric CallingConv::ID CC = F.getCallingConv(); 1689*0b57cec5SDimitry Andric 1690*0b57cec5SDimitry Andric // Do not handle FastCC. 1691*0b57cec5SDimitry Andric if (CC == CallingConv::Fast) 1692*0b57cec5SDimitry Andric return false; 1693*0b57cec5SDimitry Andric 1694*0b57cec5SDimitry Andric SmallVector<ISD::OutputArg, 4> Outs; 1695*0b57cec5SDimitry Andric GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL); 1696*0b57cec5SDimitry Andric 1697*0b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand. 1698*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ValLocs; 1699*0b57cec5SDimitry Andric MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, 1700*0b57cec5SDimitry Andric I->getContext()); 1701*0b57cec5SDimitry Andric CCAssignFn *RetCC = RetCC_Mips; 1702*0b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC); 1703*0b57cec5SDimitry Andric 1704*0b57cec5SDimitry Andric // Only handle a single return value for now. 1705*0b57cec5SDimitry Andric if (ValLocs.size() != 1) 1706*0b57cec5SDimitry Andric return false; 1707*0b57cec5SDimitry Andric 1708*0b57cec5SDimitry Andric CCValAssign &VA = ValLocs[0]; 1709*0b57cec5SDimitry Andric const Value *RV = Ret->getOperand(0); 1710*0b57cec5SDimitry Andric 1711*0b57cec5SDimitry Andric // Don't bother handling odd stuff for now. 1712*0b57cec5SDimitry Andric if ((VA.getLocInfo() != CCValAssign::Full) && 1713*0b57cec5SDimitry Andric (VA.getLocInfo() != CCValAssign::BCvt)) 1714*0b57cec5SDimitry Andric return false; 1715*0b57cec5SDimitry Andric 1716*0b57cec5SDimitry Andric // Only handle register returns for now. 1717*0b57cec5SDimitry Andric if (!VA.isRegLoc()) 1718*0b57cec5SDimitry Andric return false; 1719*0b57cec5SDimitry Andric 1720*0b57cec5SDimitry Andric unsigned Reg = getRegForValue(RV); 1721*0b57cec5SDimitry Andric if (Reg == 0) 1722*0b57cec5SDimitry Andric return false; 1723*0b57cec5SDimitry Andric 1724*0b57cec5SDimitry Andric unsigned SrcReg = Reg + VA.getValNo(); 1725*0b57cec5SDimitry Andric unsigned DestReg = VA.getLocReg(); 1726*0b57cec5SDimitry Andric // Avoid a cross-class copy. This is very unlikely. 1727*0b57cec5SDimitry Andric if (!MRI.getRegClass(SrcReg)->contains(DestReg)) 1728*0b57cec5SDimitry Andric return false; 1729*0b57cec5SDimitry Andric 1730*0b57cec5SDimitry Andric EVT RVEVT = TLI.getValueType(DL, RV->getType()); 1731*0b57cec5SDimitry Andric if (!RVEVT.isSimple()) 1732*0b57cec5SDimitry Andric return false; 1733*0b57cec5SDimitry Andric 1734*0b57cec5SDimitry Andric if (RVEVT.isVector()) 1735*0b57cec5SDimitry Andric return false; 1736*0b57cec5SDimitry Andric 1737*0b57cec5SDimitry Andric MVT RVVT = RVEVT.getSimpleVT(); 1738*0b57cec5SDimitry Andric if (RVVT == MVT::f128) 1739*0b57cec5SDimitry Andric return false; 1740*0b57cec5SDimitry Andric 1741*0b57cec5SDimitry Andric // Do not handle FGR64 returns for now. 1742*0b57cec5SDimitry Andric if (RVVT == MVT::f64 && UnsupportedFPMode) { 1743*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode\n"); 1744*0b57cec5SDimitry Andric return false; 1745*0b57cec5SDimitry Andric } 1746*0b57cec5SDimitry Andric 1747*0b57cec5SDimitry Andric MVT DestVT = VA.getValVT(); 1748*0b57cec5SDimitry Andric // Special handling for extended integers. 1749*0b57cec5SDimitry Andric if (RVVT != DestVT) { 1750*0b57cec5SDimitry Andric if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16) 1751*0b57cec5SDimitry Andric return false; 1752*0b57cec5SDimitry Andric 1753*0b57cec5SDimitry Andric if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) { 1754*0b57cec5SDimitry Andric bool IsZExt = Outs[0].Flags.isZExt(); 1755*0b57cec5SDimitry Andric SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt); 1756*0b57cec5SDimitry Andric if (SrcReg == 0) 1757*0b57cec5SDimitry Andric return false; 1758*0b57cec5SDimitry Andric } 1759*0b57cec5SDimitry Andric } 1760*0b57cec5SDimitry Andric 1761*0b57cec5SDimitry Andric // Make the copy. 1762*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 1763*0b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg); 1764*0b57cec5SDimitry Andric 1765*0b57cec5SDimitry Andric // Add register to return instruction. 1766*0b57cec5SDimitry Andric RetRegs.push_back(VA.getLocReg()); 1767*0b57cec5SDimitry Andric } 1768*0b57cec5SDimitry Andric MachineInstrBuilder MIB = emitInst(Mips::RetRA); 1769*0b57cec5SDimitry Andric for (unsigned i = 0, e = RetRegs.size(); i != e; ++i) 1770*0b57cec5SDimitry Andric MIB.addReg(RetRegs[i], RegState::Implicit); 1771*0b57cec5SDimitry Andric return true; 1772*0b57cec5SDimitry Andric } 1773*0b57cec5SDimitry Andric 1774*0b57cec5SDimitry Andric bool MipsFastISel::selectTrunc(const Instruction *I) { 1775*0b57cec5SDimitry Andric // The high bits for a type smaller than the register size are assumed to be 1776*0b57cec5SDimitry Andric // undefined. 1777*0b57cec5SDimitry Andric Value *Op = I->getOperand(0); 1778*0b57cec5SDimitry Andric 1779*0b57cec5SDimitry Andric EVT SrcVT, DestVT; 1780*0b57cec5SDimitry Andric SrcVT = TLI.getValueType(DL, Op->getType(), true); 1781*0b57cec5SDimitry Andric DestVT = TLI.getValueType(DL, I->getType(), true); 1782*0b57cec5SDimitry Andric 1783*0b57cec5SDimitry Andric if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8) 1784*0b57cec5SDimitry Andric return false; 1785*0b57cec5SDimitry Andric if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1) 1786*0b57cec5SDimitry Andric return false; 1787*0b57cec5SDimitry Andric 1788*0b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Op); 1789*0b57cec5SDimitry Andric if (!SrcReg) 1790*0b57cec5SDimitry Andric return false; 1791*0b57cec5SDimitry Andric 1792*0b57cec5SDimitry Andric // Because the high bits are undefined, a truncate doesn't generate 1793*0b57cec5SDimitry Andric // any code. 1794*0b57cec5SDimitry Andric updateValueMap(I, SrcReg); 1795*0b57cec5SDimitry Andric return true; 1796*0b57cec5SDimitry Andric } 1797*0b57cec5SDimitry Andric 1798*0b57cec5SDimitry Andric bool MipsFastISel::selectIntExt(const Instruction *I) { 1799*0b57cec5SDimitry Andric Type *DestTy = I->getType(); 1800*0b57cec5SDimitry Andric Value *Src = I->getOperand(0); 1801*0b57cec5SDimitry Andric Type *SrcTy = Src->getType(); 1802*0b57cec5SDimitry Andric 1803*0b57cec5SDimitry Andric bool isZExt = isa<ZExtInst>(I); 1804*0b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Src); 1805*0b57cec5SDimitry Andric if (!SrcReg) 1806*0b57cec5SDimitry Andric return false; 1807*0b57cec5SDimitry Andric 1808*0b57cec5SDimitry Andric EVT SrcEVT, DestEVT; 1809*0b57cec5SDimitry Andric SrcEVT = TLI.getValueType(DL, SrcTy, true); 1810*0b57cec5SDimitry Andric DestEVT = TLI.getValueType(DL, DestTy, true); 1811*0b57cec5SDimitry Andric if (!SrcEVT.isSimple()) 1812*0b57cec5SDimitry Andric return false; 1813*0b57cec5SDimitry Andric if (!DestEVT.isSimple()) 1814*0b57cec5SDimitry Andric return false; 1815*0b57cec5SDimitry Andric 1816*0b57cec5SDimitry Andric MVT SrcVT = SrcEVT.getSimpleVT(); 1817*0b57cec5SDimitry Andric MVT DestVT = DestEVT.getSimpleVT(); 1818*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 1819*0b57cec5SDimitry Andric 1820*0b57cec5SDimitry Andric if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt)) 1821*0b57cec5SDimitry Andric return false; 1822*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 1823*0b57cec5SDimitry Andric return true; 1824*0b57cec5SDimitry Andric } 1825*0b57cec5SDimitry Andric 1826*0b57cec5SDimitry Andric bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1827*0b57cec5SDimitry Andric unsigned DestReg) { 1828*0b57cec5SDimitry Andric unsigned ShiftAmt; 1829*0b57cec5SDimitry Andric switch (SrcVT.SimpleTy) { 1830*0b57cec5SDimitry Andric default: 1831*0b57cec5SDimitry Andric return false; 1832*0b57cec5SDimitry Andric case MVT::i8: 1833*0b57cec5SDimitry Andric ShiftAmt = 24; 1834*0b57cec5SDimitry Andric break; 1835*0b57cec5SDimitry Andric case MVT::i16: 1836*0b57cec5SDimitry Andric ShiftAmt = 16; 1837*0b57cec5SDimitry Andric break; 1838*0b57cec5SDimitry Andric } 1839*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 1840*0b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt); 1841*0b57cec5SDimitry Andric emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt); 1842*0b57cec5SDimitry Andric return true; 1843*0b57cec5SDimitry Andric } 1844*0b57cec5SDimitry Andric 1845*0b57cec5SDimitry Andric bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1846*0b57cec5SDimitry Andric unsigned DestReg) { 1847*0b57cec5SDimitry Andric switch (SrcVT.SimpleTy) { 1848*0b57cec5SDimitry Andric default: 1849*0b57cec5SDimitry Andric return false; 1850*0b57cec5SDimitry Andric case MVT::i8: 1851*0b57cec5SDimitry Andric emitInst(Mips::SEB, DestReg).addReg(SrcReg); 1852*0b57cec5SDimitry Andric break; 1853*0b57cec5SDimitry Andric case MVT::i16: 1854*0b57cec5SDimitry Andric emitInst(Mips::SEH, DestReg).addReg(SrcReg); 1855*0b57cec5SDimitry Andric break; 1856*0b57cec5SDimitry Andric } 1857*0b57cec5SDimitry Andric return true; 1858*0b57cec5SDimitry Andric } 1859*0b57cec5SDimitry Andric 1860*0b57cec5SDimitry Andric bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1861*0b57cec5SDimitry Andric unsigned DestReg) { 1862*0b57cec5SDimitry Andric if ((DestVT != MVT::i32) && (DestVT != MVT::i16)) 1863*0b57cec5SDimitry Andric return false; 1864*0b57cec5SDimitry Andric if (Subtarget->hasMips32r2()) 1865*0b57cec5SDimitry Andric return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg); 1866*0b57cec5SDimitry Andric return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg); 1867*0b57cec5SDimitry Andric } 1868*0b57cec5SDimitry Andric 1869*0b57cec5SDimitry Andric bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1870*0b57cec5SDimitry Andric unsigned DestReg) { 1871*0b57cec5SDimitry Andric int64_t Imm; 1872*0b57cec5SDimitry Andric 1873*0b57cec5SDimitry Andric switch (SrcVT.SimpleTy) { 1874*0b57cec5SDimitry Andric default: 1875*0b57cec5SDimitry Andric return false; 1876*0b57cec5SDimitry Andric case MVT::i1: 1877*0b57cec5SDimitry Andric Imm = 1; 1878*0b57cec5SDimitry Andric break; 1879*0b57cec5SDimitry Andric case MVT::i8: 1880*0b57cec5SDimitry Andric Imm = 0xff; 1881*0b57cec5SDimitry Andric break; 1882*0b57cec5SDimitry Andric case MVT::i16: 1883*0b57cec5SDimitry Andric Imm = 0xffff; 1884*0b57cec5SDimitry Andric break; 1885*0b57cec5SDimitry Andric } 1886*0b57cec5SDimitry Andric 1887*0b57cec5SDimitry Andric emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(Imm); 1888*0b57cec5SDimitry Andric return true; 1889*0b57cec5SDimitry Andric } 1890*0b57cec5SDimitry Andric 1891*0b57cec5SDimitry Andric bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1892*0b57cec5SDimitry Andric unsigned DestReg, bool IsZExt) { 1893*0b57cec5SDimitry Andric // FastISel does not have plumbing to deal with extensions where the SrcVT or 1894*0b57cec5SDimitry Andric // DestVT are odd things, so test to make sure that they are both types we can 1895*0b57cec5SDimitry Andric // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise 1896*0b57cec5SDimitry Andric // bail out to SelectionDAG. 1897*0b57cec5SDimitry Andric if (((DestVT != MVT::i8) && (DestVT != MVT::i16) && (DestVT != MVT::i32)) || 1898*0b57cec5SDimitry Andric ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) && (SrcVT != MVT::i16))) 1899*0b57cec5SDimitry Andric return false; 1900*0b57cec5SDimitry Andric if (IsZExt) 1901*0b57cec5SDimitry Andric return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg); 1902*0b57cec5SDimitry Andric return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg); 1903*0b57cec5SDimitry Andric } 1904*0b57cec5SDimitry Andric 1905*0b57cec5SDimitry Andric unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1906*0b57cec5SDimitry Andric bool isZExt) { 1907*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 1908*0b57cec5SDimitry Andric bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); 1909*0b57cec5SDimitry Andric return Success ? DestReg : 0; 1910*0b57cec5SDimitry Andric } 1911*0b57cec5SDimitry Andric 1912*0b57cec5SDimitry Andric bool MipsFastISel::selectDivRem(const Instruction *I, unsigned ISDOpcode) { 1913*0b57cec5SDimitry Andric EVT DestEVT = TLI.getValueType(DL, I->getType(), true); 1914*0b57cec5SDimitry Andric if (!DestEVT.isSimple()) 1915*0b57cec5SDimitry Andric return false; 1916*0b57cec5SDimitry Andric 1917*0b57cec5SDimitry Andric MVT DestVT = DestEVT.getSimpleVT(); 1918*0b57cec5SDimitry Andric if (DestVT != MVT::i32) 1919*0b57cec5SDimitry Andric return false; 1920*0b57cec5SDimitry Andric 1921*0b57cec5SDimitry Andric unsigned DivOpc; 1922*0b57cec5SDimitry Andric switch (ISDOpcode) { 1923*0b57cec5SDimitry Andric default: 1924*0b57cec5SDimitry Andric return false; 1925*0b57cec5SDimitry Andric case ISD::SDIV: 1926*0b57cec5SDimitry Andric case ISD::SREM: 1927*0b57cec5SDimitry Andric DivOpc = Mips::SDIV; 1928*0b57cec5SDimitry Andric break; 1929*0b57cec5SDimitry Andric case ISD::UDIV: 1930*0b57cec5SDimitry Andric case ISD::UREM: 1931*0b57cec5SDimitry Andric DivOpc = Mips::UDIV; 1932*0b57cec5SDimitry Andric break; 1933*0b57cec5SDimitry Andric } 1934*0b57cec5SDimitry Andric 1935*0b57cec5SDimitry Andric unsigned Src0Reg = getRegForValue(I->getOperand(0)); 1936*0b57cec5SDimitry Andric unsigned Src1Reg = getRegForValue(I->getOperand(1)); 1937*0b57cec5SDimitry Andric if (!Src0Reg || !Src1Reg) 1938*0b57cec5SDimitry Andric return false; 1939*0b57cec5SDimitry Andric 1940*0b57cec5SDimitry Andric emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg); 1941*0b57cec5SDimitry Andric emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7); 1942*0b57cec5SDimitry Andric 1943*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 1944*0b57cec5SDimitry Andric if (!ResultReg) 1945*0b57cec5SDimitry Andric return false; 1946*0b57cec5SDimitry Andric 1947*0b57cec5SDimitry Andric unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM) 1948*0b57cec5SDimitry Andric ? Mips::MFHI 1949*0b57cec5SDimitry Andric : Mips::MFLO; 1950*0b57cec5SDimitry Andric emitInst(MFOpc, ResultReg); 1951*0b57cec5SDimitry Andric 1952*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 1953*0b57cec5SDimitry Andric return true; 1954*0b57cec5SDimitry Andric } 1955*0b57cec5SDimitry Andric 1956*0b57cec5SDimitry Andric bool MipsFastISel::selectShift(const Instruction *I) { 1957*0b57cec5SDimitry Andric MVT RetVT; 1958*0b57cec5SDimitry Andric 1959*0b57cec5SDimitry Andric if (!isTypeSupported(I->getType(), RetVT)) 1960*0b57cec5SDimitry Andric return false; 1961*0b57cec5SDimitry Andric 1962*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 1963*0b57cec5SDimitry Andric if (!ResultReg) 1964*0b57cec5SDimitry Andric return false; 1965*0b57cec5SDimitry Andric 1966*0b57cec5SDimitry Andric unsigned Opcode = I->getOpcode(); 1967*0b57cec5SDimitry Andric const Value *Op0 = I->getOperand(0); 1968*0b57cec5SDimitry Andric unsigned Op0Reg = getRegForValue(Op0); 1969*0b57cec5SDimitry Andric if (!Op0Reg) 1970*0b57cec5SDimitry Andric return false; 1971*0b57cec5SDimitry Andric 1972*0b57cec5SDimitry Andric // If AShr or LShr, then we need to make sure the operand0 is sign extended. 1973*0b57cec5SDimitry Andric if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) { 1974*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 1975*0b57cec5SDimitry Andric if (!TempReg) 1976*0b57cec5SDimitry Andric return false; 1977*0b57cec5SDimitry Andric 1978*0b57cec5SDimitry Andric MVT Op0MVT = TLI.getValueType(DL, Op0->getType(), true).getSimpleVT(); 1979*0b57cec5SDimitry Andric bool IsZExt = Opcode == Instruction::LShr; 1980*0b57cec5SDimitry Andric if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt)) 1981*0b57cec5SDimitry Andric return false; 1982*0b57cec5SDimitry Andric 1983*0b57cec5SDimitry Andric Op0Reg = TempReg; 1984*0b57cec5SDimitry Andric } 1985*0b57cec5SDimitry Andric 1986*0b57cec5SDimitry Andric if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) { 1987*0b57cec5SDimitry Andric uint64_t ShiftVal = C->getZExtValue(); 1988*0b57cec5SDimitry Andric 1989*0b57cec5SDimitry Andric switch (Opcode) { 1990*0b57cec5SDimitry Andric default: 1991*0b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction."); 1992*0b57cec5SDimitry Andric case Instruction::Shl: 1993*0b57cec5SDimitry Andric Opcode = Mips::SLL; 1994*0b57cec5SDimitry Andric break; 1995*0b57cec5SDimitry Andric case Instruction::AShr: 1996*0b57cec5SDimitry Andric Opcode = Mips::SRA; 1997*0b57cec5SDimitry Andric break; 1998*0b57cec5SDimitry Andric case Instruction::LShr: 1999*0b57cec5SDimitry Andric Opcode = Mips::SRL; 2000*0b57cec5SDimitry Andric break; 2001*0b57cec5SDimitry Andric } 2002*0b57cec5SDimitry Andric 2003*0b57cec5SDimitry Andric emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal); 2004*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 2005*0b57cec5SDimitry Andric return true; 2006*0b57cec5SDimitry Andric } 2007*0b57cec5SDimitry Andric 2008*0b57cec5SDimitry Andric unsigned Op1Reg = getRegForValue(I->getOperand(1)); 2009*0b57cec5SDimitry Andric if (!Op1Reg) 2010*0b57cec5SDimitry Andric return false; 2011*0b57cec5SDimitry Andric 2012*0b57cec5SDimitry Andric switch (Opcode) { 2013*0b57cec5SDimitry Andric default: 2014*0b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction."); 2015*0b57cec5SDimitry Andric case Instruction::Shl: 2016*0b57cec5SDimitry Andric Opcode = Mips::SLLV; 2017*0b57cec5SDimitry Andric break; 2018*0b57cec5SDimitry Andric case Instruction::AShr: 2019*0b57cec5SDimitry Andric Opcode = Mips::SRAV; 2020*0b57cec5SDimitry Andric break; 2021*0b57cec5SDimitry Andric case Instruction::LShr: 2022*0b57cec5SDimitry Andric Opcode = Mips::SRLV; 2023*0b57cec5SDimitry Andric break; 2024*0b57cec5SDimitry Andric } 2025*0b57cec5SDimitry Andric 2026*0b57cec5SDimitry Andric emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg); 2027*0b57cec5SDimitry Andric updateValueMap(I, ResultReg); 2028*0b57cec5SDimitry Andric return true; 2029*0b57cec5SDimitry Andric } 2030*0b57cec5SDimitry Andric 2031*0b57cec5SDimitry Andric bool MipsFastISel::fastSelectInstruction(const Instruction *I) { 2032*0b57cec5SDimitry Andric switch (I->getOpcode()) { 2033*0b57cec5SDimitry Andric default: 2034*0b57cec5SDimitry Andric break; 2035*0b57cec5SDimitry Andric case Instruction::Load: 2036*0b57cec5SDimitry Andric return selectLoad(I); 2037*0b57cec5SDimitry Andric case Instruction::Store: 2038*0b57cec5SDimitry Andric return selectStore(I); 2039*0b57cec5SDimitry Andric case Instruction::SDiv: 2040*0b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::SDIV)) 2041*0b57cec5SDimitry Andric return selectDivRem(I, ISD::SDIV); 2042*0b57cec5SDimitry Andric return true; 2043*0b57cec5SDimitry Andric case Instruction::UDiv: 2044*0b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::UDIV)) 2045*0b57cec5SDimitry Andric return selectDivRem(I, ISD::UDIV); 2046*0b57cec5SDimitry Andric return true; 2047*0b57cec5SDimitry Andric case Instruction::SRem: 2048*0b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::SREM)) 2049*0b57cec5SDimitry Andric return selectDivRem(I, ISD::SREM); 2050*0b57cec5SDimitry Andric return true; 2051*0b57cec5SDimitry Andric case Instruction::URem: 2052*0b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::UREM)) 2053*0b57cec5SDimitry Andric return selectDivRem(I, ISD::UREM); 2054*0b57cec5SDimitry Andric return true; 2055*0b57cec5SDimitry Andric case Instruction::Shl: 2056*0b57cec5SDimitry Andric case Instruction::LShr: 2057*0b57cec5SDimitry Andric case Instruction::AShr: 2058*0b57cec5SDimitry Andric return selectShift(I); 2059*0b57cec5SDimitry Andric case Instruction::And: 2060*0b57cec5SDimitry Andric case Instruction::Or: 2061*0b57cec5SDimitry Andric case Instruction::Xor: 2062*0b57cec5SDimitry Andric return selectLogicalOp(I); 2063*0b57cec5SDimitry Andric case Instruction::Br: 2064*0b57cec5SDimitry Andric return selectBranch(I); 2065*0b57cec5SDimitry Andric case Instruction::Ret: 2066*0b57cec5SDimitry Andric return selectRet(I); 2067*0b57cec5SDimitry Andric case Instruction::Trunc: 2068*0b57cec5SDimitry Andric return selectTrunc(I); 2069*0b57cec5SDimitry Andric case Instruction::ZExt: 2070*0b57cec5SDimitry Andric case Instruction::SExt: 2071*0b57cec5SDimitry Andric return selectIntExt(I); 2072*0b57cec5SDimitry Andric case Instruction::FPTrunc: 2073*0b57cec5SDimitry Andric return selectFPTrunc(I); 2074*0b57cec5SDimitry Andric case Instruction::FPExt: 2075*0b57cec5SDimitry Andric return selectFPExt(I); 2076*0b57cec5SDimitry Andric case Instruction::FPToSI: 2077*0b57cec5SDimitry Andric return selectFPToInt(I, /*isSigned*/ true); 2078*0b57cec5SDimitry Andric case Instruction::FPToUI: 2079*0b57cec5SDimitry Andric return selectFPToInt(I, /*isSigned*/ false); 2080*0b57cec5SDimitry Andric case Instruction::ICmp: 2081*0b57cec5SDimitry Andric case Instruction::FCmp: 2082*0b57cec5SDimitry Andric return selectCmp(I); 2083*0b57cec5SDimitry Andric case Instruction::Select: 2084*0b57cec5SDimitry Andric return selectSelect(I); 2085*0b57cec5SDimitry Andric } 2086*0b57cec5SDimitry Andric return false; 2087*0b57cec5SDimitry Andric } 2088*0b57cec5SDimitry Andric 2089*0b57cec5SDimitry Andric unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, 2090*0b57cec5SDimitry Andric bool IsUnsigned) { 2091*0b57cec5SDimitry Andric unsigned VReg = getRegForValue(V); 2092*0b57cec5SDimitry Andric if (VReg == 0) 2093*0b57cec5SDimitry Andric return 0; 2094*0b57cec5SDimitry Andric MVT VMVT = TLI.getValueType(DL, V->getType(), true).getSimpleVT(); 2095*0b57cec5SDimitry Andric 2096*0b57cec5SDimitry Andric if (VMVT == MVT::i1) 2097*0b57cec5SDimitry Andric return 0; 2098*0b57cec5SDimitry Andric 2099*0b57cec5SDimitry Andric if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) { 2100*0b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 2101*0b57cec5SDimitry Andric if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned)) 2102*0b57cec5SDimitry Andric return 0; 2103*0b57cec5SDimitry Andric VReg = TempReg; 2104*0b57cec5SDimitry Andric } 2105*0b57cec5SDimitry Andric return VReg; 2106*0b57cec5SDimitry Andric } 2107*0b57cec5SDimitry Andric 2108*0b57cec5SDimitry Andric void MipsFastISel::simplifyAddress(Address &Addr) { 2109*0b57cec5SDimitry Andric if (!isInt<16>(Addr.getOffset())) { 2110*0b57cec5SDimitry Andric unsigned TempReg = 2111*0b57cec5SDimitry Andric materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass); 2112*0b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 2113*0b57cec5SDimitry Andric emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg()); 2114*0b57cec5SDimitry Andric Addr.setReg(DestReg); 2115*0b57cec5SDimitry Andric Addr.setOffset(0); 2116*0b57cec5SDimitry Andric } 2117*0b57cec5SDimitry Andric } 2118*0b57cec5SDimitry Andric 2119*0b57cec5SDimitry Andric unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode, 2120*0b57cec5SDimitry Andric const TargetRegisterClass *RC, 2121*0b57cec5SDimitry Andric unsigned Op0, bool Op0IsKill, 2122*0b57cec5SDimitry Andric unsigned Op1, bool Op1IsKill) { 2123*0b57cec5SDimitry Andric // We treat the MUL instruction in a special way because it clobbers 2124*0b57cec5SDimitry Andric // the HI0 & LO0 registers. The TableGen definition of this instruction can 2125*0b57cec5SDimitry Andric // mark these registers only as implicitly defined. As a result, the 2126*0b57cec5SDimitry Andric // register allocator runs out of registers when this instruction is 2127*0b57cec5SDimitry Andric // followed by another instruction that defines the same registers too. 2128*0b57cec5SDimitry Andric // We can fix this by explicitly marking those registers as dead. 2129*0b57cec5SDimitry Andric if (MachineInstOpcode == Mips::MUL) { 2130*0b57cec5SDimitry Andric unsigned ResultReg = createResultReg(RC); 2131*0b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(MachineInstOpcode); 2132*0b57cec5SDimitry Andric Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs()); 2133*0b57cec5SDimitry Andric Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1); 2134*0b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg) 2135*0b57cec5SDimitry Andric .addReg(Op0, getKillRegState(Op0IsKill)) 2136*0b57cec5SDimitry Andric .addReg(Op1, getKillRegState(Op1IsKill)) 2137*0b57cec5SDimitry Andric .addReg(Mips::HI0, RegState::ImplicitDefine | RegState::Dead) 2138*0b57cec5SDimitry Andric .addReg(Mips::LO0, RegState::ImplicitDefine | RegState::Dead); 2139*0b57cec5SDimitry Andric return ResultReg; 2140*0b57cec5SDimitry Andric } 2141*0b57cec5SDimitry Andric 2142*0b57cec5SDimitry Andric return FastISel::fastEmitInst_rr(MachineInstOpcode, RC, Op0, Op0IsKill, Op1, 2143*0b57cec5SDimitry Andric Op1IsKill); 2144*0b57cec5SDimitry Andric } 2145*0b57cec5SDimitry Andric 2146*0b57cec5SDimitry Andric namespace llvm { 2147*0b57cec5SDimitry Andric 2148*0b57cec5SDimitry Andric FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, 2149*0b57cec5SDimitry Andric const TargetLibraryInfo *libInfo) { 2150*0b57cec5SDimitry Andric return new MipsFastISel(funcInfo, libInfo); 2151*0b57cec5SDimitry Andric } 2152*0b57cec5SDimitry Andric 2153*0b57cec5SDimitry Andric } // end namespace llvm 2154