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