10b57cec5SDimitry Andric //===- MipsFastISel.cpp - Mips FastISel implementation --------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file defines the MIPS-specific support for the FastISel class. 110b57cec5SDimitry Andric /// Some of the target-specific code is generated by tablegen in the file 120b57cec5SDimitry Andric /// MipsGenFastISel.inc, which is #included here. 130b57cec5SDimitry Andric /// 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h" 170b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h" 180b57cec5SDimitry Andric #include "MipsCCState.h" 190b57cec5SDimitry Andric #include "MipsISelLowering.h" 200b57cec5SDimitry Andric #include "MipsInstrInfo.h" 210b57cec5SDimitry Andric #include "MipsMachineFunction.h" 220b57cec5SDimitry Andric #include "MipsSubtarget.h" 230b57cec5SDimitry Andric #include "MipsTargetMachine.h" 240b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 250b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 260b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 270b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/FastISel.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 380b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 390b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 400b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h" 410b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 420b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 430b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 440b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 450b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 460b57cec5SDimitry Andric #include "llvm/IR/Function.h" 470b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h" 480b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 490b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 500b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 510b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 520b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 530b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 540b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 550b57cec5SDimitry Andric #include "llvm/IR/Type.h" 560b57cec5SDimitry Andric #include "llvm/IR/User.h" 570b57cec5SDimitry Andric #include "llvm/IR/Value.h" 580b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 590b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 600b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 610b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 620b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 630b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 640b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 650b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 660b57cec5SDimitry Andric #include "llvm/Support/MachineValueType.h" 670b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 680b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 690b57cec5SDimitry Andric #include <algorithm> 700b57cec5SDimitry Andric #include <array> 710b57cec5SDimitry Andric #include <cassert> 720b57cec5SDimitry Andric #include <cstdint> 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric #define DEBUG_TYPE "mips-fastisel" 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric using namespace llvm; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric extern cl::opt<bool> EmitJalrReloc; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric namespace { 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric class MipsFastISel final : public FastISel { 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric // All possible address modes. 850b57cec5SDimitry Andric class Address { 860b57cec5SDimitry Andric public: 870b57cec5SDimitry Andric using BaseKind = enum { RegBase, FrameIndexBase }; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric private: 900b57cec5SDimitry Andric BaseKind Kind = RegBase; 910b57cec5SDimitry Andric union { 920b57cec5SDimitry Andric unsigned Reg; 930b57cec5SDimitry Andric int FI; 940b57cec5SDimitry Andric } Base; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric int64_t Offset = 0; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric const GlobalValue *GV = nullptr; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric public: 1010b57cec5SDimitry Andric // Innocuous defaults for our address. 1020b57cec5SDimitry Andric Address() { Base.Reg = 0; } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric void setKind(BaseKind K) { Kind = K; } 1050b57cec5SDimitry Andric BaseKind getKind() const { return Kind; } 1060b57cec5SDimitry Andric bool isRegBase() const { return Kind == RegBase; } 1070b57cec5SDimitry Andric bool isFIBase() const { return Kind == FrameIndexBase; } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric void setReg(unsigned Reg) { 1100b57cec5SDimitry Andric assert(isRegBase() && "Invalid base register access!"); 1110b57cec5SDimitry Andric Base.Reg = Reg; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric unsigned getReg() const { 1150b57cec5SDimitry Andric assert(isRegBase() && "Invalid base register access!"); 1160b57cec5SDimitry Andric return Base.Reg; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric void setFI(unsigned FI) { 1200b57cec5SDimitry Andric assert(isFIBase() && "Invalid base frame index access!"); 1210b57cec5SDimitry Andric Base.FI = FI; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric unsigned getFI() const { 1250b57cec5SDimitry Andric assert(isFIBase() && "Invalid base frame index access!"); 1260b57cec5SDimitry Andric return Base.FI; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric void setOffset(int64_t Offset_) { Offset = Offset_; } 1300b57cec5SDimitry Andric int64_t getOffset() const { return Offset; } 1310b57cec5SDimitry Andric void setGlobalValue(const GlobalValue *G) { GV = G; } 1320b57cec5SDimitry Andric const GlobalValue *getGlobalValue() { return GV; } 1330b57cec5SDimitry Andric }; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can 1360b57cec5SDimitry Andric /// make the right decision when generating code for different targets. 1370b57cec5SDimitry Andric const TargetMachine &TM; 1380b57cec5SDimitry Andric const MipsSubtarget *Subtarget; 1390b57cec5SDimitry Andric const TargetInstrInfo &TII; 1400b57cec5SDimitry Andric const TargetLowering &TLI; 1410b57cec5SDimitry Andric MipsFunctionInfo *MFI; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric // Convenience variables to avoid some queries. 1440b57cec5SDimitry Andric LLVMContext *Context; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric bool fastLowerArguments() override; 1470b57cec5SDimitry Andric bool fastLowerCall(CallLoweringInfo &CLI) override; 1480b57cec5SDimitry Andric bool fastLowerIntrinsicCall(const IntrinsicInst *II) override; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle 1510b57cec5SDimitry Andric // floating point but not reject doing fast-isel in other 1520b57cec5SDimitry Andric // situations 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric private: 1550b57cec5SDimitry Andric // Selection routines. 1560b57cec5SDimitry Andric bool selectLogicalOp(const Instruction *I); 1570b57cec5SDimitry Andric bool selectLoad(const Instruction *I); 1580b57cec5SDimitry Andric bool selectStore(const Instruction *I); 1590b57cec5SDimitry Andric bool selectBranch(const Instruction *I); 1600b57cec5SDimitry Andric bool selectSelect(const Instruction *I); 1610b57cec5SDimitry Andric bool selectCmp(const Instruction *I); 1620b57cec5SDimitry Andric bool selectFPExt(const Instruction *I); 1630b57cec5SDimitry Andric bool selectFPTrunc(const Instruction *I); 1640b57cec5SDimitry Andric bool selectFPToInt(const Instruction *I, bool IsSigned); 1650b57cec5SDimitry Andric bool selectRet(const Instruction *I); 1660b57cec5SDimitry Andric bool selectTrunc(const Instruction *I); 1670b57cec5SDimitry Andric bool selectIntExt(const Instruction *I); 1680b57cec5SDimitry Andric bool selectShift(const Instruction *I); 1690b57cec5SDimitry Andric bool selectDivRem(const Instruction *I, unsigned ISDOpcode); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric // Utility helper routines. 1720b57cec5SDimitry Andric bool isTypeLegal(Type *Ty, MVT &VT); 1730b57cec5SDimitry Andric bool isTypeSupported(Type *Ty, MVT &VT); 1740b57cec5SDimitry Andric bool isLoadTypeLegal(Type *Ty, MVT &VT); 1750b57cec5SDimitry Andric bool computeAddress(const Value *Obj, Address &Addr); 1760b57cec5SDimitry Andric bool computeCallAddress(const Value *V, Address &Addr); 1770b57cec5SDimitry Andric void simplifyAddress(Address &Addr); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // Emit helper routines. 1800b57cec5SDimitry Andric bool emitCmp(unsigned DestReg, const CmpInst *CI); 1810b57cec5SDimitry Andric bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, 1820b57cec5SDimitry Andric unsigned Alignment = 0); 1830b57cec5SDimitry Andric bool emitStore(MVT VT, unsigned SrcReg, Address Addr, 1840b57cec5SDimitry Andric MachineMemOperand *MMO = nullptr); 1850b57cec5SDimitry Andric bool emitStore(MVT VT, unsigned SrcReg, Address &Addr, 1860b57cec5SDimitry Andric unsigned Alignment = 0); 1870b57cec5SDimitry Andric unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt); 1880b57cec5SDimitry Andric bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric bool IsZExt); 1910b57cec5SDimitry Andric bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); 1940b57cec5SDimitry Andric bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1950b57cec5SDimitry Andric unsigned DestReg); 1960b57cec5SDimitry Andric bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, 1970b57cec5SDimitry Andric unsigned DestReg); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS, 2020b57cec5SDimitry Andric const Value *RHS); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric unsigned materializeFP(const ConstantFP *CFP, MVT VT); 2050b57cec5SDimitry Andric unsigned materializeGV(const GlobalValue *GV, MVT VT); 2060b57cec5SDimitry Andric unsigned materializeInt(const Constant *C, MVT VT); 2070b57cec5SDimitry Andric unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); 2080b57cec5SDimitry Andric unsigned materializeExternalCallSym(MCSymbol *Syn); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric MachineInstrBuilder emitInst(unsigned Opc) { 2110b57cec5SDimitry Andric return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) { 2150b57cec5SDimitry Andric return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), 2160b57cec5SDimitry Andric DstReg); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg, 2200b57cec5SDimitry Andric unsigned MemReg, int64_t MemOffset) { 2210b57cec5SDimitry Andric return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset); 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg, 2250b57cec5SDimitry Andric unsigned MemReg, int64_t MemOffset) { 2260b57cec5SDimitry Andric return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric unsigned fastEmitInst_rr(unsigned MachineInstOpcode, 2300b57cec5SDimitry Andric const TargetRegisterClass *RC, 2310b57cec5SDimitry Andric unsigned Op0, bool Op0IsKill, 2320b57cec5SDimitry Andric unsigned Op1, bool Op1IsKill); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // for some reason, this default is not generated by tablegen 2350b57cec5SDimitry Andric // so we explicitly generate it here. 2360b57cec5SDimitry Andric unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC, 2370b57cec5SDimitry Andric unsigned Op0, bool Op0IsKill, uint64_t imm1, 2380b57cec5SDimitry Andric uint64_t imm2, unsigned Op3, bool Op3IsKill) { 2390b57cec5SDimitry Andric return 0; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric // Call handling routines. 2430b57cec5SDimitry Andric private: 2440b57cec5SDimitry Andric CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const; 2450b57cec5SDimitry Andric bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs, 2460b57cec5SDimitry Andric unsigned &NumBytes); 2470b57cec5SDimitry Andric bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes); 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric const MipsABIInfo &getABI() const { 2500b57cec5SDimitry Andric return static_cast<const MipsTargetMachine &>(TM).getABI(); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric public: 2540b57cec5SDimitry Andric // Backend specific FastISel code. 2550b57cec5SDimitry Andric explicit MipsFastISel(FunctionLoweringInfo &funcInfo, 2560b57cec5SDimitry Andric const TargetLibraryInfo *libInfo) 2570b57cec5SDimitry Andric : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()), 2580b57cec5SDimitry Andric Subtarget(&funcInfo.MF->getSubtarget<MipsSubtarget>()), 2590b57cec5SDimitry Andric TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) { 2600b57cec5SDimitry Andric MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); 2610b57cec5SDimitry Andric Context = &funcInfo.Fn->getContext(); 2620b57cec5SDimitry Andric UnsupportedFPMode = Subtarget->isFP64bit() || Subtarget->useSoftFloat(); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric unsigned fastMaterializeAlloca(const AllocaInst *AI) override; 2660b57cec5SDimitry Andric unsigned fastMaterializeConstant(const Constant *C) override; 2670b57cec5SDimitry Andric bool fastSelectInstruction(const Instruction *I) override; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric #include "MipsGenFastISel.inc" 2700b57cec5SDimitry Andric }; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric } // end anonymous namespace 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT, 2750b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, 2760b57cec5SDimitry Andric CCState &State) LLVM_ATTRIBUTE_UNUSED; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, 2790b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo, 2800b57cec5SDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State) { 2810b57cec5SDimitry Andric llvm_unreachable("should not be called"); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, 2850b57cec5SDimitry Andric CCValAssign::LocInfo LocInfo, 2860b57cec5SDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State) { 2870b57cec5SDimitry Andric llvm_unreachable("should not be called"); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric #include "MipsGenCallingConv.inc" 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { 2930b57cec5SDimitry Andric return CC_MipsO32; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric unsigned MipsFastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT, 2970b57cec5SDimitry Andric const Value *LHS, const Value *RHS) { 2980b57cec5SDimitry Andric // Canonicalize immediates to the RHS first. 2990b57cec5SDimitry Andric if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS)) 3000b57cec5SDimitry Andric std::swap(LHS, RHS); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric unsigned Opc; 3030b57cec5SDimitry Andric switch (ISDOpc) { 3040b57cec5SDimitry Andric case ISD::AND: 3050b57cec5SDimitry Andric Opc = Mips::AND; 3060b57cec5SDimitry Andric break; 3070b57cec5SDimitry Andric case ISD::OR: 3080b57cec5SDimitry Andric Opc = Mips::OR; 3090b57cec5SDimitry Andric break; 3100b57cec5SDimitry Andric case ISD::XOR: 3110b57cec5SDimitry Andric Opc = Mips::XOR; 3120b57cec5SDimitry Andric break; 3130b57cec5SDimitry Andric default: 3140b57cec5SDimitry Andric llvm_unreachable("unexpected opcode"); 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric unsigned LHSReg = getRegForValue(LHS); 3180b57cec5SDimitry Andric if (!LHSReg) 3190b57cec5SDimitry Andric return 0; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric unsigned RHSReg; 3220b57cec5SDimitry Andric if (const auto *C = dyn_cast<ConstantInt>(RHS)) 3230b57cec5SDimitry Andric RHSReg = materializeInt(C, MVT::i32); 3240b57cec5SDimitry Andric else 3250b57cec5SDimitry Andric RHSReg = getRegForValue(RHS); 3260b57cec5SDimitry Andric if (!RHSReg) 3270b57cec5SDimitry Andric return 0; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 3300b57cec5SDimitry Andric if (!ResultReg) 3310b57cec5SDimitry Andric return 0; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric emitInst(Opc, ResultReg).addReg(LHSReg).addReg(RHSReg); 3340b57cec5SDimitry Andric return ResultReg; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric unsigned MipsFastISel::fastMaterializeAlloca(const AllocaInst *AI) { 3380b57cec5SDimitry Andric assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i32 && 3390b57cec5SDimitry Andric "Alloca should always return a pointer."); 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric DenseMap<const AllocaInst *, int>::iterator SI = 3420b57cec5SDimitry Andric FuncInfo.StaticAllocaMap.find(AI); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) { 3450b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 3460b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LEA_ADDiu), 3470b57cec5SDimitry Andric ResultReg) 3480b57cec5SDimitry Andric .addFrameIndex(SI->second) 3490b57cec5SDimitry Andric .addImm(0); 3500b57cec5SDimitry Andric return ResultReg; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric return 0; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) { 3570b57cec5SDimitry Andric if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) 3580b57cec5SDimitry Andric return 0; 3590b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass; 3600b57cec5SDimitry Andric const ConstantInt *CI = cast<ConstantInt>(C); 3610b57cec5SDimitry Andric return materialize32BitInt(CI->getZExtValue(), RC); 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric unsigned MipsFastISel::materialize32BitInt(int64_t Imm, 3650b57cec5SDimitry Andric const TargetRegisterClass *RC) { 3660b57cec5SDimitry Andric unsigned ResultReg = createResultReg(RC); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric if (isInt<16>(Imm)) { 3690b57cec5SDimitry Andric unsigned Opc = Mips::ADDiu; 3700b57cec5SDimitry Andric emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm); 3710b57cec5SDimitry Andric return ResultReg; 3720b57cec5SDimitry Andric } else if (isUInt<16>(Imm)) { 3730b57cec5SDimitry Andric emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm); 3740b57cec5SDimitry Andric return ResultReg; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric unsigned Lo = Imm & 0xFFFF; 3770b57cec5SDimitry Andric unsigned Hi = (Imm >> 16) & 0xFFFF; 3780b57cec5SDimitry Andric if (Lo) { 3790b57cec5SDimitry Andric // Both Lo and Hi have nonzero bits. 3800b57cec5SDimitry Andric unsigned TmpReg = createResultReg(RC); 3810b57cec5SDimitry Andric emitInst(Mips::LUi, TmpReg).addImm(Hi); 3820b57cec5SDimitry Andric emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo); 3830b57cec5SDimitry Andric } else { 3840b57cec5SDimitry Andric emitInst(Mips::LUi, ResultReg).addImm(Hi); 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric return ResultReg; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) { 3900b57cec5SDimitry Andric if (UnsupportedFPMode) 3910b57cec5SDimitry Andric return 0; 3920b57cec5SDimitry Andric int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); 3930b57cec5SDimitry Andric if (VT == MVT::f32) { 3940b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::FGR32RegClass; 3950b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 3960b57cec5SDimitry Andric unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass); 3970b57cec5SDimitry Andric emitInst(Mips::MTC1, DestReg).addReg(TempReg); 3980b57cec5SDimitry Andric return DestReg; 3990b57cec5SDimitry Andric } else if (VT == MVT::f64) { 4000b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::AFGR64RegClass; 4010b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 4020b57cec5SDimitry Andric unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass); 4030b57cec5SDimitry Andric unsigned TempReg2 = 4040b57cec5SDimitry Andric materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass); 4050b57cec5SDimitry Andric emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1); 4060b57cec5SDimitry Andric return DestReg; 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric return 0; 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) { 4120b57cec5SDimitry Andric // For now 32-bit only. 4130b57cec5SDimitry Andric if (VT != MVT::i32) 4140b57cec5SDimitry Andric return 0; 4150b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass; 4160b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 4170b57cec5SDimitry Andric const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); 4180b57cec5SDimitry Andric bool IsThreadLocal = GVar && GVar->isThreadLocal(); 4190b57cec5SDimitry Andric // TLS not supported at this time. 4200b57cec5SDimitry Andric if (IsThreadLocal) 4210b57cec5SDimitry Andric return 0; 4220b57cec5SDimitry Andric emitInst(Mips::LW, DestReg) 423*5ffd83dbSDimitry Andric .addReg(MFI->getGlobalBaseReg(*MF)) 4240b57cec5SDimitry Andric .addGlobalAddress(GV, 0, MipsII::MO_GOT); 4250b57cec5SDimitry Andric if ((GV->hasInternalLinkage() || 4260b57cec5SDimitry Andric (GV->hasLocalLinkage() && !isa<Function>(GV)))) { 4270b57cec5SDimitry Andric unsigned TempReg = createResultReg(RC); 4280b57cec5SDimitry Andric emitInst(Mips::ADDiu, TempReg) 4290b57cec5SDimitry Andric .addReg(DestReg) 4300b57cec5SDimitry Andric .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO); 4310b57cec5SDimitry Andric DestReg = TempReg; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric return DestReg; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric unsigned MipsFastISel::materializeExternalCallSym(MCSymbol *Sym) { 4370b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass; 4380b57cec5SDimitry Andric unsigned DestReg = createResultReg(RC); 4390b57cec5SDimitry Andric emitInst(Mips::LW, DestReg) 440*5ffd83dbSDimitry Andric .addReg(MFI->getGlobalBaseReg(*MF)) 4410b57cec5SDimitry Andric .addSym(Sym, MipsII::MO_GOT); 4420b57cec5SDimitry Andric return DestReg; 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric // Materialize a constant into a register, and return the register 4460b57cec5SDimitry Andric // number (or zero if we failed to handle it). 4470b57cec5SDimitry Andric unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { 4480b57cec5SDimitry Andric EVT CEVT = TLI.getValueType(DL, C->getType(), true); 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric // Only handle simple types. 4510b57cec5SDimitry Andric if (!CEVT.isSimple()) 4520b57cec5SDimitry Andric return 0; 4530b57cec5SDimitry Andric MVT VT = CEVT.getSimpleVT(); 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) 4560b57cec5SDimitry Andric return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT); 4570b57cec5SDimitry Andric else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) 4580b57cec5SDimitry Andric return materializeGV(GV, VT); 4590b57cec5SDimitry Andric else if (isa<ConstantInt>(C)) 4600b57cec5SDimitry Andric return materializeInt(C, VT); 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric return 0; 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { 4660b57cec5SDimitry Andric const User *U = nullptr; 4670b57cec5SDimitry Andric unsigned Opcode = Instruction::UserOp1; 4680b57cec5SDimitry Andric if (const Instruction *I = dyn_cast<Instruction>(Obj)) { 4690b57cec5SDimitry Andric // Don't walk into other basic blocks unless the object is an alloca from 4700b57cec5SDimitry Andric // another block, otherwise it may not have a virtual register assigned. 4710b57cec5SDimitry Andric if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) || 4720b57cec5SDimitry Andric FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { 4730b57cec5SDimitry Andric Opcode = I->getOpcode(); 4740b57cec5SDimitry Andric U = I; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) { 4770b57cec5SDimitry Andric Opcode = C->getOpcode(); 4780b57cec5SDimitry Andric U = C; 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric switch (Opcode) { 4810b57cec5SDimitry Andric default: 4820b57cec5SDimitry Andric break; 4830b57cec5SDimitry Andric case Instruction::BitCast: 4840b57cec5SDimitry Andric // Look through bitcasts. 4850b57cec5SDimitry Andric return computeAddress(U->getOperand(0), Addr); 4860b57cec5SDimitry Andric case Instruction::GetElementPtr: { 4870b57cec5SDimitry Andric Address SavedAddr = Addr; 4880b57cec5SDimitry Andric int64_t TmpOffset = Addr.getOffset(); 4890b57cec5SDimitry Andric // Iterate through the GEP folding the constants into offsets where 4900b57cec5SDimitry Andric // we can. 4910b57cec5SDimitry Andric gep_type_iterator GTI = gep_type_begin(U); 4920b57cec5SDimitry Andric for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; 4930b57cec5SDimitry Andric ++i, ++GTI) { 4940b57cec5SDimitry Andric const Value *Op = *i; 4950b57cec5SDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 4960b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 4970b57cec5SDimitry Andric unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); 4980b57cec5SDimitry Andric TmpOffset += SL->getElementOffset(Idx); 4990b57cec5SDimitry Andric } else { 5000b57cec5SDimitry Andric uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); 5010b57cec5SDimitry Andric while (true) { 5020b57cec5SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { 5030b57cec5SDimitry Andric // Constant-offset addressing. 5040b57cec5SDimitry Andric TmpOffset += CI->getSExtValue() * S; 5050b57cec5SDimitry Andric break; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric if (canFoldAddIntoGEP(U, Op)) { 5080b57cec5SDimitry Andric // A compatible add with a constant operand. Fold the constant. 5090b57cec5SDimitry Andric ConstantInt *CI = 5100b57cec5SDimitry Andric cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); 5110b57cec5SDimitry Andric TmpOffset += CI->getSExtValue() * S; 5120b57cec5SDimitry Andric // Iterate on the other operand. 5130b57cec5SDimitry Andric Op = cast<AddOperator>(Op)->getOperand(0); 5140b57cec5SDimitry Andric continue; 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric // Unsupported 5170b57cec5SDimitry Andric goto unsupported_gep; 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric // Try to grab the base operand now. 5220b57cec5SDimitry Andric Addr.setOffset(TmpOffset); 5230b57cec5SDimitry Andric if (computeAddress(U->getOperand(0), Addr)) 5240b57cec5SDimitry Andric return true; 5250b57cec5SDimitry Andric // We failed, restore everything and try the other options. 5260b57cec5SDimitry Andric Addr = SavedAddr; 5270b57cec5SDimitry Andric unsupported_gep: 5280b57cec5SDimitry Andric break; 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric case Instruction::Alloca: { 5310b57cec5SDimitry Andric const AllocaInst *AI = cast<AllocaInst>(Obj); 5320b57cec5SDimitry Andric DenseMap<const AllocaInst *, int>::iterator SI = 5330b57cec5SDimitry Andric FuncInfo.StaticAllocaMap.find(AI); 5340b57cec5SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) { 5350b57cec5SDimitry Andric Addr.setKind(Address::FrameIndexBase); 5360b57cec5SDimitry Andric Addr.setFI(SI->second); 5370b57cec5SDimitry Andric return true; 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric break; 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric Addr.setReg(getRegForValue(Obj)); 5430b57cec5SDimitry Andric return Addr.getReg() != 0; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) { 5470b57cec5SDimitry Andric const User *U = nullptr; 5480b57cec5SDimitry Andric unsigned Opcode = Instruction::UserOp1; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric if (const auto *I = dyn_cast<Instruction>(V)) { 5510b57cec5SDimitry Andric // Check if the value is defined in the same basic block. This information 5520b57cec5SDimitry Andric // is crucial to know whether or not folding an operand is valid. 5530b57cec5SDimitry Andric if (I->getParent() == FuncInfo.MBB->getBasicBlock()) { 5540b57cec5SDimitry Andric Opcode = I->getOpcode(); 5550b57cec5SDimitry Andric U = I; 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric } else if (const auto *C = dyn_cast<ConstantExpr>(V)) { 5580b57cec5SDimitry Andric Opcode = C->getOpcode(); 5590b57cec5SDimitry Andric U = C; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric switch (Opcode) { 5630b57cec5SDimitry Andric default: 5640b57cec5SDimitry Andric break; 5650b57cec5SDimitry Andric case Instruction::BitCast: 5660b57cec5SDimitry Andric // Look past bitcasts if its operand is in the same BB. 5670b57cec5SDimitry Andric return computeCallAddress(U->getOperand(0), Addr); 5680b57cec5SDimitry Andric break; 5690b57cec5SDimitry Andric case Instruction::IntToPtr: 5700b57cec5SDimitry Andric // Look past no-op inttoptrs if its operand is in the same BB. 5710b57cec5SDimitry Andric if (TLI.getValueType(DL, U->getOperand(0)->getType()) == 5720b57cec5SDimitry Andric TLI.getPointerTy(DL)) 5730b57cec5SDimitry Andric return computeCallAddress(U->getOperand(0), Addr); 5740b57cec5SDimitry Andric break; 5750b57cec5SDimitry Andric case Instruction::PtrToInt: 5760b57cec5SDimitry Andric // Look past no-op ptrtoints if its operand is in the same BB. 5770b57cec5SDimitry Andric if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL)) 5780b57cec5SDimitry Andric return computeCallAddress(U->getOperand(0), Addr); 5790b57cec5SDimitry Andric break; 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { 5830b57cec5SDimitry Andric Addr.setGlobalValue(GV); 5840b57cec5SDimitry Andric return true; 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric // If all else fails, try to materialize the value in a register. 5880b57cec5SDimitry Andric if (!Addr.getGlobalValue()) { 5890b57cec5SDimitry Andric Addr.setReg(getRegForValue(V)); 5900b57cec5SDimitry Andric return Addr.getReg() != 0; 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric return false; 5940b57cec5SDimitry Andric } 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { 5970b57cec5SDimitry Andric EVT evt = TLI.getValueType(DL, Ty, true); 5980b57cec5SDimitry Andric // Only handle simple types. 5990b57cec5SDimitry Andric if (evt == MVT::Other || !evt.isSimple()) 6000b57cec5SDimitry Andric return false; 6010b57cec5SDimitry Andric VT = evt.getSimpleVT(); 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric // Handle all legal types, i.e. a register that will directly hold this 6040b57cec5SDimitry Andric // value. 6050b57cec5SDimitry Andric return TLI.isTypeLegal(VT); 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric bool MipsFastISel::isTypeSupported(Type *Ty, MVT &VT) { 6090b57cec5SDimitry Andric if (Ty->isVectorTy()) 6100b57cec5SDimitry Andric return false; 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric if (isTypeLegal(Ty, VT)) 6130b57cec5SDimitry Andric return true; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric // If this is a type than can be sign or zero-extended to a basic operation 6160b57cec5SDimitry Andric // go ahead and accept it now. 6170b57cec5SDimitry Andric if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16) 6180b57cec5SDimitry Andric return true; 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric return false; 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { 6240b57cec5SDimitry Andric if (isTypeLegal(Ty, VT)) 6250b57cec5SDimitry Andric return true; 6260b57cec5SDimitry Andric // We will extend this in a later patch: 6270b57cec5SDimitry Andric // If this is a type than can be sign or zero-extended to a basic operation 6280b57cec5SDimitry Andric // go ahead and accept it now. 6290b57cec5SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 6300b57cec5SDimitry Andric return true; 6310b57cec5SDimitry Andric return false; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // Because of how EmitCmp is called with fast-isel, you can 6350b57cec5SDimitry Andric // end up with redundant "andi" instructions after the sequences emitted below. 6360b57cec5SDimitry Andric // We should try and solve this issue in the future. 6370b57cec5SDimitry Andric // 6380b57cec5SDimitry Andric bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { 6390b57cec5SDimitry Andric const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1); 6400b57cec5SDimitry Andric bool IsUnsigned = CI->isUnsigned(); 6410b57cec5SDimitry Andric unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned); 6420b57cec5SDimitry Andric if (LeftReg == 0) 6430b57cec5SDimitry Andric return false; 6440b57cec5SDimitry Andric unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned); 6450b57cec5SDimitry Andric if (RightReg == 0) 6460b57cec5SDimitry Andric return false; 6470b57cec5SDimitry Andric CmpInst::Predicate P = CI->getPredicate(); 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric switch (P) { 6500b57cec5SDimitry Andric default: 6510b57cec5SDimitry Andric return false; 6520b57cec5SDimitry Andric case CmpInst::ICMP_EQ: { 6530b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 6540b57cec5SDimitry Andric emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); 6550b57cec5SDimitry Andric emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1); 6560b57cec5SDimitry Andric break; 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric case CmpInst::ICMP_NE: { 6590b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 6600b57cec5SDimitry Andric emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); 6610b57cec5SDimitry Andric emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg); 6620b57cec5SDimitry Andric break; 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric case CmpInst::ICMP_UGT: 6650b57cec5SDimitry Andric emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg); 6660b57cec5SDimitry Andric break; 6670b57cec5SDimitry Andric case CmpInst::ICMP_ULT: 6680b57cec5SDimitry Andric emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg); 6690b57cec5SDimitry Andric break; 6700b57cec5SDimitry Andric case CmpInst::ICMP_UGE: { 6710b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 6720b57cec5SDimitry Andric emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg); 6730b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 6740b57cec5SDimitry Andric break; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric case CmpInst::ICMP_ULE: { 6770b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 6780b57cec5SDimitry Andric emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg); 6790b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 6800b57cec5SDimitry Andric break; 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric case CmpInst::ICMP_SGT: 6830b57cec5SDimitry Andric emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg); 6840b57cec5SDimitry Andric break; 6850b57cec5SDimitry Andric case CmpInst::ICMP_SLT: 6860b57cec5SDimitry Andric emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg); 6870b57cec5SDimitry Andric break; 6880b57cec5SDimitry Andric case CmpInst::ICMP_SGE: { 6890b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 6900b57cec5SDimitry Andric emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg); 6910b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 6920b57cec5SDimitry Andric break; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric case CmpInst::ICMP_SLE: { 6950b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 6960b57cec5SDimitry Andric emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg); 6970b57cec5SDimitry Andric emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); 6980b57cec5SDimitry Andric break; 6990b57cec5SDimitry Andric } 7000b57cec5SDimitry Andric case CmpInst::FCMP_OEQ: 7010b57cec5SDimitry Andric case CmpInst::FCMP_UNE: 7020b57cec5SDimitry Andric case CmpInst::FCMP_OLT: 7030b57cec5SDimitry Andric case CmpInst::FCMP_OLE: 7040b57cec5SDimitry Andric case CmpInst::FCMP_OGT: 7050b57cec5SDimitry Andric case CmpInst::FCMP_OGE: { 7060b57cec5SDimitry Andric if (UnsupportedFPMode) 7070b57cec5SDimitry Andric return false; 7080b57cec5SDimitry Andric bool IsFloat = Left->getType()->isFloatTy(); 7090b57cec5SDimitry Andric bool IsDouble = Left->getType()->isDoubleTy(); 7100b57cec5SDimitry Andric if (!IsFloat && !IsDouble) 7110b57cec5SDimitry Andric return false; 7120b57cec5SDimitry Andric unsigned Opc, CondMovOpc; 7130b57cec5SDimitry Andric switch (P) { 7140b57cec5SDimitry Andric case CmpInst::FCMP_OEQ: 7150b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; 7160b57cec5SDimitry Andric CondMovOpc = Mips::MOVT_I; 7170b57cec5SDimitry Andric break; 7180b57cec5SDimitry Andric case CmpInst::FCMP_UNE: 7190b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; 7200b57cec5SDimitry Andric CondMovOpc = Mips::MOVF_I; 7210b57cec5SDimitry Andric break; 7220b57cec5SDimitry Andric case CmpInst::FCMP_OLT: 7230b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32; 7240b57cec5SDimitry Andric CondMovOpc = Mips::MOVT_I; 7250b57cec5SDimitry Andric break; 7260b57cec5SDimitry Andric case CmpInst::FCMP_OLE: 7270b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32; 7280b57cec5SDimitry Andric CondMovOpc = Mips::MOVT_I; 7290b57cec5SDimitry Andric break; 7300b57cec5SDimitry Andric case CmpInst::FCMP_OGT: 7310b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32; 7320b57cec5SDimitry Andric CondMovOpc = Mips::MOVF_I; 7330b57cec5SDimitry Andric break; 7340b57cec5SDimitry Andric case CmpInst::FCMP_OGE: 7350b57cec5SDimitry Andric Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32; 7360b57cec5SDimitry Andric CondMovOpc = Mips::MOVF_I; 7370b57cec5SDimitry Andric break; 7380b57cec5SDimitry Andric default: 7390b57cec5SDimitry Andric llvm_unreachable("Only switching of a subset of CCs."); 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass); 7420b57cec5SDimitry Andric unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass); 7430b57cec5SDimitry Andric emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0); 7440b57cec5SDimitry Andric emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1); 7450b57cec5SDimitry Andric emitInst(Opc).addReg(Mips::FCC0, RegState::Define).addReg(LeftReg) 7460b57cec5SDimitry Andric .addReg(RightReg); 7470b57cec5SDimitry Andric emitInst(CondMovOpc, ResultReg) 7480b57cec5SDimitry Andric .addReg(RegWithOne) 7490b57cec5SDimitry Andric .addReg(Mips::FCC0) 7500b57cec5SDimitry Andric .addReg(RegWithZero); 7510b57cec5SDimitry Andric break; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric return true; 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, 7580b57cec5SDimitry Andric unsigned Alignment) { 7590b57cec5SDimitry Andric // 7600b57cec5SDimitry Andric // more cases will be handled here in following patches. 7610b57cec5SDimitry Andric // 7620b57cec5SDimitry Andric unsigned Opc; 7630b57cec5SDimitry Andric switch (VT.SimpleTy) { 7640b57cec5SDimitry Andric case MVT::i32: 7650b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::GPR32RegClass); 7660b57cec5SDimitry Andric Opc = Mips::LW; 7670b57cec5SDimitry Andric break; 7680b57cec5SDimitry Andric case MVT::i16: 7690b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::GPR32RegClass); 7700b57cec5SDimitry Andric Opc = Mips::LHu; 7710b57cec5SDimitry Andric break; 7720b57cec5SDimitry Andric case MVT::i8: 7730b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::GPR32RegClass); 7740b57cec5SDimitry Andric Opc = Mips::LBu; 7750b57cec5SDimitry Andric break; 7760b57cec5SDimitry Andric case MVT::f32: 7770b57cec5SDimitry Andric if (UnsupportedFPMode) 7780b57cec5SDimitry Andric return false; 7790b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::FGR32RegClass); 7800b57cec5SDimitry Andric Opc = Mips::LWC1; 7810b57cec5SDimitry Andric break; 7820b57cec5SDimitry Andric case MVT::f64: 7830b57cec5SDimitry Andric if (UnsupportedFPMode) 7840b57cec5SDimitry Andric return false; 7850b57cec5SDimitry Andric ResultReg = createResultReg(&Mips::AFGR64RegClass); 7860b57cec5SDimitry Andric Opc = Mips::LDC1; 7870b57cec5SDimitry Andric break; 7880b57cec5SDimitry Andric default: 7890b57cec5SDimitry Andric return false; 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric if (Addr.isRegBase()) { 7920b57cec5SDimitry Andric simplifyAddress(Addr); 7930b57cec5SDimitry Andric emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); 7940b57cec5SDimitry Andric return true; 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric if (Addr.isFIBase()) { 7970b57cec5SDimitry Andric unsigned FI = Addr.getFI(); 7980b57cec5SDimitry Andric int64_t Offset = Addr.getOffset(); 7990b57cec5SDimitry Andric MachineFrameInfo &MFI = MF->getFrameInfo(); 8000b57cec5SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 8010b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, 802*5ffd83dbSDimitry Andric MFI.getObjectSize(FI), Align(4)); 8030b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) 8040b57cec5SDimitry Andric .addFrameIndex(FI) 8050b57cec5SDimitry Andric .addImm(Offset) 8060b57cec5SDimitry Andric .addMemOperand(MMO); 8070b57cec5SDimitry Andric return true; 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric return false; 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, 8130b57cec5SDimitry Andric unsigned Alignment) { 8140b57cec5SDimitry Andric // 8150b57cec5SDimitry Andric // more cases will be handled here in following patches. 8160b57cec5SDimitry Andric // 8170b57cec5SDimitry Andric unsigned Opc; 8180b57cec5SDimitry Andric switch (VT.SimpleTy) { 8190b57cec5SDimitry Andric case MVT::i8: 8200b57cec5SDimitry Andric Opc = Mips::SB; 8210b57cec5SDimitry Andric break; 8220b57cec5SDimitry Andric case MVT::i16: 8230b57cec5SDimitry Andric Opc = Mips::SH; 8240b57cec5SDimitry Andric break; 8250b57cec5SDimitry Andric case MVT::i32: 8260b57cec5SDimitry Andric Opc = Mips::SW; 8270b57cec5SDimitry Andric break; 8280b57cec5SDimitry Andric case MVT::f32: 8290b57cec5SDimitry Andric if (UnsupportedFPMode) 8300b57cec5SDimitry Andric return false; 8310b57cec5SDimitry Andric Opc = Mips::SWC1; 8320b57cec5SDimitry Andric break; 8330b57cec5SDimitry Andric case MVT::f64: 8340b57cec5SDimitry Andric if (UnsupportedFPMode) 8350b57cec5SDimitry Andric return false; 8360b57cec5SDimitry Andric Opc = Mips::SDC1; 8370b57cec5SDimitry Andric break; 8380b57cec5SDimitry Andric default: 8390b57cec5SDimitry Andric return false; 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric if (Addr.isRegBase()) { 8420b57cec5SDimitry Andric simplifyAddress(Addr); 8430b57cec5SDimitry Andric emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); 8440b57cec5SDimitry Andric return true; 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric if (Addr.isFIBase()) { 8470b57cec5SDimitry Andric unsigned FI = Addr.getFI(); 8480b57cec5SDimitry Andric int64_t Offset = Addr.getOffset(); 8490b57cec5SDimitry Andric MachineFrameInfo &MFI = MF->getFrameInfo(); 8500b57cec5SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 8510b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, 852*5ffd83dbSDimitry Andric MFI.getObjectSize(FI), Align(4)); 8530b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) 8540b57cec5SDimitry Andric .addReg(SrcReg) 8550b57cec5SDimitry Andric .addFrameIndex(FI) 8560b57cec5SDimitry Andric .addImm(Offset) 8570b57cec5SDimitry Andric .addMemOperand(MMO); 8580b57cec5SDimitry Andric return true; 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric return false; 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric bool MipsFastISel::selectLogicalOp(const Instruction *I) { 8640b57cec5SDimitry Andric MVT VT; 8650b57cec5SDimitry Andric if (!isTypeSupported(I->getType(), VT)) 8660b57cec5SDimitry Andric return false; 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric unsigned ResultReg; 8690b57cec5SDimitry Andric switch (I->getOpcode()) { 8700b57cec5SDimitry Andric default: 8710b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction."); 8720b57cec5SDimitry Andric case Instruction::And: 8730b57cec5SDimitry Andric ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1)); 8740b57cec5SDimitry Andric break; 8750b57cec5SDimitry Andric case Instruction::Or: 8760b57cec5SDimitry Andric ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1)); 8770b57cec5SDimitry Andric break; 8780b57cec5SDimitry Andric case Instruction::Xor: 8790b57cec5SDimitry Andric ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1)); 8800b57cec5SDimitry Andric break; 8810b57cec5SDimitry Andric } 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric if (!ResultReg) 8840b57cec5SDimitry Andric return false; 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric updateValueMap(I, ResultReg); 8870b57cec5SDimitry Andric return true; 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric bool MipsFastISel::selectLoad(const Instruction *I) { 8910b57cec5SDimitry Andric // Atomic loads need special handling. 8920b57cec5SDimitry Andric if (cast<LoadInst>(I)->isAtomic()) 8930b57cec5SDimitry Andric return false; 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric // Verify we have a legal type before going any further. 8960b57cec5SDimitry Andric MVT VT; 8970b57cec5SDimitry Andric if (!isLoadTypeLegal(I->getType(), VT)) 8980b57cec5SDimitry Andric return false; 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric // See if we can handle this address. 9010b57cec5SDimitry Andric Address Addr; 9020b57cec5SDimitry Andric if (!computeAddress(I->getOperand(0), Addr)) 9030b57cec5SDimitry Andric return false; 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric unsigned ResultReg; 9060b57cec5SDimitry Andric if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment())) 9070b57cec5SDimitry Andric return false; 9080b57cec5SDimitry Andric updateValueMap(I, ResultReg); 9090b57cec5SDimitry Andric return true; 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric bool MipsFastISel::selectStore(const Instruction *I) { 9130b57cec5SDimitry Andric Value *Op0 = I->getOperand(0); 9140b57cec5SDimitry Andric unsigned SrcReg = 0; 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric // Atomic stores need special handling. 9170b57cec5SDimitry Andric if (cast<StoreInst>(I)->isAtomic()) 9180b57cec5SDimitry Andric return false; 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric // Verify we have a legal type before going any further. 9210b57cec5SDimitry Andric MVT VT; 9220b57cec5SDimitry Andric if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT)) 9230b57cec5SDimitry Andric return false; 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric // Get the value to be stored into a register. 9260b57cec5SDimitry Andric SrcReg = getRegForValue(Op0); 9270b57cec5SDimitry Andric if (SrcReg == 0) 9280b57cec5SDimitry Andric return false; 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric // See if we can handle this address. 9310b57cec5SDimitry Andric Address Addr; 9320b57cec5SDimitry Andric if (!computeAddress(I->getOperand(1), Addr)) 9330b57cec5SDimitry Andric return false; 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment())) 9360b57cec5SDimitry Andric return false; 9370b57cec5SDimitry Andric return true; 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric // This can cause a redundant sltiu to be generated. 9410b57cec5SDimitry Andric // FIXME: try and eliminate this in a future patch. 9420b57cec5SDimitry Andric bool MipsFastISel::selectBranch(const Instruction *I) { 9430b57cec5SDimitry Andric const BranchInst *BI = cast<BranchInst>(I); 9440b57cec5SDimitry Andric MachineBasicBlock *BrBB = FuncInfo.MBB; 9450b57cec5SDimitry Andric // 9460b57cec5SDimitry Andric // TBB is the basic block for the case where the comparison is true. 9470b57cec5SDimitry Andric // FBB is the basic block for the case where the comparison is false. 9480b57cec5SDimitry Andric // if (cond) goto TBB 9490b57cec5SDimitry Andric // goto FBB 9500b57cec5SDimitry Andric // TBB: 9510b57cec5SDimitry Andric // 9520b57cec5SDimitry Andric MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; 9530b57cec5SDimitry Andric MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric // Fold the common case of a conditional branch with a comparison 9560b57cec5SDimitry Andric // in the same block. 9570b57cec5SDimitry Andric unsigned ZExtCondReg = 0; 9580b57cec5SDimitry Andric if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { 9590b57cec5SDimitry Andric if (CI->hasOneUse() && CI->getParent() == I->getParent()) { 9600b57cec5SDimitry Andric ZExtCondReg = createResultReg(&Mips::GPR32RegClass); 9610b57cec5SDimitry Andric if (!emitCmp(ZExtCondReg, CI)) 9620b57cec5SDimitry Andric return false; 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric // For the general case, we need to mask with 1. 9670b57cec5SDimitry Andric if (ZExtCondReg == 0) { 9680b57cec5SDimitry Andric unsigned CondReg = getRegForValue(BI->getCondition()); 9690b57cec5SDimitry Andric if (CondReg == 0) 9700b57cec5SDimitry Andric return false; 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true); 9730b57cec5SDimitry Andric if (ZExtCondReg == 0) 9740b57cec5SDimitry Andric return false; 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) 9780b57cec5SDimitry Andric .addReg(ZExtCondReg) 9790b57cec5SDimitry Andric .addMBB(TBB); 9800b57cec5SDimitry Andric finishCondBranch(BI->getParent(), TBB, FBB); 9810b57cec5SDimitry Andric return true; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric bool MipsFastISel::selectCmp(const Instruction *I) { 9850b57cec5SDimitry Andric const CmpInst *CI = cast<CmpInst>(I); 9860b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 9870b57cec5SDimitry Andric if (!emitCmp(ResultReg, CI)) 9880b57cec5SDimitry Andric return false; 9890b57cec5SDimitry Andric updateValueMap(I, ResultReg); 9900b57cec5SDimitry Andric return true; 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric // Attempt to fast-select a floating-point extend instruction. 9940b57cec5SDimitry Andric bool MipsFastISel::selectFPExt(const Instruction *I) { 9950b57cec5SDimitry Andric if (UnsupportedFPMode) 9960b57cec5SDimitry Andric return false; 9970b57cec5SDimitry Andric Value *Src = I->getOperand(0); 9980b57cec5SDimitry Andric EVT SrcVT = TLI.getValueType(DL, Src->getType(), true); 9990b57cec5SDimitry Andric EVT DestVT = TLI.getValueType(DL, I->getType(), true); 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric if (SrcVT != MVT::f32 || DestVT != MVT::f64) 10020b57cec5SDimitry Andric return false; 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric unsigned SrcReg = 10050b57cec5SDimitry Andric getRegForValue(Src); // this must be a 32bit floating point register class 10060b57cec5SDimitry Andric // maybe we should handle this differently 10070b57cec5SDimitry Andric if (!SrcReg) 10080b57cec5SDimitry Andric return false; 10090b57cec5SDimitry Andric 10100b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::AFGR64RegClass); 10110b57cec5SDimitry Andric emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg); 10120b57cec5SDimitry Andric updateValueMap(I, DestReg); 10130b57cec5SDimitry Andric return true; 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric bool MipsFastISel::selectSelect(const Instruction *I) { 10170b57cec5SDimitry Andric assert(isa<SelectInst>(I) && "Expected a select instruction."); 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "selectSelect\n"); 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric MVT VT; 10220b57cec5SDimitry Andric if (!isTypeSupported(I->getType(), VT) || UnsupportedFPMode) { 10230b57cec5SDimitry Andric LLVM_DEBUG( 10240b57cec5SDimitry Andric dbgs() << ".. .. gave up (!isTypeSupported || UnsupportedFPMode)\n"); 10250b57cec5SDimitry Andric return false; 10260b57cec5SDimitry Andric } 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric unsigned CondMovOpc; 10290b57cec5SDimitry Andric const TargetRegisterClass *RC; 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric if (VT.isInteger() && !VT.isVector() && VT.getSizeInBits() <= 32) { 10320b57cec5SDimitry Andric CondMovOpc = Mips::MOVN_I_I; 10330b57cec5SDimitry Andric RC = &Mips::GPR32RegClass; 10340b57cec5SDimitry Andric } else if (VT == MVT::f32) { 10350b57cec5SDimitry Andric CondMovOpc = Mips::MOVN_I_S; 10360b57cec5SDimitry Andric RC = &Mips::FGR32RegClass; 10370b57cec5SDimitry Andric } else if (VT == MVT::f64) { 10380b57cec5SDimitry Andric CondMovOpc = Mips::MOVN_I_D32; 10390b57cec5SDimitry Andric RC = &Mips::AFGR64RegClass; 10400b57cec5SDimitry Andric } else 10410b57cec5SDimitry Andric return false; 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric const SelectInst *SI = cast<SelectInst>(I); 10440b57cec5SDimitry Andric const Value *Cond = SI->getCondition(); 10450b57cec5SDimitry Andric unsigned Src1Reg = getRegForValue(SI->getTrueValue()); 10460b57cec5SDimitry Andric unsigned Src2Reg = getRegForValue(SI->getFalseValue()); 10470b57cec5SDimitry Andric unsigned CondReg = getRegForValue(Cond); 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric if (!Src1Reg || !Src2Reg || !CondReg) 10500b57cec5SDimitry Andric return false; 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric unsigned ZExtCondReg = createResultReg(&Mips::GPR32RegClass); 10530b57cec5SDimitry Andric if (!ZExtCondReg) 10540b57cec5SDimitry Andric return false; 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric if (!emitIntExt(MVT::i1, CondReg, MVT::i32, ZExtCondReg, true)) 10570b57cec5SDimitry Andric return false; 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric unsigned ResultReg = createResultReg(RC); 10600b57cec5SDimitry Andric unsigned TempReg = createResultReg(RC); 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric if (!ResultReg || !TempReg) 10630b57cec5SDimitry Andric return false; 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric emitInst(TargetOpcode::COPY, TempReg).addReg(Src2Reg); 10660b57cec5SDimitry Andric emitInst(CondMovOpc, ResultReg) 10670b57cec5SDimitry Andric .addReg(Src1Reg).addReg(ZExtCondReg).addReg(TempReg); 10680b57cec5SDimitry Andric updateValueMap(I, ResultReg); 10690b57cec5SDimitry Andric return true; 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric // Attempt to fast-select a floating-point truncate instruction. 10730b57cec5SDimitry Andric bool MipsFastISel::selectFPTrunc(const Instruction *I) { 10740b57cec5SDimitry Andric if (UnsupportedFPMode) 10750b57cec5SDimitry Andric return false; 10760b57cec5SDimitry Andric Value *Src = I->getOperand(0); 10770b57cec5SDimitry Andric EVT SrcVT = TLI.getValueType(DL, Src->getType(), true); 10780b57cec5SDimitry Andric EVT DestVT = TLI.getValueType(DL, I->getType(), true); 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric if (SrcVT != MVT::f64 || DestVT != MVT::f32) 10810b57cec5SDimitry Andric return false; 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Src); 10840b57cec5SDimitry Andric if (!SrcReg) 10850b57cec5SDimitry Andric return false; 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::FGR32RegClass); 10880b57cec5SDimitry Andric if (!DestReg) 10890b57cec5SDimitry Andric return false; 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg); 10920b57cec5SDimitry Andric updateValueMap(I, DestReg); 10930b57cec5SDimitry Andric return true; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric // Attempt to fast-select a floating-point-to-integer conversion. 10970b57cec5SDimitry Andric bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) { 10980b57cec5SDimitry Andric if (UnsupportedFPMode) 10990b57cec5SDimitry Andric return false; 11000b57cec5SDimitry Andric MVT DstVT, SrcVT; 11010b57cec5SDimitry Andric if (!IsSigned) 11020b57cec5SDimitry Andric return false; // We don't handle this case yet. There is no native 11030b57cec5SDimitry Andric // instruction for this but it can be synthesized. 11040b57cec5SDimitry Andric Type *DstTy = I->getType(); 11050b57cec5SDimitry Andric if (!isTypeLegal(DstTy, DstVT)) 11060b57cec5SDimitry Andric return false; 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric if (DstVT != MVT::i32) 11090b57cec5SDimitry Andric return false; 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric Value *Src = I->getOperand(0); 11120b57cec5SDimitry Andric Type *SrcTy = Src->getType(); 11130b57cec5SDimitry Andric if (!isTypeLegal(SrcTy, SrcVT)) 11140b57cec5SDimitry Andric return false; 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric if (SrcVT != MVT::f32 && SrcVT != MVT::f64) 11170b57cec5SDimitry Andric return false; 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Src); 11200b57cec5SDimitry Andric if (SrcReg == 0) 11210b57cec5SDimitry Andric return false; 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric // Determine the opcode for the conversion, which takes place 11240b57cec5SDimitry Andric // entirely within FPRs. 11250b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 11260b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::FGR32RegClass); 11270b57cec5SDimitry Andric unsigned Opc = (SrcVT == MVT::f32) ? Mips::TRUNC_W_S : Mips::TRUNC_W_D32; 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric // Generate the convert. 11300b57cec5SDimitry Andric emitInst(Opc, TempReg).addReg(SrcReg); 11310b57cec5SDimitry Andric emitInst(Mips::MFC1, DestReg).addReg(TempReg); 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric updateValueMap(I, DestReg); 11340b57cec5SDimitry Andric return true; 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric 11370b57cec5SDimitry Andric bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, 11380b57cec5SDimitry Andric SmallVectorImpl<MVT> &OutVTs, 11390b57cec5SDimitry Andric unsigned &NumBytes) { 11400b57cec5SDimitry Andric CallingConv::ID CC = CLI.CallConv; 11410b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 11420b57cec5SDimitry Andric CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context); 11430b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC)); 11440b57cec5SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 11450b57cec5SDimitry Andric NumBytes = CCInfo.getNextStackOffset(); 11460b57cec5SDimitry Andric // This is the minimum argument area used for A0-A3. 11470b57cec5SDimitry Andric if (NumBytes < 16) 11480b57cec5SDimitry Andric NumBytes = 16; 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric emitInst(Mips::ADJCALLSTACKDOWN).addImm(16).addImm(0); 11510b57cec5SDimitry Andric // Process the args. 11520b57cec5SDimitry Andric MVT firstMVT; 11530b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 11540b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 11550b57cec5SDimitry Andric const Value *ArgVal = CLI.OutVals[VA.getValNo()]; 11560b57cec5SDimitry Andric MVT ArgVT = OutVTs[VA.getValNo()]; 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric if (i == 0) { 11590b57cec5SDimitry Andric firstMVT = ArgVT; 11600b57cec5SDimitry Andric if (ArgVT == MVT::f32) { 11610b57cec5SDimitry Andric VA.convertToReg(Mips::F12); 11620b57cec5SDimitry Andric } else if (ArgVT == MVT::f64) { 11638bcb0991SDimitry Andric if (Subtarget->isFP64bit()) 11648bcb0991SDimitry Andric VA.convertToReg(Mips::D6_64); 11658bcb0991SDimitry Andric else 11660b57cec5SDimitry Andric VA.convertToReg(Mips::D6); 11670b57cec5SDimitry Andric } 11680b57cec5SDimitry Andric } else if (i == 1) { 11690b57cec5SDimitry Andric if ((firstMVT == MVT::f32) || (firstMVT == MVT::f64)) { 11700b57cec5SDimitry Andric if (ArgVT == MVT::f32) { 11710b57cec5SDimitry Andric VA.convertToReg(Mips::F14); 11720b57cec5SDimitry Andric } else if (ArgVT == MVT::f64) { 11738bcb0991SDimitry Andric if (Subtarget->isFP64bit()) 11748bcb0991SDimitry Andric VA.convertToReg(Mips::D7_64); 11758bcb0991SDimitry Andric else 11760b57cec5SDimitry Andric VA.convertToReg(Mips::D7); 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric } 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32) || (ArgVT == MVT::i16) || 11810b57cec5SDimitry Andric (ArgVT == MVT::i8)) && 11820b57cec5SDimitry Andric VA.isMemLoc()) { 11830b57cec5SDimitry Andric switch (VA.getLocMemOffset()) { 11840b57cec5SDimitry Andric case 0: 11850b57cec5SDimitry Andric VA.convertToReg(Mips::A0); 11860b57cec5SDimitry Andric break; 11870b57cec5SDimitry Andric case 4: 11880b57cec5SDimitry Andric VA.convertToReg(Mips::A1); 11890b57cec5SDimitry Andric break; 11900b57cec5SDimitry Andric case 8: 11910b57cec5SDimitry Andric VA.convertToReg(Mips::A2); 11920b57cec5SDimitry Andric break; 11930b57cec5SDimitry Andric case 12: 11940b57cec5SDimitry Andric VA.convertToReg(Mips::A3); 11950b57cec5SDimitry Andric break; 11960b57cec5SDimitry Andric default: 11970b57cec5SDimitry Andric break; 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric } 12000b57cec5SDimitry Andric unsigned ArgReg = getRegForValue(ArgVal); 12010b57cec5SDimitry Andric if (!ArgReg) 12020b57cec5SDimitry Andric return false; 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric // Handle arg promotion: SExt, ZExt, AExt. 12050b57cec5SDimitry Andric switch (VA.getLocInfo()) { 12060b57cec5SDimitry Andric case CCValAssign::Full: 12070b57cec5SDimitry Andric break; 12080b57cec5SDimitry Andric case CCValAssign::AExt: 12090b57cec5SDimitry Andric case CCValAssign::SExt: { 12100b57cec5SDimitry Andric MVT DestVT = VA.getLocVT(); 12110b57cec5SDimitry Andric MVT SrcVT = ArgVT; 12120b57cec5SDimitry Andric ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false); 12130b57cec5SDimitry Andric if (!ArgReg) 12140b57cec5SDimitry Andric return false; 12150b57cec5SDimitry Andric break; 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric case CCValAssign::ZExt: { 12180b57cec5SDimitry Andric MVT DestVT = VA.getLocVT(); 12190b57cec5SDimitry Andric MVT SrcVT = ArgVT; 12200b57cec5SDimitry Andric ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true); 12210b57cec5SDimitry Andric if (!ArgReg) 12220b57cec5SDimitry Andric return false; 12230b57cec5SDimitry Andric break; 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric default: 12260b57cec5SDimitry Andric llvm_unreachable("Unknown arg promotion!"); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric // Now copy/store arg to correct locations. 12300b57cec5SDimitry Andric if (VA.isRegLoc() && !VA.needsCustom()) { 12310b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 12320b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg); 12330b57cec5SDimitry Andric CLI.OutRegs.push_back(VA.getLocReg()); 12340b57cec5SDimitry Andric } else if (VA.needsCustom()) { 12350b57cec5SDimitry Andric llvm_unreachable("Mips does not use custom args."); 12360b57cec5SDimitry Andric return false; 12370b57cec5SDimitry Andric } else { 12380b57cec5SDimitry Andric // 12390b57cec5SDimitry Andric // FIXME: This path will currently return false. It was copied 12400b57cec5SDimitry Andric // from the AArch64 port and should be essentially fine for Mips too. 12410b57cec5SDimitry Andric // The work to finish up this path will be done in a follow-on patch. 12420b57cec5SDimitry Andric // 12430b57cec5SDimitry Andric assert(VA.isMemLoc() && "Assuming store on stack."); 12440b57cec5SDimitry Andric // Don't emit stores for undef values. 12450b57cec5SDimitry Andric if (isa<UndefValue>(ArgVal)) 12460b57cec5SDimitry Andric continue; 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric // Need to store on the stack. 12490b57cec5SDimitry Andric // FIXME: This alignment is incorrect but this path is disabled 12500b57cec5SDimitry Andric // for now (will return false). We need to determine the right alignment 12510b57cec5SDimitry Andric // based on the normal alignment for the underlying machine type. 12520b57cec5SDimitry Andric // 12530b57cec5SDimitry Andric unsigned ArgSize = alignTo(ArgVT.getSizeInBits(), 4); 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric unsigned BEAlign = 0; 12560b57cec5SDimitry Andric if (ArgSize < 8 && !Subtarget->isLittle()) 12570b57cec5SDimitry Andric BEAlign = 8 - ArgSize; 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric Address Addr; 12600b57cec5SDimitry Andric Addr.setKind(Address::RegBase); 12610b57cec5SDimitry Andric Addr.setReg(Mips::SP); 12620b57cec5SDimitry Andric Addr.setOffset(VA.getLocMemOffset() + BEAlign); 12630b57cec5SDimitry Andric 1264*5ffd83dbSDimitry Andric Align Alignment = DL.getABITypeAlign(ArgVal->getType()); 12650b57cec5SDimitry Andric MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand( 12660b57cec5SDimitry Andric MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()), 12670b57cec5SDimitry Andric MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment); 12680b57cec5SDimitry Andric (void)(MMO); 12690b57cec5SDimitry Andric // if (!emitStore(ArgVT, ArgReg, Addr, MMO)) 12700b57cec5SDimitry Andric return false; // can't store on the stack yet. 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric } 12730b57cec5SDimitry Andric 12740b57cec5SDimitry Andric return true; 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, 12780b57cec5SDimitry Andric unsigned NumBytes) { 12790b57cec5SDimitry Andric CallingConv::ID CC = CLI.CallConv; 12800b57cec5SDimitry Andric emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0); 12810b57cec5SDimitry Andric if (RetVT != MVT::isVoid) { 12820b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 12830b57cec5SDimitry Andric MipsCCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context); 12840b57cec5SDimitry Andric 12850b57cec5SDimitry Andric CCInfo.AnalyzeCallResult(CLI.Ins, RetCC_Mips, CLI.RetTy, 12860b57cec5SDimitry Andric CLI.Symbol ? CLI.Symbol->getName().data() 12870b57cec5SDimitry Andric : nullptr); 12880b57cec5SDimitry Andric 12890b57cec5SDimitry Andric // Only handle a single return value. 12900b57cec5SDimitry Andric if (RVLocs.size() != 1) 12910b57cec5SDimitry Andric return false; 12920b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg. 12930b57cec5SDimitry Andric MVT CopyVT = RVLocs[0].getValVT(); 12940b57cec5SDimitry Andric // Special handling for extended integers. 12950b57cec5SDimitry Andric if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16) 12960b57cec5SDimitry Andric CopyVT = MVT::i32; 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT)); 12990b57cec5SDimitry Andric if (!ResultReg) 13000b57cec5SDimitry Andric return false; 13010b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 13020b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), 13030b57cec5SDimitry Andric ResultReg).addReg(RVLocs[0].getLocReg()); 13040b57cec5SDimitry Andric CLI.InRegs.push_back(RVLocs[0].getLocReg()); 13050b57cec5SDimitry Andric 13060b57cec5SDimitry Andric CLI.ResultReg = ResultReg; 13070b57cec5SDimitry Andric CLI.NumResultRegs = 1; 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric return true; 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric bool MipsFastISel::fastLowerArguments() { 13130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "fastLowerArguments\n"); 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric if (!FuncInfo.CanLowerReturn) { 13160b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (!CanLowerReturn)\n"); 13170b57cec5SDimitry Andric return false; 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric const Function *F = FuncInfo.Fn; 13210b57cec5SDimitry Andric if (F->isVarArg()) { 13220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (varargs)\n"); 13230b57cec5SDimitry Andric return false; 13240b57cec5SDimitry Andric } 13250b57cec5SDimitry Andric 13260b57cec5SDimitry Andric CallingConv::ID CC = F->getCallingConv(); 13270b57cec5SDimitry Andric if (CC != CallingConv::C) { 13280b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (calling convention is not C)\n"); 13290b57cec5SDimitry Andric return false; 13300b57cec5SDimitry Andric } 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric std::array<MCPhysReg, 4> GPR32ArgRegs = {{Mips::A0, Mips::A1, Mips::A2, 13330b57cec5SDimitry Andric Mips::A3}}; 13340b57cec5SDimitry Andric std::array<MCPhysReg, 2> FGR32ArgRegs = {{Mips::F12, Mips::F14}}; 13350b57cec5SDimitry Andric std::array<MCPhysReg, 2> AFGR64ArgRegs = {{Mips::D6, Mips::D7}}; 13360b57cec5SDimitry Andric auto NextGPR32 = GPR32ArgRegs.begin(); 13370b57cec5SDimitry Andric auto NextFGR32 = FGR32ArgRegs.begin(); 13380b57cec5SDimitry Andric auto NextAFGR64 = AFGR64ArgRegs.begin(); 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric struct AllocatedReg { 13410b57cec5SDimitry Andric const TargetRegisterClass *RC; 13420b57cec5SDimitry Andric unsigned Reg; 13430b57cec5SDimitry Andric AllocatedReg(const TargetRegisterClass *RC, unsigned Reg) 13440b57cec5SDimitry Andric : RC(RC), Reg(Reg) {} 13450b57cec5SDimitry Andric }; 13460b57cec5SDimitry Andric 13470b57cec5SDimitry Andric // Only handle simple cases. i.e. All arguments are directly mapped to 13480b57cec5SDimitry Andric // registers of the appropriate type. 13490b57cec5SDimitry Andric SmallVector<AllocatedReg, 4> Allocation; 13500b57cec5SDimitry Andric for (const auto &FormalArg : F->args()) { 13510b57cec5SDimitry Andric if (FormalArg.hasAttribute(Attribute::InReg) || 13520b57cec5SDimitry Andric FormalArg.hasAttribute(Attribute::StructRet) || 13530b57cec5SDimitry Andric FormalArg.hasAttribute(Attribute::ByVal)) { 13540b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n"); 13550b57cec5SDimitry Andric return false; 13560b57cec5SDimitry Andric } 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric Type *ArgTy = FormalArg.getType(); 13590b57cec5SDimitry Andric if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy()) { 13600b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. gave up (struct, array, or vector)\n"); 13610b57cec5SDimitry Andric return false; 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric EVT ArgVT = TLI.getValueType(DL, ArgTy); 13650b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": " 13660b57cec5SDimitry Andric << ArgVT.getEVTString() << "\n"); 13670b57cec5SDimitry Andric if (!ArgVT.isSimple()) { 13680b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (not a simple type)\n"); 13690b57cec5SDimitry Andric return false; 13700b57cec5SDimitry Andric } 13710b57cec5SDimitry Andric 13720b57cec5SDimitry Andric switch (ArgVT.getSimpleVT().SimpleTy) { 13730b57cec5SDimitry Andric case MVT::i1: 13740b57cec5SDimitry Andric case MVT::i8: 13750b57cec5SDimitry Andric case MVT::i16: 13760b57cec5SDimitry Andric if (!FormalArg.hasAttribute(Attribute::SExt) && 13770b57cec5SDimitry Andric !FormalArg.hasAttribute(Attribute::ZExt)) { 13780b57cec5SDimitry Andric // It must be any extend, this shouldn't happen for clang-generated IR 13790b57cec5SDimitry Andric // so just fall back on SelectionDAG. 13800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n"); 13810b57cec5SDimitry Andric return false; 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric if (NextGPR32 == GPR32ArgRegs.end()) { 13850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); 13860b57cec5SDimitry Andric return false; 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); 13900b57cec5SDimitry Andric Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andric // Allocating any GPR32 prohibits further use of floating point arguments. 13930b57cec5SDimitry Andric NextFGR32 = FGR32ArgRegs.end(); 13940b57cec5SDimitry Andric NextAFGR64 = AFGR64ArgRegs.end(); 13950b57cec5SDimitry Andric break; 13960b57cec5SDimitry Andric 13970b57cec5SDimitry Andric case MVT::i32: 13980b57cec5SDimitry Andric if (FormalArg.hasAttribute(Attribute::ZExt)) { 13990b57cec5SDimitry Andric // The O32 ABI does not permit a zero-extended i32. 14000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n"); 14010b57cec5SDimitry Andric return false; 14020b57cec5SDimitry Andric } 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric if (NextGPR32 == GPR32ArgRegs.end()) { 14050b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); 14060b57cec5SDimitry Andric return false; 14070b57cec5SDimitry Andric } 14080b57cec5SDimitry Andric 14090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); 14100b57cec5SDimitry Andric Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric // Allocating any GPR32 prohibits further use of floating point arguments. 14130b57cec5SDimitry Andric NextFGR32 = FGR32ArgRegs.end(); 14140b57cec5SDimitry Andric NextAFGR64 = AFGR64ArgRegs.end(); 14150b57cec5SDimitry Andric break; 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric case MVT::f32: 14180b57cec5SDimitry Andric if (UnsupportedFPMode) { 14190b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); 14200b57cec5SDimitry Andric return false; 14210b57cec5SDimitry Andric } 14220b57cec5SDimitry Andric if (NextFGR32 == FGR32ArgRegs.end()) { 14230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n"); 14240b57cec5SDimitry Andric return false; 14250b57cec5SDimitry Andric } 14260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n"); 14270b57cec5SDimitry Andric Allocation.emplace_back(&Mips::FGR32RegClass, *NextFGR32++); 14280b57cec5SDimitry Andric // Allocating an FGR32 also allocates the super-register AFGR64, and 14290b57cec5SDimitry Andric // ABI rules require us to skip the corresponding GPR32. 14300b57cec5SDimitry Andric if (NextGPR32 != GPR32ArgRegs.end()) 14310b57cec5SDimitry Andric NextGPR32++; 14320b57cec5SDimitry Andric if (NextAFGR64 != AFGR64ArgRegs.end()) 14330b57cec5SDimitry Andric NextAFGR64++; 14340b57cec5SDimitry Andric break; 14350b57cec5SDimitry Andric 14360b57cec5SDimitry Andric case MVT::f64: 14370b57cec5SDimitry Andric if (UnsupportedFPMode) { 14380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); 14390b57cec5SDimitry Andric return false; 14400b57cec5SDimitry Andric } 14410b57cec5SDimitry Andric if (NextAFGR64 == AFGR64ArgRegs.end()) { 14420b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n"); 14430b57cec5SDimitry Andric return false; 14440b57cec5SDimitry Andric } 14450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n"); 14460b57cec5SDimitry Andric Allocation.emplace_back(&Mips::AFGR64RegClass, *NextAFGR64++); 14470b57cec5SDimitry Andric // Allocating an FGR32 also allocates the super-register AFGR64, and 14480b57cec5SDimitry Andric // ABI rules require us to skip the corresponding GPR32 pair. 14490b57cec5SDimitry Andric if (NextGPR32 != GPR32ArgRegs.end()) 14500b57cec5SDimitry Andric NextGPR32++; 14510b57cec5SDimitry Andric if (NextGPR32 != GPR32ArgRegs.end()) 14520b57cec5SDimitry Andric NextGPR32++; 14530b57cec5SDimitry Andric if (NextFGR32 != FGR32ArgRegs.end()) 14540b57cec5SDimitry Andric NextFGR32++; 14550b57cec5SDimitry Andric break; 14560b57cec5SDimitry Andric 14570b57cec5SDimitry Andric default: 14580b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (unknown type)\n"); 14590b57cec5SDimitry Andric return false; 14600b57cec5SDimitry Andric } 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric for (const auto &FormalArg : F->args()) { 14640b57cec5SDimitry Andric unsigned ArgNo = FormalArg.getArgNo(); 14650b57cec5SDimitry Andric unsigned SrcReg = Allocation[ArgNo].Reg; 14660b57cec5SDimitry Andric unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, Allocation[ArgNo].RC); 14670b57cec5SDimitry Andric // FIXME: Unfortunately it's necessary to emit a copy from the livein copy. 14680b57cec5SDimitry Andric // Without this, EmitLiveInCopies may eliminate the livein if its only 14690b57cec5SDimitry Andric // use is a bitcast (which isn't turned into an instruction). 14700b57cec5SDimitry Andric unsigned ResultReg = createResultReg(Allocation[ArgNo].RC); 14710b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 14720b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), ResultReg) 14730b57cec5SDimitry Andric .addReg(DstReg, getKillRegState(true)); 14740b57cec5SDimitry Andric updateValueMap(&FormalArg, ResultReg); 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric 14770b57cec5SDimitry Andric // Calculate the size of the incoming arguments area. 14780b57cec5SDimitry Andric // We currently reject all the cases where this would be non-zero. 14790b57cec5SDimitry Andric unsigned IncomingArgSizeInBytes = 0; 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric // Account for the reserved argument area on ABI's that have one (O32). 14820b57cec5SDimitry Andric // It seems strange to do this on the caller side but it's necessary in 14830b57cec5SDimitry Andric // SelectionDAG's implementation. 14840b57cec5SDimitry Andric IncomingArgSizeInBytes = std::min(getABI().GetCalleeAllocdArgSizeInBytes(CC), 14850b57cec5SDimitry Andric IncomingArgSizeInBytes); 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andric MF->getInfo<MipsFunctionInfo>()->setFormalArgInfo(IncomingArgSizeInBytes, 14880b57cec5SDimitry Andric false); 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric return true; 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { 14940b57cec5SDimitry Andric CallingConv::ID CC = CLI.CallConv; 14950b57cec5SDimitry Andric bool IsTailCall = CLI.IsTailCall; 14960b57cec5SDimitry Andric bool IsVarArg = CLI.IsVarArg; 14970b57cec5SDimitry Andric const Value *Callee = CLI.Callee; 14980b57cec5SDimitry Andric MCSymbol *Symbol = CLI.Symbol; 14990b57cec5SDimitry Andric 15000b57cec5SDimitry Andric // Do not handle FastCC. 15010b57cec5SDimitry Andric if (CC == CallingConv::Fast) 15020b57cec5SDimitry Andric return false; 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric // Allow SelectionDAG isel to handle tail calls. 15050b57cec5SDimitry Andric if (IsTailCall) 15060b57cec5SDimitry Andric return false; 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric // Let SDISel handle vararg functions. 15090b57cec5SDimitry Andric if (IsVarArg) 15100b57cec5SDimitry Andric return false; 15110b57cec5SDimitry Andric 15120b57cec5SDimitry Andric // FIXME: Only handle *simple* calls for now. 15130b57cec5SDimitry Andric MVT RetVT; 15140b57cec5SDimitry Andric if (CLI.RetTy->isVoidTy()) 15150b57cec5SDimitry Andric RetVT = MVT::isVoid; 15160b57cec5SDimitry Andric else if (!isTypeSupported(CLI.RetTy, RetVT)) 15170b57cec5SDimitry Andric return false; 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric for (auto Flag : CLI.OutFlags) 15200b57cec5SDimitry Andric if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal()) 15210b57cec5SDimitry Andric return false; 15220b57cec5SDimitry Andric 15230b57cec5SDimitry Andric // Set up the argument vectors. 15240b57cec5SDimitry Andric SmallVector<MVT, 16> OutVTs; 15250b57cec5SDimitry Andric OutVTs.reserve(CLI.OutVals.size()); 15260b57cec5SDimitry Andric 15270b57cec5SDimitry Andric for (auto *Val : CLI.OutVals) { 15280b57cec5SDimitry Andric MVT VT; 15290b57cec5SDimitry Andric if (!isTypeLegal(Val->getType(), VT) && 15300b57cec5SDimitry Andric !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)) 15310b57cec5SDimitry Andric return false; 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric // We don't handle vector parameters yet. 15340b57cec5SDimitry Andric if (VT.isVector() || VT.getSizeInBits() > 64) 15350b57cec5SDimitry Andric return false; 15360b57cec5SDimitry Andric 15370b57cec5SDimitry Andric OutVTs.push_back(VT); 15380b57cec5SDimitry Andric } 15390b57cec5SDimitry Andric 15400b57cec5SDimitry Andric Address Addr; 15410b57cec5SDimitry Andric if (!computeCallAddress(Callee, Addr)) 15420b57cec5SDimitry Andric return false; 15430b57cec5SDimitry Andric 15440b57cec5SDimitry Andric // Handle the arguments now that we've gotten them. 15450b57cec5SDimitry Andric unsigned NumBytes; 15460b57cec5SDimitry Andric if (!processCallArgs(CLI, OutVTs, NumBytes)) 15470b57cec5SDimitry Andric return false; 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andric if (!Addr.getGlobalValue()) 15500b57cec5SDimitry Andric return false; 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric // Issue the call. 15530b57cec5SDimitry Andric unsigned DestAddress; 15540b57cec5SDimitry Andric if (Symbol) 15550b57cec5SDimitry Andric DestAddress = materializeExternalCallSym(Symbol); 15560b57cec5SDimitry Andric else 15570b57cec5SDimitry Andric DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); 15580b57cec5SDimitry Andric emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress); 15590b57cec5SDimitry Andric MachineInstrBuilder MIB = 15600b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR), 15610b57cec5SDimitry Andric Mips::RA).addReg(Mips::T9); 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric // Add implicit physical register uses to the call. 15640b57cec5SDimitry Andric for (auto Reg : CLI.OutRegs) 15650b57cec5SDimitry Andric MIB.addReg(Reg, RegState::Implicit); 15660b57cec5SDimitry Andric 15670b57cec5SDimitry Andric // Add a register mask with the call-preserved registers. 15680b57cec5SDimitry Andric // Proper defs for return values will be added by setPhysRegsDeadExcept(). 15690b57cec5SDimitry Andric MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC)); 15700b57cec5SDimitry Andric 15710b57cec5SDimitry Andric CLI.Call = MIB; 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric if (EmitJalrReloc && !Subtarget->inMips16Mode()) { 15740b57cec5SDimitry Andric // Attach callee address to the instruction, let asm printer emit 15750b57cec5SDimitry Andric // .reloc R_MIPS_JALR. 15760b57cec5SDimitry Andric if (Symbol) 15770b57cec5SDimitry Andric MIB.addSym(Symbol, MipsII::MO_JALR); 15780b57cec5SDimitry Andric else 15790b57cec5SDimitry Andric MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol( 15800b57cec5SDimitry Andric Addr.getGlobalValue()->getName()), MipsII::MO_JALR); 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric 15830b57cec5SDimitry Andric // Finish off the call including any return values. 15840b57cec5SDimitry Andric return finishCall(CLI, RetVT, NumBytes); 15850b57cec5SDimitry Andric } 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) { 15880b57cec5SDimitry Andric switch (II->getIntrinsicID()) { 15890b57cec5SDimitry Andric default: 15900b57cec5SDimitry Andric return false; 15910b57cec5SDimitry Andric case Intrinsic::bswap: { 15920b57cec5SDimitry Andric Type *RetTy = II->getCalledFunction()->getReturnType(); 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric MVT VT; 15950b57cec5SDimitry Andric if (!isTypeSupported(RetTy, VT)) 15960b57cec5SDimitry Andric return false; 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(II->getOperand(0)); 15990b57cec5SDimitry Andric if (SrcReg == 0) 16000b57cec5SDimitry Andric return false; 16010b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 16020b57cec5SDimitry Andric if (DestReg == 0) 16030b57cec5SDimitry Andric return false; 16040b57cec5SDimitry Andric if (VT == MVT::i16) { 16050b57cec5SDimitry Andric if (Subtarget->hasMips32r2()) { 16060b57cec5SDimitry Andric emitInst(Mips::WSBH, DestReg).addReg(SrcReg); 16070b57cec5SDimitry Andric updateValueMap(II, DestReg); 16080b57cec5SDimitry Andric return true; 16090b57cec5SDimitry Andric } else { 16100b57cec5SDimitry Andric unsigned TempReg[3]; 16110b57cec5SDimitry Andric for (int i = 0; i < 3; i++) { 16120b57cec5SDimitry Andric TempReg[i] = createResultReg(&Mips::GPR32RegClass); 16130b57cec5SDimitry Andric if (TempReg[i] == 0) 16140b57cec5SDimitry Andric return false; 16150b57cec5SDimitry Andric } 16160b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8); 16170b57cec5SDimitry Andric emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8); 16180b57cec5SDimitry Andric emitInst(Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]); 16190b57cec5SDimitry Andric emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF); 16200b57cec5SDimitry Andric updateValueMap(II, DestReg); 16210b57cec5SDimitry Andric return true; 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric } else if (VT == MVT::i32) { 16240b57cec5SDimitry Andric if (Subtarget->hasMips32r2()) { 16250b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 16260b57cec5SDimitry Andric emitInst(Mips::WSBH, TempReg).addReg(SrcReg); 16270b57cec5SDimitry Andric emitInst(Mips::ROTR, DestReg).addReg(TempReg).addImm(16); 16280b57cec5SDimitry Andric updateValueMap(II, DestReg); 16290b57cec5SDimitry Andric return true; 16300b57cec5SDimitry Andric } else { 16310b57cec5SDimitry Andric unsigned TempReg[8]; 16320b57cec5SDimitry Andric for (int i = 0; i < 8; i++) { 16330b57cec5SDimitry Andric TempReg[i] = createResultReg(&Mips::GPR32RegClass); 16340b57cec5SDimitry Andric if (TempReg[i] == 0) 16350b57cec5SDimitry Andric return false; 16360b57cec5SDimitry Andric } 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric emitInst(Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8); 16390b57cec5SDimitry Andric emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24); 16400b57cec5SDimitry Andric emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00); 16410b57cec5SDimitry Andric emitInst(Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]); 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric emitInst(Mips::ANDi, TempReg[4]).addReg(SrcReg).addImm(0xFF00); 16440b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg[5]).addReg(TempReg[4]).addImm(8); 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg[6]).addReg(SrcReg).addImm(24); 16470b57cec5SDimitry Andric emitInst(Mips::OR, TempReg[7]).addReg(TempReg[3]).addReg(TempReg[5]); 16480b57cec5SDimitry Andric emitInst(Mips::OR, DestReg).addReg(TempReg[6]).addReg(TempReg[7]); 16490b57cec5SDimitry Andric updateValueMap(II, DestReg); 16500b57cec5SDimitry Andric return true; 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric return false; 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric case Intrinsic::memcpy: 16560b57cec5SDimitry Andric case Intrinsic::memmove: { 16570b57cec5SDimitry Andric const auto *MTI = cast<MemTransferInst>(II); 16580b57cec5SDimitry Andric // Don't handle volatile. 16590b57cec5SDimitry Andric if (MTI->isVolatile()) 16600b57cec5SDimitry Andric return false; 16610b57cec5SDimitry Andric if (!MTI->getLength()->getType()->isIntegerTy(32)) 16620b57cec5SDimitry Andric return false; 16630b57cec5SDimitry Andric const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove"; 16640b57cec5SDimitry Andric return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 1); 16650b57cec5SDimitry Andric } 16660b57cec5SDimitry Andric case Intrinsic::memset: { 16670b57cec5SDimitry Andric const MemSetInst *MSI = cast<MemSetInst>(II); 16680b57cec5SDimitry Andric // Don't handle volatile. 16690b57cec5SDimitry Andric if (MSI->isVolatile()) 16700b57cec5SDimitry Andric return false; 16710b57cec5SDimitry Andric if (!MSI->getLength()->getType()->isIntegerTy(32)) 16720b57cec5SDimitry Andric return false; 16730b57cec5SDimitry Andric return lowerCallTo(II, "memset", II->getNumArgOperands() - 1); 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric } 16760b57cec5SDimitry Andric return false; 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric bool MipsFastISel::selectRet(const Instruction *I) { 16800b57cec5SDimitry Andric const Function &F = *I->getParent()->getParent(); 16810b57cec5SDimitry Andric const ReturnInst *Ret = cast<ReturnInst>(I); 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "selectRet\n"); 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric if (!FuncInfo.CanLowerReturn) 16860b57cec5SDimitry Andric return false; 16870b57cec5SDimitry Andric 16880b57cec5SDimitry Andric // Build a list of return value registers. 16890b57cec5SDimitry Andric SmallVector<unsigned, 4> RetRegs; 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric if (Ret->getNumOperands() > 0) { 16920b57cec5SDimitry Andric CallingConv::ID CC = F.getCallingConv(); 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric // Do not handle FastCC. 16950b57cec5SDimitry Andric if (CC == CallingConv::Fast) 16960b57cec5SDimitry Andric return false; 16970b57cec5SDimitry Andric 16980b57cec5SDimitry Andric SmallVector<ISD::OutputArg, 4> Outs; 16990b57cec5SDimitry Andric GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL); 17000b57cec5SDimitry Andric 17010b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand. 17020b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ValLocs; 17030b57cec5SDimitry Andric MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, 17040b57cec5SDimitry Andric I->getContext()); 17050b57cec5SDimitry Andric CCAssignFn *RetCC = RetCC_Mips; 17060b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC); 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric // Only handle a single return value for now. 17090b57cec5SDimitry Andric if (ValLocs.size() != 1) 17100b57cec5SDimitry Andric return false; 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric CCValAssign &VA = ValLocs[0]; 17130b57cec5SDimitry Andric const Value *RV = Ret->getOperand(0); 17140b57cec5SDimitry Andric 17150b57cec5SDimitry Andric // Don't bother handling odd stuff for now. 17160b57cec5SDimitry Andric if ((VA.getLocInfo() != CCValAssign::Full) && 17170b57cec5SDimitry Andric (VA.getLocInfo() != CCValAssign::BCvt)) 17180b57cec5SDimitry Andric return false; 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric // Only handle register returns for now. 17210b57cec5SDimitry Andric if (!VA.isRegLoc()) 17220b57cec5SDimitry Andric return false; 17230b57cec5SDimitry Andric 17240b57cec5SDimitry Andric unsigned Reg = getRegForValue(RV); 17250b57cec5SDimitry Andric if (Reg == 0) 17260b57cec5SDimitry Andric return false; 17270b57cec5SDimitry Andric 17280b57cec5SDimitry Andric unsigned SrcReg = Reg + VA.getValNo(); 17298bcb0991SDimitry Andric Register DestReg = VA.getLocReg(); 17300b57cec5SDimitry Andric // Avoid a cross-class copy. This is very unlikely. 17310b57cec5SDimitry Andric if (!MRI.getRegClass(SrcReg)->contains(DestReg)) 17320b57cec5SDimitry Andric return false; 17330b57cec5SDimitry Andric 17340b57cec5SDimitry Andric EVT RVEVT = TLI.getValueType(DL, RV->getType()); 17350b57cec5SDimitry Andric if (!RVEVT.isSimple()) 17360b57cec5SDimitry Andric return false; 17370b57cec5SDimitry Andric 17380b57cec5SDimitry Andric if (RVEVT.isVector()) 17390b57cec5SDimitry Andric return false; 17400b57cec5SDimitry Andric 17410b57cec5SDimitry Andric MVT RVVT = RVEVT.getSimpleVT(); 17420b57cec5SDimitry Andric if (RVVT == MVT::f128) 17430b57cec5SDimitry Andric return false; 17440b57cec5SDimitry Andric 17450b57cec5SDimitry Andric // Do not handle FGR64 returns for now. 17460b57cec5SDimitry Andric if (RVVT == MVT::f64 && UnsupportedFPMode) { 17470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode\n"); 17480b57cec5SDimitry Andric return false; 17490b57cec5SDimitry Andric } 17500b57cec5SDimitry Andric 17510b57cec5SDimitry Andric MVT DestVT = VA.getValVT(); 17520b57cec5SDimitry Andric // Special handling for extended integers. 17530b57cec5SDimitry Andric if (RVVT != DestVT) { 17540b57cec5SDimitry Andric if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16) 17550b57cec5SDimitry Andric return false; 17560b57cec5SDimitry Andric 17570b57cec5SDimitry Andric if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) { 17580b57cec5SDimitry Andric bool IsZExt = Outs[0].Flags.isZExt(); 17590b57cec5SDimitry Andric SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt); 17600b57cec5SDimitry Andric if (SrcReg == 0) 17610b57cec5SDimitry Andric return false; 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric 17650b57cec5SDimitry Andric // Make the copy. 17660b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, 17670b57cec5SDimitry Andric TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg); 17680b57cec5SDimitry Andric 17690b57cec5SDimitry Andric // Add register to return instruction. 17700b57cec5SDimitry Andric RetRegs.push_back(VA.getLocReg()); 17710b57cec5SDimitry Andric } 17720b57cec5SDimitry Andric MachineInstrBuilder MIB = emitInst(Mips::RetRA); 17730b57cec5SDimitry Andric for (unsigned i = 0, e = RetRegs.size(); i != e; ++i) 17740b57cec5SDimitry Andric MIB.addReg(RetRegs[i], RegState::Implicit); 17750b57cec5SDimitry Andric return true; 17760b57cec5SDimitry Andric } 17770b57cec5SDimitry Andric 17780b57cec5SDimitry Andric bool MipsFastISel::selectTrunc(const Instruction *I) { 17790b57cec5SDimitry Andric // The high bits for a type smaller than the register size are assumed to be 17800b57cec5SDimitry Andric // undefined. 17810b57cec5SDimitry Andric Value *Op = I->getOperand(0); 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric EVT SrcVT, DestVT; 17840b57cec5SDimitry Andric SrcVT = TLI.getValueType(DL, Op->getType(), true); 17850b57cec5SDimitry Andric DestVT = TLI.getValueType(DL, I->getType(), true); 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8) 17880b57cec5SDimitry Andric return false; 17890b57cec5SDimitry Andric if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1) 17900b57cec5SDimitry Andric return false; 17910b57cec5SDimitry Andric 17920b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Op); 17930b57cec5SDimitry Andric if (!SrcReg) 17940b57cec5SDimitry Andric return false; 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric // Because the high bits are undefined, a truncate doesn't generate 17970b57cec5SDimitry Andric // any code. 17980b57cec5SDimitry Andric updateValueMap(I, SrcReg); 17990b57cec5SDimitry Andric return true; 18000b57cec5SDimitry Andric } 18010b57cec5SDimitry Andric 18020b57cec5SDimitry Andric bool MipsFastISel::selectIntExt(const Instruction *I) { 18030b57cec5SDimitry Andric Type *DestTy = I->getType(); 18040b57cec5SDimitry Andric Value *Src = I->getOperand(0); 18050b57cec5SDimitry Andric Type *SrcTy = Src->getType(); 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric bool isZExt = isa<ZExtInst>(I); 18080b57cec5SDimitry Andric unsigned SrcReg = getRegForValue(Src); 18090b57cec5SDimitry Andric if (!SrcReg) 18100b57cec5SDimitry Andric return false; 18110b57cec5SDimitry Andric 18120b57cec5SDimitry Andric EVT SrcEVT, DestEVT; 18130b57cec5SDimitry Andric SrcEVT = TLI.getValueType(DL, SrcTy, true); 18140b57cec5SDimitry Andric DestEVT = TLI.getValueType(DL, DestTy, true); 18150b57cec5SDimitry Andric if (!SrcEVT.isSimple()) 18160b57cec5SDimitry Andric return false; 18170b57cec5SDimitry Andric if (!DestEVT.isSimple()) 18180b57cec5SDimitry Andric return false; 18190b57cec5SDimitry Andric 18200b57cec5SDimitry Andric MVT SrcVT = SrcEVT.getSimpleVT(); 18210b57cec5SDimitry Andric MVT DestVT = DestEVT.getSimpleVT(); 18220b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt)) 18250b57cec5SDimitry Andric return false; 18260b57cec5SDimitry Andric updateValueMap(I, ResultReg); 18270b57cec5SDimitry Andric return true; 18280b57cec5SDimitry Andric } 18290b57cec5SDimitry Andric 18300b57cec5SDimitry Andric bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, 18310b57cec5SDimitry Andric unsigned DestReg) { 18320b57cec5SDimitry Andric unsigned ShiftAmt; 18330b57cec5SDimitry Andric switch (SrcVT.SimpleTy) { 18340b57cec5SDimitry Andric default: 18350b57cec5SDimitry Andric return false; 18360b57cec5SDimitry Andric case MVT::i8: 18370b57cec5SDimitry Andric ShiftAmt = 24; 18380b57cec5SDimitry Andric break; 18390b57cec5SDimitry Andric case MVT::i16: 18400b57cec5SDimitry Andric ShiftAmt = 16; 18410b57cec5SDimitry Andric break; 18420b57cec5SDimitry Andric } 18430b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 18440b57cec5SDimitry Andric emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt); 18450b57cec5SDimitry Andric emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt); 18460b57cec5SDimitry Andric return true; 18470b57cec5SDimitry Andric } 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, 18500b57cec5SDimitry Andric unsigned DestReg) { 18510b57cec5SDimitry Andric switch (SrcVT.SimpleTy) { 18520b57cec5SDimitry Andric default: 18530b57cec5SDimitry Andric return false; 18540b57cec5SDimitry Andric case MVT::i8: 18550b57cec5SDimitry Andric emitInst(Mips::SEB, DestReg).addReg(SrcReg); 18560b57cec5SDimitry Andric break; 18570b57cec5SDimitry Andric case MVT::i16: 18580b57cec5SDimitry Andric emitInst(Mips::SEH, DestReg).addReg(SrcReg); 18590b57cec5SDimitry Andric break; 18600b57cec5SDimitry Andric } 18610b57cec5SDimitry Andric return true; 18620b57cec5SDimitry Andric } 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 18650b57cec5SDimitry Andric unsigned DestReg) { 18660b57cec5SDimitry Andric if ((DestVT != MVT::i32) && (DestVT != MVT::i16)) 18670b57cec5SDimitry Andric return false; 18680b57cec5SDimitry Andric if (Subtarget->hasMips32r2()) 18690b57cec5SDimitry Andric return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg); 18700b57cec5SDimitry Andric return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg); 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric 18730b57cec5SDimitry Andric bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 18740b57cec5SDimitry Andric unsigned DestReg) { 18750b57cec5SDimitry Andric int64_t Imm; 18760b57cec5SDimitry Andric 18770b57cec5SDimitry Andric switch (SrcVT.SimpleTy) { 18780b57cec5SDimitry Andric default: 18790b57cec5SDimitry Andric return false; 18800b57cec5SDimitry Andric case MVT::i1: 18810b57cec5SDimitry Andric Imm = 1; 18820b57cec5SDimitry Andric break; 18830b57cec5SDimitry Andric case MVT::i8: 18840b57cec5SDimitry Andric Imm = 0xff; 18850b57cec5SDimitry Andric break; 18860b57cec5SDimitry Andric case MVT::i16: 18870b57cec5SDimitry Andric Imm = 0xffff; 18880b57cec5SDimitry Andric break; 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(Imm); 18920b57cec5SDimitry Andric return true; 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 18960b57cec5SDimitry Andric unsigned DestReg, bool IsZExt) { 18970b57cec5SDimitry Andric // FastISel does not have plumbing to deal with extensions where the SrcVT or 18980b57cec5SDimitry Andric // DestVT are odd things, so test to make sure that they are both types we can 18990b57cec5SDimitry Andric // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise 19000b57cec5SDimitry Andric // bail out to SelectionDAG. 19010b57cec5SDimitry Andric if (((DestVT != MVT::i8) && (DestVT != MVT::i16) && (DestVT != MVT::i32)) || 19020b57cec5SDimitry Andric ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) && (SrcVT != MVT::i16))) 19030b57cec5SDimitry Andric return false; 19040b57cec5SDimitry Andric if (IsZExt) 19050b57cec5SDimitry Andric return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg); 19060b57cec5SDimitry Andric return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg); 19070b57cec5SDimitry Andric } 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, 19100b57cec5SDimitry Andric bool isZExt) { 19110b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 19120b57cec5SDimitry Andric bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); 19130b57cec5SDimitry Andric return Success ? DestReg : 0; 19140b57cec5SDimitry Andric } 19150b57cec5SDimitry Andric 19160b57cec5SDimitry Andric bool MipsFastISel::selectDivRem(const Instruction *I, unsigned ISDOpcode) { 19170b57cec5SDimitry Andric EVT DestEVT = TLI.getValueType(DL, I->getType(), true); 19180b57cec5SDimitry Andric if (!DestEVT.isSimple()) 19190b57cec5SDimitry Andric return false; 19200b57cec5SDimitry Andric 19210b57cec5SDimitry Andric MVT DestVT = DestEVT.getSimpleVT(); 19220b57cec5SDimitry Andric if (DestVT != MVT::i32) 19230b57cec5SDimitry Andric return false; 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric unsigned DivOpc; 19260b57cec5SDimitry Andric switch (ISDOpcode) { 19270b57cec5SDimitry Andric default: 19280b57cec5SDimitry Andric return false; 19290b57cec5SDimitry Andric case ISD::SDIV: 19300b57cec5SDimitry Andric case ISD::SREM: 19310b57cec5SDimitry Andric DivOpc = Mips::SDIV; 19320b57cec5SDimitry Andric break; 19330b57cec5SDimitry Andric case ISD::UDIV: 19340b57cec5SDimitry Andric case ISD::UREM: 19350b57cec5SDimitry Andric DivOpc = Mips::UDIV; 19360b57cec5SDimitry Andric break; 19370b57cec5SDimitry Andric } 19380b57cec5SDimitry Andric 19390b57cec5SDimitry Andric unsigned Src0Reg = getRegForValue(I->getOperand(0)); 19400b57cec5SDimitry Andric unsigned Src1Reg = getRegForValue(I->getOperand(1)); 19410b57cec5SDimitry Andric if (!Src0Reg || !Src1Reg) 19420b57cec5SDimitry Andric return false; 19430b57cec5SDimitry Andric 19440b57cec5SDimitry Andric emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg); 19450b57cec5SDimitry Andric emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7); 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 19480b57cec5SDimitry Andric if (!ResultReg) 19490b57cec5SDimitry Andric return false; 19500b57cec5SDimitry Andric 19510b57cec5SDimitry Andric unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM) 19520b57cec5SDimitry Andric ? Mips::MFHI 19530b57cec5SDimitry Andric : Mips::MFLO; 19540b57cec5SDimitry Andric emitInst(MFOpc, ResultReg); 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric updateValueMap(I, ResultReg); 19570b57cec5SDimitry Andric return true; 19580b57cec5SDimitry Andric } 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric bool MipsFastISel::selectShift(const Instruction *I) { 19610b57cec5SDimitry Andric MVT RetVT; 19620b57cec5SDimitry Andric 19630b57cec5SDimitry Andric if (!isTypeSupported(I->getType(), RetVT)) 19640b57cec5SDimitry Andric return false; 19650b57cec5SDimitry Andric 19660b57cec5SDimitry Andric unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); 19670b57cec5SDimitry Andric if (!ResultReg) 19680b57cec5SDimitry Andric return false; 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric unsigned Opcode = I->getOpcode(); 19710b57cec5SDimitry Andric const Value *Op0 = I->getOperand(0); 19720b57cec5SDimitry Andric unsigned Op0Reg = getRegForValue(Op0); 19730b57cec5SDimitry Andric if (!Op0Reg) 19740b57cec5SDimitry Andric return false; 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric // If AShr or LShr, then we need to make sure the operand0 is sign extended. 19770b57cec5SDimitry Andric if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) { 19780b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 19790b57cec5SDimitry Andric if (!TempReg) 19800b57cec5SDimitry Andric return false; 19810b57cec5SDimitry Andric 19820b57cec5SDimitry Andric MVT Op0MVT = TLI.getValueType(DL, Op0->getType(), true).getSimpleVT(); 19830b57cec5SDimitry Andric bool IsZExt = Opcode == Instruction::LShr; 19840b57cec5SDimitry Andric if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt)) 19850b57cec5SDimitry Andric return false; 19860b57cec5SDimitry Andric 19870b57cec5SDimitry Andric Op0Reg = TempReg; 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) { 19910b57cec5SDimitry Andric uint64_t ShiftVal = C->getZExtValue(); 19920b57cec5SDimitry Andric 19930b57cec5SDimitry Andric switch (Opcode) { 19940b57cec5SDimitry Andric default: 19950b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction."); 19960b57cec5SDimitry Andric case Instruction::Shl: 19970b57cec5SDimitry Andric Opcode = Mips::SLL; 19980b57cec5SDimitry Andric break; 19990b57cec5SDimitry Andric case Instruction::AShr: 20000b57cec5SDimitry Andric Opcode = Mips::SRA; 20010b57cec5SDimitry Andric break; 20020b57cec5SDimitry Andric case Instruction::LShr: 20030b57cec5SDimitry Andric Opcode = Mips::SRL; 20040b57cec5SDimitry Andric break; 20050b57cec5SDimitry Andric } 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal); 20080b57cec5SDimitry Andric updateValueMap(I, ResultReg); 20090b57cec5SDimitry Andric return true; 20100b57cec5SDimitry Andric } 20110b57cec5SDimitry Andric 20120b57cec5SDimitry Andric unsigned Op1Reg = getRegForValue(I->getOperand(1)); 20130b57cec5SDimitry Andric if (!Op1Reg) 20140b57cec5SDimitry Andric return false; 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric switch (Opcode) { 20170b57cec5SDimitry Andric default: 20180b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction."); 20190b57cec5SDimitry Andric case Instruction::Shl: 20200b57cec5SDimitry Andric Opcode = Mips::SLLV; 20210b57cec5SDimitry Andric break; 20220b57cec5SDimitry Andric case Instruction::AShr: 20230b57cec5SDimitry Andric Opcode = Mips::SRAV; 20240b57cec5SDimitry Andric break; 20250b57cec5SDimitry Andric case Instruction::LShr: 20260b57cec5SDimitry Andric Opcode = Mips::SRLV; 20270b57cec5SDimitry Andric break; 20280b57cec5SDimitry Andric } 20290b57cec5SDimitry Andric 20300b57cec5SDimitry Andric emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg); 20310b57cec5SDimitry Andric updateValueMap(I, ResultReg); 20320b57cec5SDimitry Andric return true; 20330b57cec5SDimitry Andric } 20340b57cec5SDimitry Andric 20350b57cec5SDimitry Andric bool MipsFastISel::fastSelectInstruction(const Instruction *I) { 20360b57cec5SDimitry Andric switch (I->getOpcode()) { 20370b57cec5SDimitry Andric default: 20380b57cec5SDimitry Andric break; 20390b57cec5SDimitry Andric case Instruction::Load: 20400b57cec5SDimitry Andric return selectLoad(I); 20410b57cec5SDimitry Andric case Instruction::Store: 20420b57cec5SDimitry Andric return selectStore(I); 20430b57cec5SDimitry Andric case Instruction::SDiv: 20440b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::SDIV)) 20450b57cec5SDimitry Andric return selectDivRem(I, ISD::SDIV); 20460b57cec5SDimitry Andric return true; 20470b57cec5SDimitry Andric case Instruction::UDiv: 20480b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::UDIV)) 20490b57cec5SDimitry Andric return selectDivRem(I, ISD::UDIV); 20500b57cec5SDimitry Andric return true; 20510b57cec5SDimitry Andric case Instruction::SRem: 20520b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::SREM)) 20530b57cec5SDimitry Andric return selectDivRem(I, ISD::SREM); 20540b57cec5SDimitry Andric return true; 20550b57cec5SDimitry Andric case Instruction::URem: 20560b57cec5SDimitry Andric if (!selectBinaryOp(I, ISD::UREM)) 20570b57cec5SDimitry Andric return selectDivRem(I, ISD::UREM); 20580b57cec5SDimitry Andric return true; 20590b57cec5SDimitry Andric case Instruction::Shl: 20600b57cec5SDimitry Andric case Instruction::LShr: 20610b57cec5SDimitry Andric case Instruction::AShr: 20620b57cec5SDimitry Andric return selectShift(I); 20630b57cec5SDimitry Andric case Instruction::And: 20640b57cec5SDimitry Andric case Instruction::Or: 20650b57cec5SDimitry Andric case Instruction::Xor: 20660b57cec5SDimitry Andric return selectLogicalOp(I); 20670b57cec5SDimitry Andric case Instruction::Br: 20680b57cec5SDimitry Andric return selectBranch(I); 20690b57cec5SDimitry Andric case Instruction::Ret: 20700b57cec5SDimitry Andric return selectRet(I); 20710b57cec5SDimitry Andric case Instruction::Trunc: 20720b57cec5SDimitry Andric return selectTrunc(I); 20730b57cec5SDimitry Andric case Instruction::ZExt: 20740b57cec5SDimitry Andric case Instruction::SExt: 20750b57cec5SDimitry Andric return selectIntExt(I); 20760b57cec5SDimitry Andric case Instruction::FPTrunc: 20770b57cec5SDimitry Andric return selectFPTrunc(I); 20780b57cec5SDimitry Andric case Instruction::FPExt: 20790b57cec5SDimitry Andric return selectFPExt(I); 20800b57cec5SDimitry Andric case Instruction::FPToSI: 20810b57cec5SDimitry Andric return selectFPToInt(I, /*isSigned*/ true); 20820b57cec5SDimitry Andric case Instruction::FPToUI: 20830b57cec5SDimitry Andric return selectFPToInt(I, /*isSigned*/ false); 20840b57cec5SDimitry Andric case Instruction::ICmp: 20850b57cec5SDimitry Andric case Instruction::FCmp: 20860b57cec5SDimitry Andric return selectCmp(I); 20870b57cec5SDimitry Andric case Instruction::Select: 20880b57cec5SDimitry Andric return selectSelect(I); 20890b57cec5SDimitry Andric } 20900b57cec5SDimitry Andric return false; 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, 20940b57cec5SDimitry Andric bool IsUnsigned) { 20950b57cec5SDimitry Andric unsigned VReg = getRegForValue(V); 20960b57cec5SDimitry Andric if (VReg == 0) 20970b57cec5SDimitry Andric return 0; 20980b57cec5SDimitry Andric MVT VMVT = TLI.getValueType(DL, V->getType(), true).getSimpleVT(); 20990b57cec5SDimitry Andric 21000b57cec5SDimitry Andric if (VMVT == MVT::i1) 21010b57cec5SDimitry Andric return 0; 21020b57cec5SDimitry Andric 21030b57cec5SDimitry Andric if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) { 21040b57cec5SDimitry Andric unsigned TempReg = createResultReg(&Mips::GPR32RegClass); 21050b57cec5SDimitry Andric if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned)) 21060b57cec5SDimitry Andric return 0; 21070b57cec5SDimitry Andric VReg = TempReg; 21080b57cec5SDimitry Andric } 21090b57cec5SDimitry Andric return VReg; 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric 21120b57cec5SDimitry Andric void MipsFastISel::simplifyAddress(Address &Addr) { 21130b57cec5SDimitry Andric if (!isInt<16>(Addr.getOffset())) { 21140b57cec5SDimitry Andric unsigned TempReg = 21150b57cec5SDimitry Andric materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass); 21160b57cec5SDimitry Andric unsigned DestReg = createResultReg(&Mips::GPR32RegClass); 21170b57cec5SDimitry Andric emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg()); 21180b57cec5SDimitry Andric Addr.setReg(DestReg); 21190b57cec5SDimitry Andric Addr.setOffset(0); 21200b57cec5SDimitry Andric } 21210b57cec5SDimitry Andric } 21220b57cec5SDimitry Andric 21230b57cec5SDimitry Andric unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode, 21240b57cec5SDimitry Andric const TargetRegisterClass *RC, 21250b57cec5SDimitry Andric unsigned Op0, bool Op0IsKill, 21260b57cec5SDimitry Andric unsigned Op1, bool Op1IsKill) { 21270b57cec5SDimitry Andric // We treat the MUL instruction in a special way because it clobbers 21280b57cec5SDimitry Andric // the HI0 & LO0 registers. The TableGen definition of this instruction can 21290b57cec5SDimitry Andric // mark these registers only as implicitly defined. As a result, the 21300b57cec5SDimitry Andric // register allocator runs out of registers when this instruction is 21310b57cec5SDimitry Andric // followed by another instruction that defines the same registers too. 21320b57cec5SDimitry Andric // We can fix this by explicitly marking those registers as dead. 21330b57cec5SDimitry Andric if (MachineInstOpcode == Mips::MUL) { 21340b57cec5SDimitry Andric unsigned ResultReg = createResultReg(RC); 21350b57cec5SDimitry Andric const MCInstrDesc &II = TII.get(MachineInstOpcode); 21360b57cec5SDimitry Andric Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs()); 21370b57cec5SDimitry Andric Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1); 21380b57cec5SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg) 21390b57cec5SDimitry Andric .addReg(Op0, getKillRegState(Op0IsKill)) 21400b57cec5SDimitry Andric .addReg(Op1, getKillRegState(Op1IsKill)) 21410b57cec5SDimitry Andric .addReg(Mips::HI0, RegState::ImplicitDefine | RegState::Dead) 21420b57cec5SDimitry Andric .addReg(Mips::LO0, RegState::ImplicitDefine | RegState::Dead); 21430b57cec5SDimitry Andric return ResultReg; 21440b57cec5SDimitry Andric } 21450b57cec5SDimitry Andric 21460b57cec5SDimitry Andric return FastISel::fastEmitInst_rr(MachineInstOpcode, RC, Op0, Op0IsKill, Op1, 21470b57cec5SDimitry Andric Op1IsKill); 21480b57cec5SDimitry Andric } 21490b57cec5SDimitry Andric 21500b57cec5SDimitry Andric namespace llvm { 21510b57cec5SDimitry Andric 21520b57cec5SDimitry Andric FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, 21530b57cec5SDimitry Andric const TargetLibraryInfo *libInfo) { 21540b57cec5SDimitry Andric return new MipsFastISel(funcInfo, libInfo); 21550b57cec5SDimitry Andric } 21560b57cec5SDimitry Andric 21570b57cec5SDimitry Andric } // end namespace llvm 2158