179220eaeSEugene Zelenko //===- MipsFastISel.cpp - Mips FastISel implementation --------------------===//
2a9e5154dSVasileios Kalintiris //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9e5154dSVasileios Kalintiris //
7a9e5154dSVasileios Kalintiris //===----------------------------------------------------------------------===//
8a9e5154dSVasileios Kalintiris ///
9a9e5154dSVasileios Kalintiris /// \file
105f8f34e4SAdrian Prantl /// This file defines the MIPS-specific support for the FastISel class.
11a9e5154dSVasileios Kalintiris /// Some of the target-specific code is generated by tablegen in the file
12a9e5154dSVasileios Kalintiris /// MipsGenFastISel.inc, which is #included here.
13a9e5154dSVasileios Kalintiris ///
14a9e5154dSVasileios Kalintiris //===----------------------------------------------------------------------===//
15720c5ca4SReed Kotler 
16dde94e4cSEugene Zelenko #include "MCTargetDesc/MipsABIInfo.h"
17dde94e4cSEugene Zelenko #include "MCTargetDesc/MipsBaseInfo.h"
18d9903888SChandler Carruth #include "MipsCCState.h"
19d9903888SChandler Carruth #include "MipsISelLowering.h"
206bda14b3SChandler Carruth #include "MipsInstrInfo.h"
21d9903888SChandler Carruth #include "MipsMachineFunction.h"
22d9903888SChandler Carruth #include "MipsSubtarget.h"
23d9903888SChandler Carruth #include "MipsTargetMachine.h"
24dde94e4cSEugene Zelenko #include "llvm/ADT/APInt.h"
25dde94e4cSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
26dde94e4cSEugene Zelenko #include "llvm/ADT/DenseMap.h"
27dde94e4cSEugene Zelenko #include "llvm/ADT/SmallVector.h"
2862d4215bSChandler Carruth #include "llvm/Analysis/TargetLibraryInfo.h"
29dde94e4cSEugene Zelenko #include "llvm/CodeGen/CallingConvLower.h"
30720c5ca4SReed Kotler #include "llvm/CodeGen/FastISel.h"
31aa150ed7SReed Kotler #include "llvm/CodeGen/FunctionLoweringInfo.h"
32dde94e4cSEugene Zelenko #include "llvm/CodeGen/ISDOpcodes.h"
33dde94e4cSEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h"
34dde94e4cSEugene Zelenko #include "llvm/CodeGen/MachineFrameInfo.h"
3567077b30SReed Kotler #include "llvm/CodeGen/MachineInstrBuilder.h"
36dde94e4cSEugene Zelenko #include "llvm/CodeGen/MachineMemOperand.h"
37aa150ed7SReed Kotler #include "llvm/CodeGen/MachineRegisterInfo.h"
383f833edcSDavid Blaikie #include "llvm/CodeGen/TargetInstrInfo.h"
39b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetLowering.h"
402fa14362SCraig Topper #include "llvm/CodeGen/ValueTypes.h"
41dde94e4cSEugene Zelenko #include "llvm/IR/Attributes.h"
42dde94e4cSEugene Zelenko #include "llvm/IR/CallingConv.h"
43dde94e4cSEugene Zelenko #include "llvm/IR/Constant.h"
44dde94e4cSEugene Zelenko #include "llvm/IR/Constants.h"
45dde94e4cSEugene Zelenko #include "llvm/IR/DataLayout.h"
46dde94e4cSEugene Zelenko #include "llvm/IR/Function.h"
47457343dcSDavid Blaikie #include "llvm/IR/GetElementPtrTypeIterator.h"
48dde94e4cSEugene Zelenko #include "llvm/IR/GlobalValue.h"
49bab3f23dSReed Kotler #include "llvm/IR/GlobalVariable.h"
50dde94e4cSEugene Zelenko #include "llvm/IR/InstrTypes.h"
51dde94e4cSEugene Zelenko #include "llvm/IR/Instruction.h"
52dde94e4cSEugene Zelenko #include "llvm/IR/Instructions.h"
53dde94e4cSEugene Zelenko #include "llvm/IR/IntrinsicInst.h"
54dde94e4cSEugene Zelenko #include "llvm/IR/Operator.h"
55dde94e4cSEugene Zelenko #include "llvm/IR/Type.h"
56dde94e4cSEugene Zelenko #include "llvm/IR/User.h"
57dde94e4cSEugene Zelenko #include "llvm/IR/Value.h"
583daf8bc9SVladimir Stefanovic #include "llvm/MC/MCContext.h"
59dde94e4cSEugene Zelenko #include "llvm/MC/MCInstrDesc.h"
60dde94e4cSEugene Zelenko #include "llvm/MC/MCRegisterInfo.h"
61ce4c2bc1SRafael Espindola #include "llvm/MC/MCSymbol.h"
62dde94e4cSEugene Zelenko #include "llvm/Support/Casting.h"
63dde94e4cSEugene Zelenko #include "llvm/Support/Compiler.h"
64cbaca42aSDaniel Sanders #include "llvm/Support/Debug.h"
65dde94e4cSEugene Zelenko #include "llvm/Support/ErrorHandling.h"
6613e77db2SDavid Blaikie #include "llvm/Support/MachineValueType.h"
67dde94e4cSEugene Zelenko #include "llvm/Support/MathExtras.h"
68dde94e4cSEugene Zelenko #include "llvm/Support/raw_ostream.h"
69dde94e4cSEugene Zelenko #include <algorithm>
709d68b9eaSManoj Gupta #include <array>
71dde94e4cSEugene Zelenko #include <cassert>
72dde94e4cSEugene Zelenko #include <cstdint>
73cbaca42aSDaniel Sanders 
74cbaca42aSDaniel Sanders #define DEBUG_TYPE "mips-fastisel"
75720c5ca4SReed Kotler 
76720c5ca4SReed Kotler using namespace llvm;
77720c5ca4SReed Kotler 
783daf8bc9SVladimir Stefanovic extern cl::opt<bool> EmitJalrReloc;
793daf8bc9SVladimir Stefanovic 
80720c5ca4SReed Kotler namespace {
81720c5ca4SReed Kotler 
82a562b46dSReed Kotler class MipsFastISel final : public FastISel {
83bab3f23dSReed Kotler 
84a562b46dSReed Kotler   // All possible address modes.
85a562b46dSReed Kotler   class Address {
86a562b46dSReed Kotler   public:
8779220eaeSEugene Zelenko     using BaseKind = enum { RegBase, FrameIndexBase };
88a562b46dSReed Kotler 
89a562b46dSReed Kotler   private:
90dde94e4cSEugene Zelenko     BaseKind Kind = RegBase;
91bab3f23dSReed Kotler     union {
92bab3f23dSReed Kotler       unsigned Reg;
93bab3f23dSReed Kotler       int FI;
94bab3f23dSReed Kotler     } Base;
95bab3f23dSReed Kotler 
96dde94e4cSEugene Zelenko     int64_t Offset = 0;
97bab3f23dSReed Kotler 
98dde94e4cSEugene Zelenko     const GlobalValue *GV = nullptr;
99bab3f23dSReed Kotler 
100a562b46dSReed Kotler   public:
101a562b46dSReed Kotler     // Innocuous defaults for our address.
Address()102dde94e4cSEugene Zelenko     Address() { Base.Reg = 0; }
103dde94e4cSEugene Zelenko 
setKind(BaseKind K)104a562b46dSReed Kotler     void setKind(BaseKind K) { Kind = K; }
getKind() const105a562b46dSReed Kotler     BaseKind getKind() const { return Kind; }
isRegBase() const106a562b46dSReed Kotler     bool isRegBase() const { return Kind == RegBase; }
isFIBase() const1075fb7d8b5SReed Kotler     bool isFIBase() const { return Kind == FrameIndexBase; }
108dde94e4cSEugene Zelenko 
setReg(unsigned Reg)109a562b46dSReed Kotler     void setReg(unsigned Reg) {
110a562b46dSReed Kotler       assert(isRegBase() && "Invalid base register access!");
111a562b46dSReed Kotler       Base.Reg = Reg;
112a562b46dSReed Kotler     }
113dde94e4cSEugene Zelenko 
getReg() const114a562b46dSReed Kotler     unsigned getReg() const {
115a562b46dSReed Kotler       assert(isRegBase() && "Invalid base register access!");
116a562b46dSReed Kotler       return Base.Reg;
117a562b46dSReed Kotler     }
118dde94e4cSEugene Zelenko 
setFI(unsigned FI)1195fb7d8b5SReed Kotler     void setFI(unsigned FI) {
1205fb7d8b5SReed Kotler       assert(isFIBase() && "Invalid base frame index access!");
1215fb7d8b5SReed Kotler       Base.FI = FI;
1225fb7d8b5SReed Kotler     }
123dde94e4cSEugene Zelenko 
getFI() const1245fb7d8b5SReed Kotler     unsigned getFI() const {
1255fb7d8b5SReed Kotler       assert(isFIBase() && "Invalid base frame index access!");
1265fb7d8b5SReed Kotler       return Base.FI;
1275fb7d8b5SReed Kotler     }
1285fb7d8b5SReed Kotler 
setOffset(int64_t Offset_)129a562b46dSReed Kotler     void setOffset(int64_t Offset_) { Offset = Offset_; }
getOffset() const130a562b46dSReed Kotler     int64_t getOffset() const { return Offset; }
setGlobalValue(const GlobalValue * G)131a562b46dSReed Kotler     void setGlobalValue(const GlobalValue *G) { GV = G; }
getGlobalValue()132a562b46dSReed Kotler     const GlobalValue *getGlobalValue() { return GV; }
133a562b46dSReed Kotler   };
134720c5ca4SReed Kotler 
13567077b30SReed Kotler   /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
13667077b30SReed Kotler   /// make the right decision when generating code for different targets.
13767077b30SReed Kotler   const TargetMachine &TM;
13896e72c6aSEric Christopher   const MipsSubtarget *Subtarget;
13967077b30SReed Kotler   const TargetInstrInfo &TII;
14067077b30SReed Kotler   const TargetLowering &TLI;
14167077b30SReed Kotler   MipsFunctionInfo *MFI;
14267077b30SReed Kotler 
14367077b30SReed Kotler   // Convenience variables to avoid some queries.
14467077b30SReed Kotler   LLVMContext *Context;
14567077b30SReed Kotler 
146cbaca42aSDaniel Sanders   bool fastLowerArguments() override;
147d5c4196cSReed Kotler   bool fastLowerCall(CallLoweringInfo &CLI) override;
148bdb91b31SVasileios Kalintiris   bool fastLowerIntrinsicCall(const IntrinsicInst *II) override;
149d5c4196cSReed Kotler 
150a562b46dSReed Kotler   bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle
151a562b46dSReed Kotler   // floating point but not reject doing fast-isel in other
152a562b46dSReed Kotler   // situations
153a562b46dSReed Kotler 
154a562b46dSReed Kotler private:
155a562b46dSReed Kotler   // Selection routines.
15607d3a2f6SReed Kotler   bool selectLogicalOp(const Instruction *I);
157a562b46dSReed Kotler   bool selectLoad(const Instruction *I);
158a562b46dSReed Kotler   bool selectStore(const Instruction *I);
159a562b46dSReed Kotler   bool selectBranch(const Instruction *I);
160127f894bSVasileios Kalintiris   bool selectSelect(const Instruction *I);
161a562b46dSReed Kotler   bool selectCmp(const Instruction *I);
162a562b46dSReed Kotler   bool selectFPExt(const Instruction *I);
163a562b46dSReed Kotler   bool selectFPTrunc(const Instruction *I);
164a562b46dSReed Kotler   bool selectFPToInt(const Instruction *I, bool IsSigned);
165a562b46dSReed Kotler   bool selectRet(const Instruction *I);
166a562b46dSReed Kotler   bool selectTrunc(const Instruction *I);
167a562b46dSReed Kotler   bool selectIntExt(const Instruction *I);
1687a6b1878SVasileios Kalintiris   bool selectShift(const Instruction *I);
1698fcb3986SVasileios Kalintiris   bool selectDivRem(const Instruction *I, unsigned ISDOpcode);
170a562b46dSReed Kotler 
171a562b46dSReed Kotler   // Utility helper routines.
172a562b46dSReed Kotler   bool isTypeLegal(Type *Ty, MVT &VT);
17307d3a2f6SReed Kotler   bool isTypeSupported(Type *Ty, MVT &VT);
174a562b46dSReed Kotler   bool isLoadTypeLegal(Type *Ty, MVT &VT);
175a562b46dSReed Kotler   bool computeAddress(const Value *Obj, Address &Addr);
176d5c4196cSReed Kotler   bool computeCallAddress(const Value *V, Address &Addr);
1775fb7d8b5SReed Kotler   void simplifyAddress(Address &Addr);
178a562b46dSReed Kotler 
179a562b46dSReed Kotler   // Emit helper routines.
180a562b46dSReed Kotler   bool emitCmp(unsigned DestReg, const CmpInst *CI);
181*310e3279SGuillaume Chatelet   bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr);
182*310e3279SGuillaume Chatelet   bool emitStore(MVT VT, unsigned SrcReg, Address &Addr);
183d5c4196cSReed Kotler   unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
184a562b46dSReed Kotler   bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg,
185a562b46dSReed Kotler 
186a562b46dSReed Kotler                   bool IsZExt);
187a562b46dSReed Kotler   bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
188a562b46dSReed Kotler 
189a562b46dSReed Kotler   bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg);
190a562b46dSReed Kotler   bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
191a562b46dSReed Kotler                        unsigned DestReg);
192a562b46dSReed Kotler   bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
193a562b46dSReed Kotler                        unsigned DestReg);
194a562b46dSReed Kotler 
195a562b46dSReed Kotler   unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned);
196a562b46dSReed Kotler 
19707d3a2f6SReed Kotler   unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS,
19807d3a2f6SReed Kotler                          const Value *RHS);
19907d3a2f6SReed Kotler 
200a562b46dSReed Kotler   unsigned materializeFP(const ConstantFP *CFP, MVT VT);
201a562b46dSReed Kotler   unsigned materializeGV(const GlobalValue *GV, MVT VT);
202a562b46dSReed Kotler   unsigned materializeInt(const Constant *C, MVT VT);
203a562b46dSReed Kotler   unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
204ce4c2bc1SRafael Espindola   unsigned materializeExternalCallSym(MCSymbol *Syn);
205a562b46dSReed Kotler 
emitInst(unsigned Opc)206a562b46dSReed Kotler   MachineInstrBuilder emitInst(unsigned Opc) {
207a562b46dSReed Kotler     return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
208a562b46dSReed Kotler   }
209dde94e4cSEugene Zelenko 
emitInst(unsigned Opc,unsigned DstReg)210a562b46dSReed Kotler   MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) {
211a562b46dSReed Kotler     return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
212a562b46dSReed Kotler                    DstReg);
213a562b46dSReed Kotler   }
214dde94e4cSEugene Zelenko 
emitInstStore(unsigned Opc,unsigned SrcReg,unsigned MemReg,int64_t MemOffset)215a562b46dSReed Kotler   MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg,
216a562b46dSReed Kotler                                     unsigned MemReg, int64_t MemOffset) {
217a562b46dSReed Kotler     return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
218a562b46dSReed Kotler   }
219dde94e4cSEugene Zelenko 
emitInstLoad(unsigned Opc,unsigned DstReg,unsigned MemReg,int64_t MemOffset)220a562b46dSReed Kotler   MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg,
221a562b46dSReed Kotler                                    unsigned MemReg, int64_t MemOffset) {
222a562b46dSReed Kotler     return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
223a562b46dSReed Kotler   }
2247f680e15SVasileios Kalintiris 
2257f680e15SVasileios Kalintiris   unsigned fastEmitInst_rr(unsigned MachineInstOpcode,
2267f680e15SVasileios Kalintiris                            const TargetRegisterClass *RC,
22766506582SNikita Popov                            unsigned Op0, unsigned Op1);
2287f680e15SVasileios Kalintiris 
229a562b46dSReed Kotler   // for some reason, this default is not generated by tablegen
230a562b46dSReed Kotler   // so we explicitly generate it here.
fastEmitInst_riir(uint64_t inst,const TargetRegisterClass * RC,unsigned Op0,uint64_t imm1,uint64_t imm2,unsigned Op3)231a562b46dSReed Kotler   unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC,
23266506582SNikita Popov                              unsigned Op0, uint64_t imm1, uint64_t imm2,
23366506582SNikita Popov                              unsigned Op3) {
234a562b46dSReed Kotler     return 0;
235a562b46dSReed Kotler   }
23667077b30SReed Kotler 
237d5c4196cSReed Kotler   // Call handling routines.
238d5c4196cSReed Kotler private:
239d5c4196cSReed Kotler   CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const;
240d5c4196cSReed Kotler   bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs,
241d5c4196cSReed Kotler                        unsigned &NumBytes);
242d5c4196cSReed Kotler   bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes);
243dde94e4cSEugene Zelenko 
getABI() const244cbaca42aSDaniel Sanders   const MipsABIInfo &getABI() const {
245cbaca42aSDaniel Sanders     return static_cast<const MipsTargetMachine &>(TM).getABI();
246cbaca42aSDaniel Sanders   }
247d5c4196cSReed Kotler 
248720c5ca4SReed Kotler public:
249a562b46dSReed Kotler   // Backend specific FastISel code.
MipsFastISel(FunctionLoweringInfo & funcInfo,const TargetLibraryInfo * libInfo)250720c5ca4SReed Kotler   explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
251720c5ca4SReed Kotler                         const TargetLibraryInfo *libInfo)
2523ab98895SEric Christopher       : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()),
253b2a5fa98SEric Christopher         Subtarget(&funcInfo.MF->getSubtarget<MipsSubtarget>()),
25496e72c6aSEric Christopher         TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) {
25567077b30SReed Kotler     MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
25667077b30SReed Kotler     Context = &funcInfo.Fn->getContext();
25786b3a1e7SSimon Dardis     UnsupportedFPMode = Subtarget->isFP64bit() || Subtarget->useSoftFloat();
25867077b30SReed Kotler   }
25967077b30SReed Kotler 
260816ea84eSVasileios Kalintiris   unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
2615b8bb4d7SJuergen Ributzka   unsigned fastMaterializeConstant(const Constant *C) override;
262a562b46dSReed Kotler   bool fastSelectInstruction(const Instruction *I) override;
2639fe3bfd0SReed Kotler 
2649fe25f35SReed Kotler #include "MipsGenFastISel.inc"
265720c5ca4SReed Kotler };
266dde94e4cSEugene Zelenko 
267dde94e4cSEugene Zelenko } // end anonymous namespace
26867077b30SReed Kotler 
269d5c4196cSReed Kotler static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT,
270d5c4196cSReed Kotler                     CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
271d378174dSReid Kleckner                     CCState &State) LLVM_ATTRIBUTE_UNUSED;
272d5c4196cSReed Kotler 
CC_MipsO32_FP32(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)273d5c4196cSReed Kotler static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT,
274d5c4196cSReed Kotler                             CCValAssign::LocInfo LocInfo,
275d5c4196cSReed Kotler                             ISD::ArgFlagsTy ArgFlags, CCState &State) {
276d5c4196cSReed Kotler   llvm_unreachable("should not be called");
277d5c4196cSReed Kotler }
278d5c4196cSReed Kotler 
CC_MipsO32_FP64(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)279970eac40SBenjamin Kramer static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT,
280970eac40SBenjamin Kramer                             CCValAssign::LocInfo LocInfo,
281970eac40SBenjamin Kramer                             ISD::ArgFlagsTy ArgFlags, CCState &State) {
282d5c4196cSReed Kotler   llvm_unreachable("should not be called");
283d5c4196cSReed Kotler }
284d5c4196cSReed Kotler 
285d5c4196cSReed Kotler #include "MipsGenCallingConv.inc"
286d5c4196cSReed Kotler 
CCAssignFnForCall(CallingConv::ID CC) const287d5c4196cSReed Kotler CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const {
288d5c4196cSReed Kotler   return CC_MipsO32;
289d5c4196cSReed Kotler }
290d5c4196cSReed Kotler 
emitLogicalOp(unsigned ISDOpc,MVT RetVT,const Value * LHS,const Value * RHS)29107d3a2f6SReed Kotler unsigned MipsFastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT,
29207d3a2f6SReed Kotler                                      const Value *LHS, const Value *RHS) {
29307d3a2f6SReed Kotler   // Canonicalize immediates to the RHS first.
29407d3a2f6SReed Kotler   if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
29507d3a2f6SReed Kotler     std::swap(LHS, RHS);
29607d3a2f6SReed Kotler 
29707d3a2f6SReed Kotler   unsigned Opc;
298daad571bSVasileios Kalintiris   switch (ISDOpc) {
299daad571bSVasileios Kalintiris   case ISD::AND:
30007d3a2f6SReed Kotler     Opc = Mips::AND;
301daad571bSVasileios Kalintiris     break;
302daad571bSVasileios Kalintiris   case ISD::OR:
30307d3a2f6SReed Kotler     Opc = Mips::OR;
304daad571bSVasileios Kalintiris     break;
305daad571bSVasileios Kalintiris   case ISD::XOR:
30607d3a2f6SReed Kotler     Opc = Mips::XOR;
307daad571bSVasileios Kalintiris     break;
308daad571bSVasileios Kalintiris   default:
30907d3a2f6SReed Kotler     llvm_unreachable("unexpected opcode");
310daad571bSVasileios Kalintiris   }
31107d3a2f6SReed Kotler 
312d6b07348SJim Lin   Register LHSReg = getRegForValue(LHS);
31307d3a2f6SReed Kotler   if (!LHSReg)
31407d3a2f6SReed Kotler     return 0;
31507d3a2f6SReed Kotler 
316daad571bSVasileios Kalintiris   unsigned RHSReg;
31707d3a2f6SReed Kotler   if (const auto *C = dyn_cast<ConstantInt>(RHS))
31807d3a2f6SReed Kotler     RHSReg = materializeInt(C, MVT::i32);
31907d3a2f6SReed Kotler   else
32007d3a2f6SReed Kotler     RHSReg = getRegForValue(RHS);
32107d3a2f6SReed Kotler   if (!RHSReg)
32207d3a2f6SReed Kotler     return 0;
32307d3a2f6SReed Kotler 
324d6b07348SJim Lin   Register ResultReg = createResultReg(&Mips::GPR32RegClass);
325daad571bSVasileios Kalintiris   if (!ResultReg)
326daad571bSVasileios Kalintiris     return 0;
327daad571bSVasileios Kalintiris 
32807d3a2f6SReed Kotler   emitInst(Opc, ResultReg).addReg(LHSReg).addReg(RHSReg);
32907d3a2f6SReed Kotler   return ResultReg;
33007d3a2f6SReed Kotler }
33107d3a2f6SReed Kotler 
fastMaterializeAlloca(const AllocaInst * AI)332816ea84eSVasileios Kalintiris unsigned MipsFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
33344ede33aSMehdi Amini   assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i32 &&
334816ea84eSVasileios Kalintiris          "Alloca should always return a pointer.");
335816ea84eSVasileios Kalintiris 
336816ea84eSVasileios Kalintiris   DenseMap<const AllocaInst *, int>::iterator SI =
337816ea84eSVasileios Kalintiris       FuncInfo.StaticAllocaMap.find(AI);
338816ea84eSVasileios Kalintiris 
339816ea84eSVasileios Kalintiris   if (SI != FuncInfo.StaticAllocaMap.end()) {
340d6b07348SJim Lin     Register ResultReg = createResultReg(&Mips::GPR32RegClass);
341816ea84eSVasileios Kalintiris     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LEA_ADDiu),
342816ea84eSVasileios Kalintiris             ResultReg)
343816ea84eSVasileios Kalintiris         .addFrameIndex(SI->second)
344816ea84eSVasileios Kalintiris         .addImm(0);
345816ea84eSVasileios Kalintiris     return ResultReg;
346816ea84eSVasileios Kalintiris   }
347816ea84eSVasileios Kalintiris 
348816ea84eSVasileios Kalintiris   return 0;
349816ea84eSVasileios Kalintiris }
350816ea84eSVasileios Kalintiris 
materializeInt(const Constant * C,MVT VT)351d4ea29e6SReed Kotler unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) {
352d4ea29e6SReed Kotler   if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
353497311abSReed Kotler     return 0;
354d4ea29e6SReed Kotler   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
355d4ea29e6SReed Kotler   const ConstantInt *CI = cast<ConstantInt>(C);
35677fb0a3dSVasileios Kalintiris   return materialize32BitInt(CI->getZExtValue(), RC);
357497311abSReed Kotler }
358497311abSReed Kotler 
materialize32BitInt(int64_t Imm,const TargetRegisterClass * RC)359d4ea29e6SReed Kotler unsigned MipsFastISel::materialize32BitInt(int64_t Imm,
360d4ea29e6SReed Kotler                                            const TargetRegisterClass *RC) {
361d6b07348SJim Lin   Register ResultReg = createResultReg(RC);
362d4ea29e6SReed Kotler 
363d4ea29e6SReed Kotler   if (isInt<16>(Imm)) {
364d4ea29e6SReed Kotler     unsigned Opc = Mips::ADDiu;
365d4ea29e6SReed Kotler     emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
366d4ea29e6SReed Kotler     return ResultReg;
367d4ea29e6SReed Kotler   } else if (isUInt<16>(Imm)) {
368d4ea29e6SReed Kotler     emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
369d4ea29e6SReed Kotler     return ResultReg;
3709fe3bfd0SReed Kotler   }
371d4ea29e6SReed Kotler   unsigned Lo = Imm & 0xFFFF;
372d4ea29e6SReed Kotler   unsigned Hi = (Imm >> 16) & 0xFFFF;
373d4ea29e6SReed Kotler   if (Lo) {
374d4ea29e6SReed Kotler     // Both Lo and Hi have nonzero bits.
375d6b07348SJim Lin     Register TmpReg = createResultReg(RC);
376d4ea29e6SReed Kotler     emitInst(Mips::LUi, TmpReg).addImm(Hi);
377d4ea29e6SReed Kotler     emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
378d4ea29e6SReed Kotler   } else {
379d4ea29e6SReed Kotler     emitInst(Mips::LUi, ResultReg).addImm(Hi);
3809fe3bfd0SReed Kotler   }
381d4ea29e6SReed Kotler   return ResultReg;
3829fe3bfd0SReed Kotler }
383d4ea29e6SReed Kotler 
materializeFP(const ConstantFP * CFP,MVT VT)384d4ea29e6SReed Kotler unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) {
38512f9488eSReed Kotler   if (UnsupportedFPMode)
386d4ea29e6SReed Kotler     return 0;
387d4ea29e6SReed Kotler   int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
388d4ea29e6SReed Kotler   if (VT == MVT::f32) {
389d4ea29e6SReed Kotler     const TargetRegisterClass *RC = &Mips::FGR32RegClass;
390d6b07348SJim Lin     Register DestReg = createResultReg(RC);
391d4ea29e6SReed Kotler     unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass);
392d4ea29e6SReed Kotler     emitInst(Mips::MTC1, DestReg).addReg(TempReg);
393d4ea29e6SReed Kotler     return DestReg;
394d4ea29e6SReed Kotler   } else if (VT == MVT::f64) {
395d4ea29e6SReed Kotler     const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
396d6b07348SJim Lin     Register DestReg = createResultReg(RC);
397d4ea29e6SReed Kotler     unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
398d4ea29e6SReed Kotler     unsigned TempReg2 =
399d4ea29e6SReed Kotler         materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
400d4ea29e6SReed Kotler     emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
401d4ea29e6SReed Kotler     return DestReg;
4029fe3bfd0SReed Kotler   }
403d4ea29e6SReed Kotler   return 0;
4049fe3bfd0SReed Kotler }
405d4ea29e6SReed Kotler 
materializeGV(const GlobalValue * GV,MVT VT)406d4ea29e6SReed Kotler unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) {
407d4ea29e6SReed Kotler   // For now 32-bit only.
408d4ea29e6SReed Kotler   if (VT != MVT::i32)
409d4ea29e6SReed Kotler     return 0;
410d4ea29e6SReed Kotler   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
411d6b07348SJim Lin   Register DestReg = createResultReg(RC);
412d4ea29e6SReed Kotler   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
413d4ea29e6SReed Kotler   bool IsThreadLocal = GVar && GVar->isThreadLocal();
414d4ea29e6SReed Kotler   // TLS not supported at this time.
415d4ea29e6SReed Kotler   if (IsThreadLocal)
416d4ea29e6SReed Kotler     return 0;
417d4ea29e6SReed Kotler   emitInst(Mips::LW, DestReg)
418669bb311SMatt Arsenault       .addReg(MFI->getGlobalBaseReg(*MF))
419d4ea29e6SReed Kotler       .addGlobalAddress(GV, 0, MipsII::MO_GOT);
420d4ea29e6SReed Kotler   if ((GV->hasInternalLinkage() ||
421d4ea29e6SReed Kotler        (GV->hasLocalLinkage() && !isa<Function>(GV)))) {
422d6b07348SJim Lin     Register TempReg = createResultReg(RC);
423d4ea29e6SReed Kotler     emitInst(Mips::ADDiu, TempReg)
424d4ea29e6SReed Kotler         .addReg(DestReg)
425d4ea29e6SReed Kotler         .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO);
426d4ea29e6SReed Kotler     DestReg = TempReg;
4279fe3bfd0SReed Kotler   }
428d4ea29e6SReed Kotler   return DestReg;
4299fe3bfd0SReed Kotler }
4309fe3bfd0SReed Kotler 
materializeExternalCallSym(MCSymbol * Sym)431ce4c2bc1SRafael Espindola unsigned MipsFastISel::materializeExternalCallSym(MCSymbol *Sym) {
432bdb91b31SVasileios Kalintiris   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
433d6b07348SJim Lin   Register DestReg = createResultReg(RC);
434bdb91b31SVasileios Kalintiris   emitInst(Mips::LW, DestReg)
435669bb311SMatt Arsenault       .addReg(MFI->getGlobalBaseReg(*MF))
436ce4c2bc1SRafael Espindola       .addSym(Sym, MipsII::MO_GOT);
437bdb91b31SVasileios Kalintiris   return DestReg;
438bdb91b31SVasileios Kalintiris }
439bdb91b31SVasileios Kalintiris 
440bab3f23dSReed Kotler // Materialize a constant into a register, and return the register
441bab3f23dSReed Kotler // number (or zero if we failed to handle it).
fastMaterializeConstant(const Constant * C)4425b8bb4d7SJuergen Ributzka unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
44344ede33aSMehdi Amini   EVT CEVT = TLI.getValueType(DL, C->getType(), true);
444bab3f23dSReed Kotler 
445bab3f23dSReed Kotler   // Only handle simple types.
446bab3f23dSReed Kotler   if (!CEVT.isSimple())
447bab3f23dSReed Kotler     return 0;
448bab3f23dSReed Kotler   MVT VT = CEVT.getSimpleVT();
449bab3f23dSReed Kotler 
450bab3f23dSReed Kotler   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
451a562b46dSReed Kotler     return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT);
452bab3f23dSReed Kotler   else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
453a562b46dSReed Kotler     return materializeGV(GV, VT);
454bab3f23dSReed Kotler   else if (isa<ConstantInt>(C))
455a562b46dSReed Kotler     return materializeInt(C, VT);
456bab3f23dSReed Kotler 
457bab3f23dSReed Kotler   return 0;
458bab3f23dSReed Kotler }
459bab3f23dSReed Kotler 
computeAddress(const Value * Obj,Address & Addr)460d4ea29e6SReed Kotler bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) {
4615fb7d8b5SReed Kotler   const User *U = nullptr;
4625fb7d8b5SReed Kotler   unsigned Opcode = Instruction::UserOp1;
4635fb7d8b5SReed Kotler   if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
4645fb7d8b5SReed Kotler     // Don't walk into other basic blocks unless the object is an alloca from
4655fb7d8b5SReed Kotler     // another block, otherwise it may not have a virtual register assigned.
4665fb7d8b5SReed Kotler     if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
4675fb7d8b5SReed Kotler         FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
4685fb7d8b5SReed Kotler       Opcode = I->getOpcode();
4695fb7d8b5SReed Kotler       U = I;
4705fb7d8b5SReed Kotler     }
47132cd69a2SVasileios Kalintiris   } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
47232cd69a2SVasileios Kalintiris     Opcode = C->getOpcode();
47332cd69a2SVasileios Kalintiris     U = C;
47432cd69a2SVasileios Kalintiris   }
4755fb7d8b5SReed Kotler   switch (Opcode) {
4765fb7d8b5SReed Kotler   default:
4775fb7d8b5SReed Kotler     break;
478dde94e4cSEugene Zelenko   case Instruction::BitCast:
4795fb7d8b5SReed Kotler     // Look through bitcasts.
4805fb7d8b5SReed Kotler     return computeAddress(U->getOperand(0), Addr);
4815fb7d8b5SReed Kotler   case Instruction::GetElementPtr: {
4825fb7d8b5SReed Kotler     Address SavedAddr = Addr;
4838ca1cbccSSimon Dardis     int64_t TmpOffset = Addr.getOffset();
4845fb7d8b5SReed Kotler     // Iterate through the GEP folding the constants into offsets where
4855fb7d8b5SReed Kotler     // we can.
4865fb7d8b5SReed Kotler     gep_type_iterator GTI = gep_type_begin(U);
4875fb7d8b5SReed Kotler     for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e;
4885fb7d8b5SReed Kotler          ++i, ++GTI) {
4895fb7d8b5SReed Kotler       const Value *Op = *i;
490ab85225bSPeter Collingbourne       if (StructType *STy = GTI.getStructTypeOrNull()) {
4915fb7d8b5SReed Kotler         const StructLayout *SL = DL.getStructLayout(STy);
4925fb7d8b5SReed Kotler         unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
4935fb7d8b5SReed Kotler         TmpOffset += SL->getElementOffset(Idx);
4945fb7d8b5SReed Kotler       } else {
4955fb7d8b5SReed Kotler         uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
496dde94e4cSEugene Zelenko         while (true) {
4975fb7d8b5SReed Kotler           if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
4985fb7d8b5SReed Kotler             // Constant-offset addressing.
4995fb7d8b5SReed Kotler             TmpOffset += CI->getSExtValue() * S;
5005fb7d8b5SReed Kotler             break;
5015fb7d8b5SReed Kotler           }
5025fb7d8b5SReed Kotler           if (canFoldAddIntoGEP(U, Op)) {
5035fb7d8b5SReed Kotler             // A compatible add with a constant operand. Fold the constant.
5045fb7d8b5SReed Kotler             ConstantInt *CI =
5055fb7d8b5SReed Kotler                 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
5065fb7d8b5SReed Kotler             TmpOffset += CI->getSExtValue() * S;
5075fb7d8b5SReed Kotler             // Iterate on the other operand.
5085fb7d8b5SReed Kotler             Op = cast<AddOperator>(Op)->getOperand(0);
5095fb7d8b5SReed Kotler             continue;
5105fb7d8b5SReed Kotler           }
5115fb7d8b5SReed Kotler           // Unsupported
5125fb7d8b5SReed Kotler           goto unsupported_gep;
5135fb7d8b5SReed Kotler         }
5145fb7d8b5SReed Kotler       }
5155fb7d8b5SReed Kotler     }
5165fb7d8b5SReed Kotler     // Try to grab the base operand now.
5175fb7d8b5SReed Kotler     Addr.setOffset(TmpOffset);
5185fb7d8b5SReed Kotler     if (computeAddress(U->getOperand(0), Addr))
5195fb7d8b5SReed Kotler       return true;
5205fb7d8b5SReed Kotler     // We failed, restore everything and try the other options.
5215fb7d8b5SReed Kotler     Addr = SavedAddr;
5225fb7d8b5SReed Kotler   unsupported_gep:
5235fb7d8b5SReed Kotler     break;
5245fb7d8b5SReed Kotler   }
5255fb7d8b5SReed Kotler   case Instruction::Alloca: {
5265fb7d8b5SReed Kotler     const AllocaInst *AI = cast<AllocaInst>(Obj);
5275fb7d8b5SReed Kotler     DenseMap<const AllocaInst *, int>::iterator SI =
5285fb7d8b5SReed Kotler         FuncInfo.StaticAllocaMap.find(AI);
5295fb7d8b5SReed Kotler     if (SI != FuncInfo.StaticAllocaMap.end()) {
5305fb7d8b5SReed Kotler       Addr.setKind(Address::FrameIndexBase);
5315fb7d8b5SReed Kotler       Addr.setFI(SI->second);
5325fb7d8b5SReed Kotler       return true;
5335fb7d8b5SReed Kotler     }
5345fb7d8b5SReed Kotler     break;
5355fb7d8b5SReed Kotler   }
5365fb7d8b5SReed Kotler   }
537d4ea29e6SReed Kotler   Addr.setReg(getRegForValue(Obj));
538d4ea29e6SReed Kotler   return Addr.getReg() != 0;
5399fe3bfd0SReed Kotler }
540d4ea29e6SReed Kotler 
computeCallAddress(const Value * V,Address & Addr)541d5c4196cSReed Kotler bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) {
542bdb91b31SVasileios Kalintiris   const User *U = nullptr;
543bdb91b31SVasileios Kalintiris   unsigned Opcode = Instruction::UserOp1;
544bdb91b31SVasileios Kalintiris 
545bdb91b31SVasileios Kalintiris   if (const auto *I = dyn_cast<Instruction>(V)) {
546bdb91b31SVasileios Kalintiris     // Check if the value is defined in the same basic block. This information
547bdb91b31SVasileios Kalintiris     // is crucial to know whether or not folding an operand is valid.
548bdb91b31SVasileios Kalintiris     if (I->getParent() == FuncInfo.MBB->getBasicBlock()) {
549bdb91b31SVasileios Kalintiris       Opcode = I->getOpcode();
550bdb91b31SVasileios Kalintiris       U = I;
551bdb91b31SVasileios Kalintiris     }
552bdb91b31SVasileios Kalintiris   } else if (const auto *C = dyn_cast<ConstantExpr>(V)) {
553bdb91b31SVasileios Kalintiris     Opcode = C->getOpcode();
554bdb91b31SVasileios Kalintiris     U = C;
555bdb91b31SVasileios Kalintiris   }
556bdb91b31SVasileios Kalintiris 
557bdb91b31SVasileios Kalintiris   switch (Opcode) {
558bdb91b31SVasileios Kalintiris   default:
559bdb91b31SVasileios Kalintiris     break;
560bdb91b31SVasileios Kalintiris   case Instruction::BitCast:
561bdb91b31SVasileios Kalintiris     // Look past bitcasts if its operand is in the same BB.
562bdb91b31SVasileios Kalintiris       return computeCallAddress(U->getOperand(0), Addr);
563bdb91b31SVasileios Kalintiris     break;
564bdb91b31SVasileios Kalintiris   case Instruction::IntToPtr:
565bdb91b31SVasileios Kalintiris     // Look past no-op inttoptrs if its operand is in the same BB.
56644ede33aSMehdi Amini     if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
56744ede33aSMehdi Amini         TLI.getPointerTy(DL))
568bdb91b31SVasileios Kalintiris       return computeCallAddress(U->getOperand(0), Addr);
569bdb91b31SVasileios Kalintiris     break;
570bdb91b31SVasileios Kalintiris   case Instruction::PtrToInt:
571bdb91b31SVasileios Kalintiris     // Look past no-op ptrtoints if its operand is in the same BB.
57244ede33aSMehdi Amini     if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
573bdb91b31SVasileios Kalintiris       return computeCallAddress(U->getOperand(0), Addr);
574bdb91b31SVasileios Kalintiris     break;
575bdb91b31SVasileios Kalintiris   }
576bdb91b31SVasileios Kalintiris 
577d5c4196cSReed Kotler   if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
578d5c4196cSReed Kotler     Addr.setGlobalValue(GV);
579d5c4196cSReed Kotler     return true;
580d5c4196cSReed Kotler   }
581bdb91b31SVasileios Kalintiris 
582bdb91b31SVasileios Kalintiris   // If all else fails, try to materialize the value in a register.
583bdb91b31SVasileios Kalintiris   if (!Addr.getGlobalValue()) {
584bdb91b31SVasileios Kalintiris     Addr.setReg(getRegForValue(V));
585bdb91b31SVasileios Kalintiris     return Addr.getReg() != 0;
586bdb91b31SVasileios Kalintiris   }
587bdb91b31SVasileios Kalintiris 
588d5c4196cSReed Kotler   return false;
589d5c4196cSReed Kotler }
590d5c4196cSReed Kotler 
isTypeLegal(Type * Ty,MVT & VT)591d4ea29e6SReed Kotler bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
59244ede33aSMehdi Amini   EVT evt = TLI.getValueType(DL, Ty, true);
593d4ea29e6SReed Kotler   // Only handle simple types.
594d4ea29e6SReed Kotler   if (evt == MVT::Other || !evt.isSimple())
595d4ea29e6SReed Kotler     return false;
596d4ea29e6SReed Kotler   VT = evt.getSimpleVT();
597d4ea29e6SReed Kotler 
598d4ea29e6SReed Kotler   // Handle all legal types, i.e. a register that will directly hold this
599d4ea29e6SReed Kotler   // value.
600d4ea29e6SReed Kotler   return TLI.isTypeLegal(VT);
601d4ea29e6SReed Kotler }
602d4ea29e6SReed Kotler 
isTypeSupported(Type * Ty,MVT & VT)60307d3a2f6SReed Kotler bool MipsFastISel::isTypeSupported(Type *Ty, MVT &VT) {
60407d3a2f6SReed Kotler   if (Ty->isVectorTy())
60507d3a2f6SReed Kotler     return false;
60607d3a2f6SReed Kotler 
60707d3a2f6SReed Kotler   if (isTypeLegal(Ty, VT))
60807d3a2f6SReed Kotler     return true;
60907d3a2f6SReed Kotler 
61007d3a2f6SReed Kotler   // If this is a type than can be sign or zero-extended to a basic operation
61107d3a2f6SReed Kotler   // go ahead and accept it now.
61207d3a2f6SReed Kotler   if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)
61307d3a2f6SReed Kotler     return true;
61407d3a2f6SReed Kotler 
61507d3a2f6SReed Kotler   return false;
61607d3a2f6SReed Kotler }
61707d3a2f6SReed Kotler 
isLoadTypeLegal(Type * Ty,MVT & VT)618d4ea29e6SReed Kotler bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
619d4ea29e6SReed Kotler   if (isTypeLegal(Ty, VT))
6209fe3bfd0SReed Kotler     return true;
621d4ea29e6SReed Kotler   // We will extend this in a later patch:
622d4ea29e6SReed Kotler   //   If this is a type than can be sign or zero-extended to a basic operation
623d4ea29e6SReed Kotler   //   go ahead and accept it now.
624d4ea29e6SReed Kotler   if (VT == MVT::i8 || VT == MVT::i16)
6253ebdcc9eSReed Kotler     return true;
62662de6b96SReed Kotler   return false;
62762de6b96SReed Kotler }
62879220eaeSEugene Zelenko 
62962de6b96SReed Kotler // Because of how EmitCmp is called with fast-isel, you can
630497311abSReed Kotler // end up with redundant "andi" instructions after the sequences emitted below.
631497311abSReed Kotler // We should try and solve this issue in the future.
632497311abSReed Kotler //
emitCmp(unsigned ResultReg,const CmpInst * CI)633a562b46dSReed Kotler bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
63462de6b96SReed Kotler   const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1);
635497311abSReed Kotler   bool IsUnsigned = CI->isUnsigned();
636497311abSReed Kotler   unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned);
637497311abSReed Kotler   if (LeftReg == 0)
638497311abSReed Kotler     return false;
639497311abSReed Kotler   unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned);
640497311abSReed Kotler   if (RightReg == 0)
641497311abSReed Kotler     return false;
6421f64ecabSReed Kotler   CmpInst::Predicate P = CI->getPredicate();
64362de6b96SReed Kotler 
6441f64ecabSReed Kotler   switch (P) {
645497311abSReed Kotler   default:
646497311abSReed Kotler     return false;
647497311abSReed Kotler   case CmpInst::ICMP_EQ: {
648d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
649a562b46dSReed Kotler     emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
650a562b46dSReed Kotler     emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1);
651497311abSReed Kotler     break;
652497311abSReed Kotler   }
653497311abSReed Kotler   case CmpInst::ICMP_NE: {
654d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
655a562b46dSReed Kotler     emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg);
656a562b46dSReed Kotler     emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg);
657497311abSReed Kotler     break;
658497311abSReed Kotler   }
659dde94e4cSEugene Zelenko   case CmpInst::ICMP_UGT:
660a562b46dSReed Kotler     emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg);
661497311abSReed Kotler     break;
662dde94e4cSEugene Zelenko   case CmpInst::ICMP_ULT:
663a562b46dSReed Kotler     emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg);
664497311abSReed Kotler     break;
665497311abSReed Kotler   case CmpInst::ICMP_UGE: {
666d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
667a562b46dSReed Kotler     emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg);
668a562b46dSReed Kotler     emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
669497311abSReed Kotler     break;
670497311abSReed Kotler   }
671497311abSReed Kotler   case CmpInst::ICMP_ULE: {
672d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
673a562b46dSReed Kotler     emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg);
674a562b46dSReed Kotler     emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
675497311abSReed Kotler     break;
676497311abSReed Kotler   }
677dde94e4cSEugene Zelenko   case CmpInst::ICMP_SGT:
678a562b46dSReed Kotler     emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg);
679497311abSReed Kotler     break;
680dde94e4cSEugene Zelenko   case CmpInst::ICMP_SLT:
681a562b46dSReed Kotler     emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg);
682497311abSReed Kotler     break;
683497311abSReed Kotler   case CmpInst::ICMP_SGE: {
684d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
685a562b46dSReed Kotler     emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg);
686a562b46dSReed Kotler     emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
687497311abSReed Kotler     break;
688497311abSReed Kotler   }
689497311abSReed Kotler   case CmpInst::ICMP_SLE: {
690d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
691a562b46dSReed Kotler     emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg);
692a562b46dSReed Kotler     emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1);
693497311abSReed Kotler     break;
694497311abSReed Kotler   }
6951f64ecabSReed Kotler   case CmpInst::FCMP_OEQ:
6961f64ecabSReed Kotler   case CmpInst::FCMP_UNE:
6971f64ecabSReed Kotler   case CmpInst::FCMP_OLT:
6981f64ecabSReed Kotler   case CmpInst::FCMP_OLE:
6991f64ecabSReed Kotler   case CmpInst::FCMP_OGT:
7001f64ecabSReed Kotler   case CmpInst::FCMP_OGE: {
7011f64ecabSReed Kotler     if (UnsupportedFPMode)
7021f64ecabSReed Kotler       return false;
7031f64ecabSReed Kotler     bool IsFloat = Left->getType()->isFloatTy();
7041f64ecabSReed Kotler     bool IsDouble = Left->getType()->isDoubleTy();
7051f64ecabSReed Kotler     if (!IsFloat && !IsDouble)
7061f64ecabSReed Kotler       return false;
7071f64ecabSReed Kotler     unsigned Opc, CondMovOpc;
7081f64ecabSReed Kotler     switch (P) {
7091f64ecabSReed Kotler     case CmpInst::FCMP_OEQ:
7101f64ecabSReed Kotler       Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
7111f64ecabSReed Kotler       CondMovOpc = Mips::MOVT_I;
7121f64ecabSReed Kotler       break;
7131f64ecabSReed Kotler     case CmpInst::FCMP_UNE:
7141f64ecabSReed Kotler       Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32;
7151f64ecabSReed Kotler       CondMovOpc = Mips::MOVF_I;
7161f64ecabSReed Kotler       break;
7171f64ecabSReed Kotler     case CmpInst::FCMP_OLT:
7181f64ecabSReed Kotler       Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32;
7191f64ecabSReed Kotler       CondMovOpc = Mips::MOVT_I;
7201f64ecabSReed Kotler       break;
7211f64ecabSReed Kotler     case CmpInst::FCMP_OLE:
7221f64ecabSReed Kotler       Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32;
7231f64ecabSReed Kotler       CondMovOpc = Mips::MOVT_I;
7241f64ecabSReed Kotler       break;
7251f64ecabSReed Kotler     case CmpInst::FCMP_OGT:
7261f64ecabSReed Kotler       Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32;
7271f64ecabSReed Kotler       CondMovOpc = Mips::MOVF_I;
7281f64ecabSReed Kotler       break;
7291f64ecabSReed Kotler     case CmpInst::FCMP_OGE:
7301f64ecabSReed Kotler       Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32;
7311f64ecabSReed Kotler       CondMovOpc = Mips::MOVF_I;
7321f64ecabSReed Kotler       break;
7331f64ecabSReed Kotler     default:
73438811ccbSChandler Carruth       llvm_unreachable("Only switching of a subset of CCs.");
7351f64ecabSReed Kotler     }
736d6b07348SJim Lin     Register RegWithZero = createResultReg(&Mips::GPR32RegClass);
737d6b07348SJim Lin     Register RegWithOne = createResultReg(&Mips::GPR32RegClass);
738a562b46dSReed Kotler     emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
739a562b46dSReed Kotler     emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
740730fdb73SSimon Dardis     emitInst(Opc).addReg(Mips::FCC0, RegState::Define).addReg(LeftReg)
741730fdb73SSimon Dardis                  .addReg(RightReg);
742a6cda121SDaniel Sanders     emitInst(CondMovOpc, ResultReg)
7431f64ecabSReed Kotler         .addReg(RegWithOne)
7441f64ecabSReed Kotler         .addReg(Mips::FCC0)
745a6cda121SDaniel Sanders         .addReg(RegWithZero);
7461f64ecabSReed Kotler     break;
7471f64ecabSReed Kotler   }
748497311abSReed Kotler   }
74962de6b96SReed Kotler   return true;
75062de6b96SReed Kotler }
751dde94e4cSEugene Zelenko 
emitLoad(MVT VT,unsigned & ResultReg,Address & Addr)752*310e3279SGuillaume Chatelet bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr) {
753d4ea29e6SReed Kotler   //
754d4ea29e6SReed Kotler   // more cases will be handled here in following patches.
755d4ea29e6SReed Kotler   //
756d4ea29e6SReed Kotler   unsigned Opc;
757d4ea29e6SReed Kotler   switch (VT.SimpleTy) {
758dde94e4cSEugene Zelenko   case MVT::i32:
759d4ea29e6SReed Kotler     ResultReg = createResultReg(&Mips::GPR32RegClass);
760d4ea29e6SReed Kotler     Opc = Mips::LW;
761d4ea29e6SReed Kotler     break;
762dde94e4cSEugene Zelenko   case MVT::i16:
763d4ea29e6SReed Kotler     ResultReg = createResultReg(&Mips::GPR32RegClass);
764d4ea29e6SReed Kotler     Opc = Mips::LHu;
765d4ea29e6SReed Kotler     break;
766dde94e4cSEugene Zelenko   case MVT::i8:
767d4ea29e6SReed Kotler     ResultReg = createResultReg(&Mips::GPR32RegClass);
768d4ea29e6SReed Kotler     Opc = Mips::LBu;
769d4ea29e6SReed Kotler     break;
770dde94e4cSEugene Zelenko   case MVT::f32:
771d4ea29e6SReed Kotler     if (UnsupportedFPMode)
772d4ea29e6SReed Kotler       return false;
773d4ea29e6SReed Kotler     ResultReg = createResultReg(&Mips::FGR32RegClass);
774d4ea29e6SReed Kotler     Opc = Mips::LWC1;
775d4ea29e6SReed Kotler     break;
776dde94e4cSEugene Zelenko   case MVT::f64:
777d4ea29e6SReed Kotler     if (UnsupportedFPMode)
778d4ea29e6SReed Kotler       return false;
779d4ea29e6SReed Kotler     ResultReg = createResultReg(&Mips::AFGR64RegClass);
780d4ea29e6SReed Kotler     Opc = Mips::LDC1;
781d4ea29e6SReed Kotler     break;
782d4ea29e6SReed Kotler   default:
783d4ea29e6SReed Kotler     return false;
784d4ea29e6SReed Kotler   }
7855fb7d8b5SReed Kotler   if (Addr.isRegBase()) {
7865fb7d8b5SReed Kotler     simplifyAddress(Addr);
787d4ea29e6SReed Kotler     emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset());
788d4ea29e6SReed Kotler     return true;
789d4ea29e6SReed Kotler   }
7905fb7d8b5SReed Kotler   if (Addr.isFIBase()) {
7915fb7d8b5SReed Kotler     unsigned FI = Addr.getFI();
7928ca1cbccSSimon Dardis     int64_t Offset = Addr.getOffset();
793941a705bSMatthias Braun     MachineFrameInfo &MFI = MF->getFrameInfo();
7945fb7d8b5SReed Kotler     MachineMemOperand *MMO = MF->getMachineMemOperand(
795e40c8a2bSAlex Lorenz         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
796c9d5c195SGuillaume Chatelet         MFI.getObjectSize(FI), Align(4));
7975fb7d8b5SReed Kotler     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
7985fb7d8b5SReed Kotler         .addFrameIndex(FI)
7995fb7d8b5SReed Kotler         .addImm(Offset)
8005fb7d8b5SReed Kotler         .addMemOperand(MMO);
8015fb7d8b5SReed Kotler     return true;
8025fb7d8b5SReed Kotler   }
8035fb7d8b5SReed Kotler   return false;
8045fb7d8b5SReed Kotler }
805d4ea29e6SReed Kotler 
emitStore(MVT VT,unsigned SrcReg,Address & Addr)806*310e3279SGuillaume Chatelet bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr) {
807d4ea29e6SReed Kotler   //
808d4ea29e6SReed Kotler   // more cases will be handled here in following patches.
809d4ea29e6SReed Kotler   //
810d4ea29e6SReed Kotler   unsigned Opc;
811d4ea29e6SReed Kotler   switch (VT.SimpleTy) {
812d4ea29e6SReed Kotler   case MVT::i8:
813d4ea29e6SReed Kotler     Opc = Mips::SB;
814d4ea29e6SReed Kotler     break;
815d4ea29e6SReed Kotler   case MVT::i16:
816d4ea29e6SReed Kotler     Opc = Mips::SH;
817d4ea29e6SReed Kotler     break;
818d4ea29e6SReed Kotler   case MVT::i32:
819d4ea29e6SReed Kotler     Opc = Mips::SW;
820d4ea29e6SReed Kotler     break;
821d4ea29e6SReed Kotler   case MVT::f32:
822d4ea29e6SReed Kotler     if (UnsupportedFPMode)
823d4ea29e6SReed Kotler       return false;
824d4ea29e6SReed Kotler     Opc = Mips::SWC1;
825d4ea29e6SReed Kotler     break;
826d4ea29e6SReed Kotler   case MVT::f64:
827d4ea29e6SReed Kotler     if (UnsupportedFPMode)
828d4ea29e6SReed Kotler       return false;
829d4ea29e6SReed Kotler     Opc = Mips::SDC1;
830d4ea29e6SReed Kotler     break;
831d4ea29e6SReed Kotler   default:
832d4ea29e6SReed Kotler     return false;
833d4ea29e6SReed Kotler   }
8345fb7d8b5SReed Kotler   if (Addr.isRegBase()) {
8355fb7d8b5SReed Kotler     simplifyAddress(Addr);
836d4ea29e6SReed Kotler     emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset());
837d4ea29e6SReed Kotler     return true;
838d4ea29e6SReed Kotler   }
8395fb7d8b5SReed Kotler   if (Addr.isFIBase()) {
8405fb7d8b5SReed Kotler     unsigned FI = Addr.getFI();
8418ca1cbccSSimon Dardis     int64_t Offset = Addr.getOffset();
842941a705bSMatthias Braun     MachineFrameInfo &MFI = MF->getFrameInfo();
8435fb7d8b5SReed Kotler     MachineMemOperand *MMO = MF->getMachineMemOperand(
844d8bceb9dSSimon Dardis         MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
845c9d5c195SGuillaume Chatelet         MFI.getObjectSize(FI), Align(4));
8465fb7d8b5SReed Kotler     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
8475fb7d8b5SReed Kotler         .addReg(SrcReg)
8485fb7d8b5SReed Kotler         .addFrameIndex(FI)
8495fb7d8b5SReed Kotler         .addImm(Offset)
8505fb7d8b5SReed Kotler         .addMemOperand(MMO);
8515fb7d8b5SReed Kotler     return true;
8525fb7d8b5SReed Kotler   }
8535fb7d8b5SReed Kotler   return false;
8545fb7d8b5SReed Kotler }
855d4ea29e6SReed Kotler 
selectLogicalOp(const Instruction * I)85607d3a2f6SReed Kotler bool MipsFastISel::selectLogicalOp(const Instruction *I) {
85707d3a2f6SReed Kotler   MVT VT;
85807d3a2f6SReed Kotler   if (!isTypeSupported(I->getType(), VT))
85907d3a2f6SReed Kotler     return false;
86007d3a2f6SReed Kotler 
86107d3a2f6SReed Kotler   unsigned ResultReg;
86207d3a2f6SReed Kotler   switch (I->getOpcode()) {
86307d3a2f6SReed Kotler   default:
86407d3a2f6SReed Kotler     llvm_unreachable("Unexpected instruction.");
86507d3a2f6SReed Kotler   case Instruction::And:
86607d3a2f6SReed Kotler     ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1));
86707d3a2f6SReed Kotler     break;
86807d3a2f6SReed Kotler   case Instruction::Or:
86907d3a2f6SReed Kotler     ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1));
87007d3a2f6SReed Kotler     break;
87107d3a2f6SReed Kotler   case Instruction::Xor:
87207d3a2f6SReed Kotler     ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1));
87307d3a2f6SReed Kotler     break;
87407d3a2f6SReed Kotler   }
87507d3a2f6SReed Kotler 
87607d3a2f6SReed Kotler   if (!ResultReg)
87707d3a2f6SReed Kotler     return false;
87807d3a2f6SReed Kotler 
87907d3a2f6SReed Kotler   updateValueMap(I, ResultReg);
88007d3a2f6SReed Kotler   return true;
88107d3a2f6SReed Kotler }
88207d3a2f6SReed Kotler 
selectLoad(const Instruction * I)883d4ea29e6SReed Kotler bool MipsFastISel::selectLoad(const Instruction *I) {
884d4ea29e6SReed Kotler   // Atomic loads need special handling.
885d4ea29e6SReed Kotler   if (cast<LoadInst>(I)->isAtomic())
886d4ea29e6SReed Kotler     return false;
887d4ea29e6SReed Kotler 
888d4ea29e6SReed Kotler   // Verify we have a legal type before going any further.
889d4ea29e6SReed Kotler   MVT VT;
890d4ea29e6SReed Kotler   if (!isLoadTypeLegal(I->getType(), VT))
891d4ea29e6SReed Kotler     return false;
892d4ea29e6SReed Kotler 
893d4ea29e6SReed Kotler   // See if we can handle this address.
894d4ea29e6SReed Kotler   Address Addr;
895d4ea29e6SReed Kotler   if (!computeAddress(I->getOperand(0), Addr))
896d4ea29e6SReed Kotler     return false;
897d4ea29e6SReed Kotler 
898d4ea29e6SReed Kotler   unsigned ResultReg;
899*310e3279SGuillaume Chatelet   if (!emitLoad(VT, ResultReg, Addr))
900d4ea29e6SReed Kotler     return false;
901d4ea29e6SReed Kotler   updateValueMap(I, ResultReg);
902d4ea29e6SReed Kotler   return true;
903d4ea29e6SReed Kotler }
904d4ea29e6SReed Kotler 
selectStore(const Instruction * I)905d4ea29e6SReed Kotler bool MipsFastISel::selectStore(const Instruction *I) {
906d4ea29e6SReed Kotler   Value *Op0 = I->getOperand(0);
907d4ea29e6SReed Kotler   unsigned SrcReg = 0;
908d4ea29e6SReed Kotler 
909d4ea29e6SReed Kotler   // Atomic stores need special handling.
910d4ea29e6SReed Kotler   if (cast<StoreInst>(I)->isAtomic())
911d4ea29e6SReed Kotler     return false;
912d4ea29e6SReed Kotler 
913d4ea29e6SReed Kotler   // Verify we have a legal type before going any further.
914d4ea29e6SReed Kotler   MVT VT;
915d4ea29e6SReed Kotler   if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
916d4ea29e6SReed Kotler     return false;
917d4ea29e6SReed Kotler 
918d4ea29e6SReed Kotler   // Get the value to be stored into a register.
919d4ea29e6SReed Kotler   SrcReg = getRegForValue(Op0);
920d4ea29e6SReed Kotler   if (SrcReg == 0)
921d4ea29e6SReed Kotler     return false;
922d4ea29e6SReed Kotler 
923d4ea29e6SReed Kotler   // See if we can handle this address.
924d4ea29e6SReed Kotler   Address Addr;
925d4ea29e6SReed Kotler   if (!computeAddress(I->getOperand(1), Addr))
926d4ea29e6SReed Kotler     return false;
927d4ea29e6SReed Kotler 
928*310e3279SGuillaume Chatelet   if (!emitStore(VT, SrcReg, Addr))
929d4ea29e6SReed Kotler     return false;
930d4ea29e6SReed Kotler   return true;
931d4ea29e6SReed Kotler }
932d4ea29e6SReed Kotler 
933d4ea29e6SReed Kotler // This can cause a redundant sltiu to be generated.
934d4ea29e6SReed Kotler // FIXME: try and eliminate this in a future patch.
selectBranch(const Instruction * I)935d4ea29e6SReed Kotler bool MipsFastISel::selectBranch(const Instruction *I) {
936d4ea29e6SReed Kotler   const BranchInst *BI = cast<BranchInst>(I);
937d4ea29e6SReed Kotler   MachineBasicBlock *BrBB = FuncInfo.MBB;
938d4ea29e6SReed Kotler   //
939d4ea29e6SReed Kotler   // TBB is the basic block for the case where the comparison is true.
940d4ea29e6SReed Kotler   // FBB is the basic block for the case where the comparison is false.
941d4ea29e6SReed Kotler   // if (cond) goto TBB
942d4ea29e6SReed Kotler   // goto FBB
943d4ea29e6SReed Kotler   // TBB:
944d4ea29e6SReed Kotler   //
945d4ea29e6SReed Kotler   MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)];
946d4ea29e6SReed Kotler   MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)];
947fcbd7f64SNikita Popov 
948fcbd7f64SNikita Popov   // Fold the common case of a conditional branch with a comparison
949fcbd7f64SNikita Popov   // in the same block.
950fcbd7f64SNikita Popov   unsigned ZExtCondReg = 0;
951d4ea29e6SReed Kotler   if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) {
952fcbd7f64SNikita Popov     if (CI->hasOneUse() && CI->getParent() == I->getParent()) {
953fcbd7f64SNikita Popov       ZExtCondReg = createResultReg(&Mips::GPR32RegClass);
954fcbd7f64SNikita Popov       if (!emitCmp(ZExtCondReg, CI))
955fcbd7f64SNikita Popov         return false;
956fcbd7f64SNikita Popov     }
957fcbd7f64SNikita Popov   }
958fcbd7f64SNikita Popov 
959fcbd7f64SNikita Popov   // For the general case, we need to mask with 1.
960fcbd7f64SNikita Popov   if (ZExtCondReg == 0) {
961d6b07348SJim Lin     Register CondReg = getRegForValue(BI->getCondition());
962fcbd7f64SNikita Popov     if (CondReg == 0)
963f9808c5fSPetar Jovanovic       return false;
964f9808c5fSPetar Jovanovic 
965fcbd7f64SNikita Popov     ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true);
966fcbd7f64SNikita Popov     if (ZExtCondReg == 0)
967fcbd7f64SNikita Popov       return false;
968fcbd7f64SNikita Popov   }
969fcbd7f64SNikita Popov 
970d4ea29e6SReed Kotler   BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ))
971fcbd7f64SNikita Popov       .addReg(ZExtCondReg)
972d4ea29e6SReed Kotler       .addMBB(TBB);
973ccfc9c8dSMatthias Braun   finishCondBranch(BI->getParent(), TBB, FBB);
974d4ea29e6SReed Kotler   return true;
975d4ea29e6SReed Kotler }
97662de6b96SReed Kotler 
selectCmp(const Instruction * I)977a562b46dSReed Kotler bool MipsFastISel::selectCmp(const Instruction *I) {
97862de6b96SReed Kotler   const CmpInst *CI = cast<CmpInst>(I);
979d6b07348SJim Lin   Register ResultReg = createResultReg(&Mips::GPR32RegClass);
980a562b46dSReed Kotler   if (!emitCmp(ResultReg, CI))
98162de6b96SReed Kotler     return false;
982497311abSReed Kotler   updateValueMap(I, ResultReg);
983497311abSReed Kotler   return true;
984497311abSReed Kotler }
985497311abSReed Kotler 
986d4ea29e6SReed Kotler // Attempt to fast-select a floating-point extend instruction.
selectFPExt(const Instruction * I)987d4ea29e6SReed Kotler bool MipsFastISel::selectFPExt(const Instruction *I) {
988d4ea29e6SReed Kotler   if (UnsupportedFPMode)
989d4ea29e6SReed Kotler     return false;
990d4ea29e6SReed Kotler   Value *Src = I->getOperand(0);
99144ede33aSMehdi Amini   EVT SrcVT = TLI.getValueType(DL, Src->getType(), true);
99244ede33aSMehdi Amini   EVT DestVT = TLI.getValueType(DL, I->getType(), true);
993d4ea29e6SReed Kotler 
994d4ea29e6SReed Kotler   if (SrcVT != MVT::f32 || DestVT != MVT::f64)
995d4ea29e6SReed Kotler     return false;
996d4ea29e6SReed Kotler 
997d6b07348SJim Lin   Register SrcReg =
9982cf5e89eSNico Weber       getRegForValue(Src); // this must be a 32bit floating point register class
999d4ea29e6SReed Kotler                            // maybe we should handle this differently
1000d4ea29e6SReed Kotler   if (!SrcReg)
1001d4ea29e6SReed Kotler     return false;
1002d4ea29e6SReed Kotler 
1003d6b07348SJim Lin   Register DestReg = createResultReg(&Mips::AFGR64RegClass);
1004d4ea29e6SReed Kotler   emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg);
1005d4ea29e6SReed Kotler   updateValueMap(I, DestReg);
1006d4ea29e6SReed Kotler   return true;
1007d4ea29e6SReed Kotler }
1008d4ea29e6SReed Kotler 
selectSelect(const Instruction * I)1009127f894bSVasileios Kalintiris bool MipsFastISel::selectSelect(const Instruction *I) {
1010127f894bSVasileios Kalintiris   assert(isa<SelectInst>(I) && "Expected a select instruction.");
1011127f894bSVasileios Kalintiris 
1012d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "selectSelect\n");
1013b432a3edSSimon Dardis 
1014127f894bSVasileios Kalintiris   MVT VT;
1015b432a3edSSimon Dardis   if (!isTypeSupported(I->getType(), VT) || UnsupportedFPMode) {
1016d34e60caSNicola Zaghen     LLVM_DEBUG(
1017d34e60caSNicola Zaghen         dbgs() << ".. .. gave up (!isTypeSupported || UnsupportedFPMode)\n");
1018127f894bSVasileios Kalintiris     return false;
1019b432a3edSSimon Dardis   }
1020127f894bSVasileios Kalintiris 
1021127f894bSVasileios Kalintiris   unsigned CondMovOpc;
1022127f894bSVasileios Kalintiris   const TargetRegisterClass *RC;
1023127f894bSVasileios Kalintiris 
1024127f894bSVasileios Kalintiris   if (VT.isInteger() && !VT.isVector() && VT.getSizeInBits() <= 32) {
1025127f894bSVasileios Kalintiris     CondMovOpc = Mips::MOVN_I_I;
1026127f894bSVasileios Kalintiris     RC = &Mips::GPR32RegClass;
1027127f894bSVasileios Kalintiris   } else if (VT == MVT::f32) {
1028127f894bSVasileios Kalintiris     CondMovOpc = Mips::MOVN_I_S;
1029127f894bSVasileios Kalintiris     RC = &Mips::FGR32RegClass;
1030127f894bSVasileios Kalintiris   } else if (VT == MVT::f64) {
1031127f894bSVasileios Kalintiris     CondMovOpc = Mips::MOVN_I_D32;
1032127f894bSVasileios Kalintiris     RC = &Mips::AFGR64RegClass;
1033127f894bSVasileios Kalintiris   } else
1034127f894bSVasileios Kalintiris     return false;
1035127f894bSVasileios Kalintiris 
1036127f894bSVasileios Kalintiris   const SelectInst *SI = cast<SelectInst>(I);
1037127f894bSVasileios Kalintiris   const Value *Cond = SI->getCondition();
1038d6b07348SJim Lin   Register Src1Reg = getRegForValue(SI->getTrueValue());
1039d6b07348SJim Lin   Register Src2Reg = getRegForValue(SI->getFalseValue());
1040d6b07348SJim Lin   Register CondReg = getRegForValue(Cond);
1041127f894bSVasileios Kalintiris 
1042127f894bSVasileios Kalintiris   if (!Src1Reg || !Src2Reg || !CondReg)
1043127f894bSVasileios Kalintiris     return false;
1044127f894bSVasileios Kalintiris 
1045d6b07348SJim Lin   Register ZExtCondReg = createResultReg(&Mips::GPR32RegClass);
10469ec61148SVasileios Kalintiris   if (!ZExtCondReg)
10479ec61148SVasileios Kalintiris     return false;
10489ec61148SVasileios Kalintiris 
10499ec61148SVasileios Kalintiris   if (!emitIntExt(MVT::i1, CondReg, MVT::i32, ZExtCondReg, true))
10509ec61148SVasileios Kalintiris     return false;
10519ec61148SVasileios Kalintiris 
1052d6b07348SJim Lin   Register ResultReg = createResultReg(RC);
1053d6b07348SJim Lin   Register TempReg = createResultReg(RC);
1054127f894bSVasileios Kalintiris 
1055127f894bSVasileios Kalintiris   if (!ResultReg || !TempReg)
1056127f894bSVasileios Kalintiris     return false;
1057127f894bSVasileios Kalintiris 
1058127f894bSVasileios Kalintiris   emitInst(TargetOpcode::COPY, TempReg).addReg(Src2Reg);
1059127f894bSVasileios Kalintiris   emitInst(CondMovOpc, ResultReg)
10609ec61148SVasileios Kalintiris     .addReg(Src1Reg).addReg(ZExtCondReg).addReg(TempReg);
1061127f894bSVasileios Kalintiris   updateValueMap(I, ResultReg);
1062127f894bSVasileios Kalintiris   return true;
1063127f894bSVasileios Kalintiris }
1064127f894bSVasileios Kalintiris 
1065d4ea29e6SReed Kotler // Attempt to fast-select a floating-point truncate instruction.
selectFPTrunc(const Instruction * I)1066d4ea29e6SReed Kotler bool MipsFastISel::selectFPTrunc(const Instruction *I) {
1067d4ea29e6SReed Kotler   if (UnsupportedFPMode)
1068d4ea29e6SReed Kotler     return false;
1069d4ea29e6SReed Kotler   Value *Src = I->getOperand(0);
107044ede33aSMehdi Amini   EVT SrcVT = TLI.getValueType(DL, Src->getType(), true);
107144ede33aSMehdi Amini   EVT DestVT = TLI.getValueType(DL, I->getType(), true);
1072d4ea29e6SReed Kotler 
1073d4ea29e6SReed Kotler   if (SrcVT != MVT::f64 || DestVT != MVT::f32)
1074d4ea29e6SReed Kotler     return false;
1075d4ea29e6SReed Kotler 
1076d6b07348SJim Lin   Register SrcReg = getRegForValue(Src);
1077d4ea29e6SReed Kotler   if (!SrcReg)
1078d4ea29e6SReed Kotler     return false;
1079d4ea29e6SReed Kotler 
1080d6b07348SJim Lin   Register DestReg = createResultReg(&Mips::FGR32RegClass);
1081d4ea29e6SReed Kotler   if (!DestReg)
1082d4ea29e6SReed Kotler     return false;
1083d4ea29e6SReed Kotler 
1084d4ea29e6SReed Kotler   emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg);
1085d4ea29e6SReed Kotler   updateValueMap(I, DestReg);
1086d4ea29e6SReed Kotler   return true;
1087d4ea29e6SReed Kotler }
1088d4ea29e6SReed Kotler 
1089d4ea29e6SReed Kotler // Attempt to fast-select a floating-point-to-integer conversion.
selectFPToInt(const Instruction * I,bool IsSigned)1090d4ea29e6SReed Kotler bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) {
1091d4ea29e6SReed Kotler   if (UnsupportedFPMode)
1092d4ea29e6SReed Kotler     return false;
1093d4ea29e6SReed Kotler   MVT DstVT, SrcVT;
1094d4ea29e6SReed Kotler   if (!IsSigned)
1095d4ea29e6SReed Kotler     return false; // We don't handle this case yet. There is no native
1096d4ea29e6SReed Kotler                   // instruction for this but it can be synthesized.
1097d4ea29e6SReed Kotler   Type *DstTy = I->getType();
1098d4ea29e6SReed Kotler   if (!isTypeLegal(DstTy, DstVT))
1099d4ea29e6SReed Kotler     return false;
1100d4ea29e6SReed Kotler 
1101d4ea29e6SReed Kotler   if (DstVT != MVT::i32)
1102d4ea29e6SReed Kotler     return false;
1103d4ea29e6SReed Kotler 
1104d4ea29e6SReed Kotler   Value *Src = I->getOperand(0);
1105d4ea29e6SReed Kotler   Type *SrcTy = Src->getType();
1106d4ea29e6SReed Kotler   if (!isTypeLegal(SrcTy, SrcVT))
1107d4ea29e6SReed Kotler     return false;
1108d4ea29e6SReed Kotler 
1109d4ea29e6SReed Kotler   if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
1110d4ea29e6SReed Kotler     return false;
1111d4ea29e6SReed Kotler 
1112d6b07348SJim Lin   Register SrcReg = getRegForValue(Src);
1113d4ea29e6SReed Kotler   if (SrcReg == 0)
1114d4ea29e6SReed Kotler     return false;
1115d4ea29e6SReed Kotler 
1116d4ea29e6SReed Kotler   // Determine the opcode for the conversion, which takes place
1117d4ea29e6SReed Kotler   // entirely within FPRs.
1118d6b07348SJim Lin   Register DestReg = createResultReg(&Mips::GPR32RegClass);
1119d6b07348SJim Lin   Register TempReg = createResultReg(&Mips::FGR32RegClass);
11206ae1b35cSVasileios Kalintiris   unsigned Opc = (SrcVT == MVT::f32) ? Mips::TRUNC_W_S : Mips::TRUNC_W_D32;
1121d4ea29e6SReed Kotler 
1122d4ea29e6SReed Kotler   // Generate the convert.
1123d4ea29e6SReed Kotler   emitInst(Opc, TempReg).addReg(SrcReg);
1124d4ea29e6SReed Kotler   emitInst(Mips::MFC1, DestReg).addReg(TempReg);
1125d4ea29e6SReed Kotler 
1126d4ea29e6SReed Kotler   updateValueMap(I, DestReg);
1127d4ea29e6SReed Kotler   return true;
1128d4ea29e6SReed Kotler }
11296ae1b35cSVasileios Kalintiris 
processCallArgs(CallLoweringInfo & CLI,SmallVectorImpl<MVT> & OutVTs,unsigned & NumBytes)1130d5c4196cSReed Kotler bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI,
1131d5c4196cSReed Kotler                                    SmallVectorImpl<MVT> &OutVTs,
1132d5c4196cSReed Kotler                                    unsigned &NumBytes) {
1133d5c4196cSReed Kotler   CallingConv::ID CC = CLI.CallConv;
1134d5c4196cSReed Kotler   SmallVector<CCValAssign, 16> ArgLocs;
1135d5c4196cSReed Kotler   CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context);
1136d5c4196cSReed Kotler   CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC));
1137d5c4196cSReed Kotler   // Get a count of how many bytes are to be pushed on the stack.
1138d5c4196cSReed Kotler   NumBytes = CCInfo.getNextStackOffset();
1139d5c4196cSReed Kotler   // This is the minimum argument area used for A0-A3.
1140d5c4196cSReed Kotler   if (NumBytes < 16)
1141d5c4196cSReed Kotler     NumBytes = 16;
1142d5c4196cSReed Kotler 
1143d526b13eSSerge Pavlov   emitInst(Mips::ADJCALLSTACKDOWN).addImm(16).addImm(0);
1144d5c4196cSReed Kotler   // Process the args.
1145d5c4196cSReed Kotler   MVT firstMVT;
1146d5c4196cSReed Kotler   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1147d5c4196cSReed Kotler     CCValAssign &VA = ArgLocs[i];
1148d5c4196cSReed Kotler     const Value *ArgVal = CLI.OutVals[VA.getValNo()];
1149d5c4196cSReed Kotler     MVT ArgVT = OutVTs[VA.getValNo()];
1150d5c4196cSReed Kotler 
1151d5c4196cSReed Kotler     if (i == 0) {
1152d5c4196cSReed Kotler       firstMVT = ArgVT;
1153d5c4196cSReed Kotler       if (ArgVT == MVT::f32) {
1154d5c4196cSReed Kotler         VA.convertToReg(Mips::F12);
1155d5c4196cSReed Kotler       } else if (ArgVT == MVT::f64) {
1156242c5a70SSimon Atanasyan         if (Subtarget->isFP64bit())
1157242c5a70SSimon Atanasyan           VA.convertToReg(Mips::D6_64);
1158242c5a70SSimon Atanasyan         else
1159d5c4196cSReed Kotler           VA.convertToReg(Mips::D6);
1160d5c4196cSReed Kotler       }
1161d5c4196cSReed Kotler     } else if (i == 1) {
1162d5c4196cSReed Kotler       if ((firstMVT == MVT::f32) || (firstMVT == MVT::f64)) {
1163d5c4196cSReed Kotler         if (ArgVT == MVT::f32) {
1164d5c4196cSReed Kotler           VA.convertToReg(Mips::F14);
1165d5c4196cSReed Kotler         } else if (ArgVT == MVT::f64) {
1166242c5a70SSimon Atanasyan           if (Subtarget->isFP64bit())
1167242c5a70SSimon Atanasyan             VA.convertToReg(Mips::D7_64);
1168242c5a70SSimon Atanasyan           else
1169d5c4196cSReed Kotler             VA.convertToReg(Mips::D7);
1170d5c4196cSReed Kotler         }
1171d5c4196cSReed Kotler       }
1172d5c4196cSReed Kotler     }
1173b48c9056SVasileios Kalintiris     if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32) || (ArgVT == MVT::i16) ||
1174b48c9056SVasileios Kalintiris          (ArgVT == MVT::i8)) &&
1175b48c9056SVasileios Kalintiris         VA.isMemLoc()) {
1176d5c4196cSReed Kotler       switch (VA.getLocMemOffset()) {
1177d5c4196cSReed Kotler       case 0:
1178d5c4196cSReed Kotler         VA.convertToReg(Mips::A0);
1179d5c4196cSReed Kotler         break;
1180d5c4196cSReed Kotler       case 4:
1181d5c4196cSReed Kotler         VA.convertToReg(Mips::A1);
1182d5c4196cSReed Kotler         break;
1183d5c4196cSReed Kotler       case 8:
1184d5c4196cSReed Kotler         VA.convertToReg(Mips::A2);
1185d5c4196cSReed Kotler         break;
1186d5c4196cSReed Kotler       case 12:
1187d5c4196cSReed Kotler         VA.convertToReg(Mips::A3);
1188d5c4196cSReed Kotler         break;
1189d5c4196cSReed Kotler       default:
1190d5c4196cSReed Kotler         break;
1191d5c4196cSReed Kotler       }
1192d5c4196cSReed Kotler     }
1193d6b07348SJim Lin     Register ArgReg = getRegForValue(ArgVal);
1194d5c4196cSReed Kotler     if (!ArgReg)
1195d5c4196cSReed Kotler       return false;
1196d5c4196cSReed Kotler 
1197d5c4196cSReed Kotler     // Handle arg promotion: SExt, ZExt, AExt.
1198d5c4196cSReed Kotler     switch (VA.getLocInfo()) {
1199d5c4196cSReed Kotler     case CCValAssign::Full:
1200d5c4196cSReed Kotler       break;
1201d5c4196cSReed Kotler     case CCValAssign::AExt:
1202d5c4196cSReed Kotler     case CCValAssign::SExt: {
1203d5c4196cSReed Kotler       MVT DestVT = VA.getLocVT();
1204d5c4196cSReed Kotler       MVT SrcVT = ArgVT;
1205d5c4196cSReed Kotler       ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false);
1206d5c4196cSReed Kotler       if (!ArgReg)
1207d5c4196cSReed Kotler         return false;
1208d5c4196cSReed Kotler       break;
1209d5c4196cSReed Kotler     }
1210d5c4196cSReed Kotler     case CCValAssign::ZExt: {
1211d5c4196cSReed Kotler       MVT DestVT = VA.getLocVT();
1212d5c4196cSReed Kotler       MVT SrcVT = ArgVT;
1213d5c4196cSReed Kotler       ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true);
1214d5c4196cSReed Kotler       if (!ArgReg)
1215d5c4196cSReed Kotler         return false;
1216d5c4196cSReed Kotler       break;
1217d5c4196cSReed Kotler     }
1218d5c4196cSReed Kotler     default:
1219d5c4196cSReed Kotler       llvm_unreachable("Unknown arg promotion!");
1220d5c4196cSReed Kotler     }
1221d5c4196cSReed Kotler 
1222d5c4196cSReed Kotler     // Now copy/store arg to correct locations.
1223d5c4196cSReed Kotler     if (VA.isRegLoc() && !VA.needsCustom()) {
1224d5c4196cSReed Kotler       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1225d5c4196cSReed Kotler               TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg);
1226d5c4196cSReed Kotler       CLI.OutRegs.push_back(VA.getLocReg());
1227d5c4196cSReed Kotler     } else if (VA.needsCustom()) {
1228d5c4196cSReed Kotler       llvm_unreachable("Mips does not use custom args.");
1229d5c4196cSReed Kotler       return false;
1230d5c4196cSReed Kotler     } else {
1231d5c4196cSReed Kotler       //
1232d5c4196cSReed Kotler       // FIXME: This path will currently return false. It was copied
1233d5c4196cSReed Kotler       // from the AArch64 port and should be essentially fine for Mips too.
1234d5c4196cSReed Kotler       // The work to finish up this path will be done in a follow-on patch.
1235d5c4196cSReed Kotler       //
1236d5c4196cSReed Kotler       assert(VA.isMemLoc() && "Assuming store on stack.");
1237d5c4196cSReed Kotler       // Don't emit stores for undef values.
1238d5c4196cSReed Kotler       if (isa<UndefValue>(ArgVal))
1239d5c4196cSReed Kotler         continue;
1240d5c4196cSReed Kotler 
1241d5c4196cSReed Kotler       // Need to store on the stack.
1242d5c4196cSReed Kotler       // FIXME: This alignment is incorrect but this path is disabled
1243d5c4196cSReed Kotler       // for now (will return false). We need to determine the right alignment
1244d5c4196cSReed Kotler       // based on the normal alignment for the underlying machine type.
1245d5c4196cSReed Kotler       //
1246da00f2fdSRui Ueyama       unsigned ArgSize = alignTo(ArgVT.getSizeInBits(), 4);
1247d5c4196cSReed Kotler 
1248d5c4196cSReed Kotler       unsigned BEAlign = 0;
1249d5c4196cSReed Kotler       if (ArgSize < 8 && !Subtarget->isLittle())
1250d5c4196cSReed Kotler         BEAlign = 8 - ArgSize;
1251d5c4196cSReed Kotler 
1252d5c4196cSReed Kotler       Address Addr;
1253d5c4196cSReed Kotler       Addr.setKind(Address::RegBase);
1254d5c4196cSReed Kotler       Addr.setReg(Mips::SP);
1255d5c4196cSReed Kotler       Addr.setOffset(VA.getLocMemOffset() + BEAlign);
1256d5c4196cSReed Kotler 
1257c9d5c195SGuillaume Chatelet       Align Alignment = DL.getABITypeAlign(ArgVal->getType());
1258d5c4196cSReed Kotler       MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
1259e40c8a2bSAlex Lorenz           MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()),
1260d5c4196cSReed Kotler           MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment);
1261d5c4196cSReed Kotler       (void)(MMO);
1262d5c4196cSReed Kotler       // if (!emitStore(ArgVT, ArgReg, Addr, MMO))
1263d5c4196cSReed Kotler       return false; // can't store on the stack yet.
1264d5c4196cSReed Kotler     }
1265d5c4196cSReed Kotler   }
1266d5c4196cSReed Kotler 
1267d5c4196cSReed Kotler   return true;
1268d5c4196cSReed Kotler }
1269d5c4196cSReed Kotler 
finishCall(CallLoweringInfo & CLI,MVT RetVT,unsigned NumBytes)1270d5c4196cSReed Kotler bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT,
1271d5c4196cSReed Kotler                               unsigned NumBytes) {
1272d5c4196cSReed Kotler   CallingConv::ID CC = CLI.CallConv;
127301bcefd9SDaniel Sanders   emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0);
1274d5c4196cSReed Kotler   if (RetVT != MVT::isVoid) {
1275d5c4196cSReed Kotler     SmallVector<CCValAssign, 16> RVLocs;
127670f79251SSimon Dardis     MipsCCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
127770f79251SSimon Dardis 
127870f79251SSimon Dardis     CCInfo.AnalyzeCallResult(CLI.Ins, RetCC_Mips, CLI.RetTy,
12799d580e85SSimon Dardis                              CLI.Symbol ? CLI.Symbol->getName().data()
12809d580e85SSimon Dardis                                         : nullptr);
1281d5c4196cSReed Kotler 
1282d5c4196cSReed Kotler     // Only handle a single return value.
1283d5c4196cSReed Kotler     if (RVLocs.size() != 1)
1284d5c4196cSReed Kotler       return false;
1285d5c4196cSReed Kotler     // Copy all of the result registers out of their specified physreg.
1286d5c4196cSReed Kotler     MVT CopyVT = RVLocs[0].getValVT();
1287d5c4196cSReed Kotler     // Special handling for extended integers.
1288d5c4196cSReed Kotler     if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16)
1289d5c4196cSReed Kotler       CopyVT = MVT::i32;
1290d5c4196cSReed Kotler 
1291d6b07348SJim Lin     Register ResultReg = createResultReg(TLI.getRegClassFor(CopyVT));
12921249e746SVasileios Kalintiris     if (!ResultReg)
12931249e746SVasileios Kalintiris       return false;
1294d5c4196cSReed Kotler     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1295d5c4196cSReed Kotler             TII.get(TargetOpcode::COPY),
1296d5c4196cSReed Kotler             ResultReg).addReg(RVLocs[0].getLocReg());
1297d5c4196cSReed Kotler     CLI.InRegs.push_back(RVLocs[0].getLocReg());
1298d5c4196cSReed Kotler 
1299d5c4196cSReed Kotler     CLI.ResultReg = ResultReg;
1300d5c4196cSReed Kotler     CLI.NumResultRegs = 1;
1301d5c4196cSReed Kotler   }
1302d5c4196cSReed Kotler   return true;
1303d5c4196cSReed Kotler }
1304d5c4196cSReed Kotler 
fastLowerArguments()1305cbaca42aSDaniel Sanders bool MipsFastISel::fastLowerArguments() {
1306d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "fastLowerArguments\n");
1307cbaca42aSDaniel Sanders 
1308cbaca42aSDaniel Sanders   if (!FuncInfo.CanLowerReturn) {
1309d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << ".. gave up (!CanLowerReturn)\n");
1310cbaca42aSDaniel Sanders     return false;
1311cbaca42aSDaniel Sanders   }
1312cbaca42aSDaniel Sanders 
1313cbaca42aSDaniel Sanders   const Function *F = FuncInfo.Fn;
1314cbaca42aSDaniel Sanders   if (F->isVarArg()) {
1315d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << ".. gave up (varargs)\n");
1316cbaca42aSDaniel Sanders     return false;
1317cbaca42aSDaniel Sanders   }
1318cbaca42aSDaniel Sanders 
1319cbaca42aSDaniel Sanders   CallingConv::ID CC = F->getCallingConv();
1320cbaca42aSDaniel Sanders   if (CC != CallingConv::C) {
1321d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << ".. gave up (calling convention is not C)\n");
1322cbaca42aSDaniel Sanders     return false;
1323cbaca42aSDaniel Sanders   }
1324cbaca42aSDaniel Sanders 
1325afb355bdSManoj Gupta   std::array<MCPhysReg, 4> GPR32ArgRegs = {{Mips::A0, Mips::A1, Mips::A2,
1326afb355bdSManoj Gupta                                            Mips::A3}};
1327afb355bdSManoj Gupta   std::array<MCPhysReg, 2> FGR32ArgRegs = {{Mips::F12, Mips::F14}};
1328afb355bdSManoj Gupta   std::array<MCPhysReg, 2> AFGR64ArgRegs = {{Mips::D6, Mips::D7}};
13299d68b9eaSManoj Gupta   auto NextGPR32 = GPR32ArgRegs.begin();
13309d68b9eaSManoj Gupta   auto NextFGR32 = FGR32ArgRegs.begin();
13319d68b9eaSManoj Gupta   auto NextAFGR64 = AFGR64ArgRegs.begin();
1332cbaca42aSDaniel Sanders 
1333cbaca42aSDaniel Sanders   struct AllocatedReg {
1334cbaca42aSDaniel Sanders     const TargetRegisterClass *RC;
1335cbaca42aSDaniel Sanders     unsigned Reg;
1336cbaca42aSDaniel Sanders     AllocatedReg(const TargetRegisterClass *RC, unsigned Reg)
1337cbaca42aSDaniel Sanders         : RC(RC), Reg(Reg) {}
1338cbaca42aSDaniel Sanders   };
1339cbaca42aSDaniel Sanders 
1340b3ae33c7SDaniel Sanders   // Only handle simple cases. i.e. All arguments are directly mapped to
1341b3ae33c7SDaniel Sanders   // registers of the appropriate type.
1342cbaca42aSDaniel Sanders   SmallVector<AllocatedReg, 4> Allocation;
1343cbaca42aSDaniel Sanders   for (const auto &FormalArg : F->args()) {
13446652a52eSReid Kleckner     if (FormalArg.hasAttribute(Attribute::InReg) ||
13456652a52eSReid Kleckner         FormalArg.hasAttribute(Attribute::StructRet) ||
13466652a52eSReid Kleckner         FormalArg.hasAttribute(Attribute::ByVal)) {
1347d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n");
1348cbaca42aSDaniel Sanders       return false;
1349cbaca42aSDaniel Sanders     }
1350cbaca42aSDaniel Sanders 
1351cbaca42aSDaniel Sanders     Type *ArgTy = FormalArg.getType();
1352cbaca42aSDaniel Sanders     if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy()) {
1353d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. gave up (struct, array, or vector)\n");
1354cbaca42aSDaniel Sanders       return false;
1355cbaca42aSDaniel Sanders     }
1356cbaca42aSDaniel Sanders 
1357cbaca42aSDaniel Sanders     EVT ArgVT = TLI.getValueType(DL, ArgTy);
1358d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": "
13596652a52eSReid Kleckner                       << ArgVT.getEVTString() << "\n");
1360cbaca42aSDaniel Sanders     if (!ArgVT.isSimple()) {
1361d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. gave up (not a simple type)\n");
1362cbaca42aSDaniel Sanders       return false;
1363cbaca42aSDaniel Sanders     }
1364cbaca42aSDaniel Sanders 
1365cbaca42aSDaniel Sanders     switch (ArgVT.getSimpleVT().SimpleTy) {
1366cbaca42aSDaniel Sanders     case MVT::i1:
1367cbaca42aSDaniel Sanders     case MVT::i8:
1368cbaca42aSDaniel Sanders     case MVT::i16:
13696652a52eSReid Kleckner       if (!FormalArg.hasAttribute(Attribute::SExt) &&
13706652a52eSReid Kleckner           !FormalArg.hasAttribute(Attribute::ZExt)) {
1371cbaca42aSDaniel Sanders         // It must be any extend, this shouldn't happen for clang-generated IR
1372cbaca42aSDaniel Sanders         // so just fall back on SelectionDAG.
1373d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n");
1374cbaca42aSDaniel Sanders         return false;
1375cbaca42aSDaniel Sanders       }
1376b3ae33c7SDaniel Sanders 
1377b3ae33c7SDaniel Sanders       if (NextGPR32 == GPR32ArgRegs.end()) {
1378d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n");
1379b3ae33c7SDaniel Sanders         return false;
1380b3ae33c7SDaniel Sanders       }
1381b3ae33c7SDaniel Sanders 
1382d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n");
1383b3ae33c7SDaniel Sanders       Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++);
1384b3ae33c7SDaniel Sanders 
1385b3ae33c7SDaniel Sanders       // Allocating any GPR32 prohibits further use of floating point arguments.
1386b3ae33c7SDaniel Sanders       NextFGR32 = FGR32ArgRegs.end();
1387b3ae33c7SDaniel Sanders       NextAFGR64 = AFGR64ArgRegs.end();
1388cbaca42aSDaniel Sanders       break;
1389cbaca42aSDaniel Sanders 
1390cbaca42aSDaniel Sanders     case MVT::i32:
13916652a52eSReid Kleckner       if (FormalArg.hasAttribute(Attribute::ZExt)) {
1392cbaca42aSDaniel Sanders         // The O32 ABI does not permit a zero-extended i32.
1393d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n");
1394cbaca42aSDaniel Sanders         return false;
1395cbaca42aSDaniel Sanders       }
1396b3ae33c7SDaniel Sanders 
1397b3ae33c7SDaniel Sanders       if (NextGPR32 == GPR32ArgRegs.end()) {
1398d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n");
1399b3ae33c7SDaniel Sanders         return false;
1400b3ae33c7SDaniel Sanders       }
1401b3ae33c7SDaniel Sanders 
1402d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n");
1403b3ae33c7SDaniel Sanders       Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++);
1404b3ae33c7SDaniel Sanders 
1405b3ae33c7SDaniel Sanders       // Allocating any GPR32 prohibits further use of floating point arguments.
1406b3ae33c7SDaniel Sanders       NextFGR32 = FGR32ArgRegs.end();
1407b3ae33c7SDaniel Sanders       NextAFGR64 = AFGR64ArgRegs.end();
1408cbaca42aSDaniel Sanders       break;
1409cbaca42aSDaniel Sanders 
1410cbaca42aSDaniel Sanders     case MVT::f32:
141186b3a1e7SSimon Dardis       if (UnsupportedFPMode) {
1412d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n");
141386b3a1e7SSimon Dardis         return false;
141486b3a1e7SSimon Dardis       }
1415b3ae33c7SDaniel Sanders       if (NextFGR32 == FGR32ArgRegs.end()) {
1416d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n");
1417cbaca42aSDaniel Sanders         return false;
1418cbaca42aSDaniel Sanders       }
1419d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n");
1420b3ae33c7SDaniel Sanders       Allocation.emplace_back(&Mips::FGR32RegClass, *NextFGR32++);
1421b3ae33c7SDaniel Sanders       // Allocating an FGR32 also allocates the super-register AFGR64, and
1422b3ae33c7SDaniel Sanders       // ABI rules require us to skip the corresponding GPR32.
1423b3ae33c7SDaniel Sanders       if (NextGPR32 != GPR32ArgRegs.end())
1424b3ae33c7SDaniel Sanders         NextGPR32++;
1425b3ae33c7SDaniel Sanders       if (NextAFGR64 != AFGR64ArgRegs.end())
1426b3ae33c7SDaniel Sanders         NextAFGR64++;
1427cbaca42aSDaniel Sanders       break;
1428cbaca42aSDaniel Sanders 
1429cbaca42aSDaniel Sanders     case MVT::f64:
1430b432a3edSSimon Dardis       if (UnsupportedFPMode) {
1431d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n");
1432b432a3edSSimon Dardis         return false;
1433b432a3edSSimon Dardis       }
1434b3ae33c7SDaniel Sanders       if (NextAFGR64 == AFGR64ArgRegs.end()) {
1435d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n");
1436cbaca42aSDaniel Sanders         return false;
1437cbaca42aSDaniel Sanders       }
1438d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n");
1439b3ae33c7SDaniel Sanders       Allocation.emplace_back(&Mips::AFGR64RegClass, *NextAFGR64++);
1440b3ae33c7SDaniel Sanders       // Allocating an FGR32 also allocates the super-register AFGR64, and
1441b3ae33c7SDaniel Sanders       // ABI rules require us to skip the corresponding GPR32 pair.
1442b3ae33c7SDaniel Sanders       if (NextGPR32 != GPR32ArgRegs.end())
1443b3ae33c7SDaniel Sanders         NextGPR32++;
1444b3ae33c7SDaniel Sanders       if (NextGPR32 != GPR32ArgRegs.end())
1445b3ae33c7SDaniel Sanders         NextGPR32++;
1446b3ae33c7SDaniel Sanders       if (NextFGR32 != FGR32ArgRegs.end())
1447b3ae33c7SDaniel Sanders         NextFGR32++;
1448cbaca42aSDaniel Sanders       break;
1449cbaca42aSDaniel Sanders 
1450cbaca42aSDaniel Sanders     default:
1451d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. gave up (unknown type)\n");
1452cbaca42aSDaniel Sanders       return false;
1453cbaca42aSDaniel Sanders     }
1454cbaca42aSDaniel Sanders   }
1455cbaca42aSDaniel Sanders 
1456cbaca42aSDaniel Sanders   for (const auto &FormalArg : F->args()) {
14576652a52eSReid Kleckner     unsigned ArgNo = FormalArg.getArgNo();
14586652a52eSReid Kleckner     unsigned SrcReg = Allocation[ArgNo].Reg;
1459d6b07348SJim Lin     Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, Allocation[ArgNo].RC);
1460cbaca42aSDaniel Sanders     // FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
1461cbaca42aSDaniel Sanders     // Without this, EmitLiveInCopies may eliminate the livein if its only
1462cbaca42aSDaniel Sanders     // use is a bitcast (which isn't turned into an instruction).
1463d6b07348SJim Lin     Register ResultReg = createResultReg(Allocation[ArgNo].RC);
1464cbaca42aSDaniel Sanders     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1465cbaca42aSDaniel Sanders             TII.get(TargetOpcode::COPY), ResultReg)
1466cbaca42aSDaniel Sanders         .addReg(DstReg, getKillRegState(true));
1467cbaca42aSDaniel Sanders     updateValueMap(&FormalArg, ResultReg);
1468cbaca42aSDaniel Sanders   }
1469cbaca42aSDaniel Sanders 
1470cbaca42aSDaniel Sanders   // Calculate the size of the incoming arguments area.
1471cbaca42aSDaniel Sanders   // We currently reject all the cases where this would be non-zero.
1472cbaca42aSDaniel Sanders   unsigned IncomingArgSizeInBytes = 0;
1473cbaca42aSDaniel Sanders 
1474cbaca42aSDaniel Sanders   // Account for the reserved argument area on ABI's that have one (O32).
1475cbaca42aSDaniel Sanders   // It seems strange to do this on the caller side but it's necessary in
1476cbaca42aSDaniel Sanders   // SelectionDAG's implementation.
1477cbaca42aSDaniel Sanders   IncomingArgSizeInBytes = std::min(getABI().GetCalleeAllocdArgSizeInBytes(CC),
1478cbaca42aSDaniel Sanders                                     IncomingArgSizeInBytes);
1479cbaca42aSDaniel Sanders 
1480cbaca42aSDaniel Sanders   MF->getInfo<MipsFunctionInfo>()->setFormalArgInfo(IncomingArgSizeInBytes,
1481cbaca42aSDaniel Sanders                                                     false);
1482cbaca42aSDaniel Sanders 
1483cbaca42aSDaniel Sanders   return true;
1484cbaca42aSDaniel Sanders }
1485cbaca42aSDaniel Sanders 
fastLowerCall(CallLoweringInfo & CLI)1486d5c4196cSReed Kotler bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) {
1487d5c4196cSReed Kotler   CallingConv::ID CC = CLI.CallConv;
1488d5c4196cSReed Kotler   bool IsTailCall = CLI.IsTailCall;
1489d5c4196cSReed Kotler   bool IsVarArg = CLI.IsVarArg;
1490d5c4196cSReed Kotler   const Value *Callee = CLI.Callee;
1491ce4c2bc1SRafael Espindola   MCSymbol *Symbol = CLI.Symbol;
1492d5c4196cSReed Kotler 
14939876946aSVasileios Kalintiris   // Do not handle FastCC.
14949876946aSVasileios Kalintiris   if (CC == CallingConv::Fast)
14959876946aSVasileios Kalintiris     return false;
14969876946aSVasileios Kalintiris 
1497d5c4196cSReed Kotler   // Allow SelectionDAG isel to handle tail calls.
1498d5c4196cSReed Kotler   if (IsTailCall)
1499d5c4196cSReed Kotler     return false;
1500d5c4196cSReed Kotler 
1501d5c4196cSReed Kotler   // Let SDISel handle vararg functions.
1502d5c4196cSReed Kotler   if (IsVarArg)
1503d5c4196cSReed Kotler     return false;
1504d5c4196cSReed Kotler 
1505d5c4196cSReed Kotler   // FIXME: Only handle *simple* calls for now.
1506d5c4196cSReed Kotler   MVT RetVT;
1507d5c4196cSReed Kotler   if (CLI.RetTy->isVoidTy())
1508d5c4196cSReed Kotler     RetVT = MVT::isVoid;
15091249e746SVasileios Kalintiris   else if (!isTypeSupported(CLI.RetTy, RetVT))
1510d5c4196cSReed Kotler     return false;
1511d5c4196cSReed Kotler 
1512d5c4196cSReed Kotler   for (auto Flag : CLI.OutFlags)
1513d5c4196cSReed Kotler     if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal())
1514d5c4196cSReed Kotler       return false;
1515d5c4196cSReed Kotler 
1516d5c4196cSReed Kotler   // Set up the argument vectors.
1517d5c4196cSReed Kotler   SmallVector<MVT, 16> OutVTs;
1518d5c4196cSReed Kotler   OutVTs.reserve(CLI.OutVals.size());
1519d5c4196cSReed Kotler 
1520d5c4196cSReed Kotler   for (auto *Val : CLI.OutVals) {
1521d5c4196cSReed Kotler     MVT VT;
1522d5c4196cSReed Kotler     if (!isTypeLegal(Val->getType(), VT) &&
1523d5c4196cSReed Kotler         !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16))
1524d5c4196cSReed Kotler       return false;
1525d5c4196cSReed Kotler 
1526d5c4196cSReed Kotler     // We don't handle vector parameters yet.
1527d5c4196cSReed Kotler     if (VT.isVector() || VT.getSizeInBits() > 64)
1528d5c4196cSReed Kotler       return false;
1529d5c4196cSReed Kotler 
1530d5c4196cSReed Kotler     OutVTs.push_back(VT);
1531d5c4196cSReed Kotler   }
1532d5c4196cSReed Kotler 
1533d5c4196cSReed Kotler   Address Addr;
1534d5c4196cSReed Kotler   if (!computeCallAddress(Callee, Addr))
1535d5c4196cSReed Kotler     return false;
1536d5c4196cSReed Kotler 
1537d5c4196cSReed Kotler   // Handle the arguments now that we've gotten them.
1538d5c4196cSReed Kotler   unsigned NumBytes;
1539d5c4196cSReed Kotler   if (!processCallArgs(CLI, OutVTs, NumBytes))
1540d5c4196cSReed Kotler     return false;
1541d5c4196cSReed Kotler 
1542bdb91b31SVasileios Kalintiris   if (!Addr.getGlobalValue())
1543bdb91b31SVasileios Kalintiris     return false;
1544bdb91b31SVasileios Kalintiris 
1545d5c4196cSReed Kotler   // Issue the call.
1546bdb91b31SVasileios Kalintiris   unsigned DestAddress;
1547ce4c2bc1SRafael Espindola   if (Symbol)
1548ce4c2bc1SRafael Espindola     DestAddress = materializeExternalCallSym(Symbol);
1549bdb91b31SVasileios Kalintiris   else
1550bdb91b31SVasileios Kalintiris     DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32);
1551d5c4196cSReed Kotler   emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress);
1552d5c4196cSReed Kotler   MachineInstrBuilder MIB =
1553d5c4196cSReed Kotler       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR),
1554d5c4196cSReed Kotler               Mips::RA).addReg(Mips::T9);
1555d5c4196cSReed Kotler 
1556d5c4196cSReed Kotler   // Add implicit physical register uses to the call.
1557d5c4196cSReed Kotler   for (auto Reg : CLI.OutRegs)
1558d5c4196cSReed Kotler     MIB.addReg(Reg, RegState::Implicit);
1559d5c4196cSReed Kotler 
1560d5c4196cSReed Kotler   // Add a register mask with the call-preserved registers.
1561d5c4196cSReed Kotler   // Proper defs for return values will be added by setPhysRegsDeadExcept().
15629deb75d1SEric Christopher   MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC));
1563d5c4196cSReed Kotler 
1564d5c4196cSReed Kotler   CLI.Call = MIB;
1565d5c4196cSReed Kotler 
15663daf8bc9SVladimir Stefanovic   if (EmitJalrReloc && !Subtarget->inMips16Mode()) {
15673daf8bc9SVladimir Stefanovic     // Attach callee address to the instruction, let asm printer emit
15683daf8bc9SVladimir Stefanovic     // .reloc R_MIPS_JALR.
15693daf8bc9SVladimir Stefanovic     if (Symbol)
15703daf8bc9SVladimir Stefanovic       MIB.addSym(Symbol, MipsII::MO_JALR);
15713daf8bc9SVladimir Stefanovic     else
15723daf8bc9SVladimir Stefanovic       MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol(
15733daf8bc9SVladimir Stefanovic 	                   Addr.getGlobalValue()->getName()), MipsII::MO_JALR);
15743daf8bc9SVladimir Stefanovic   }
15753daf8bc9SVladimir Stefanovic 
1576d5c4196cSReed Kotler   // Finish off the call including any return values.
1577d5c4196cSReed Kotler   return finishCall(CLI, RetVT, NumBytes);
1578d5c4196cSReed Kotler }
1579d5c4196cSReed Kotler 
fastLowerIntrinsicCall(const IntrinsicInst * II)1580bdb91b31SVasileios Kalintiris bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) {
1581bdb91b31SVasileios Kalintiris   switch (II->getIntrinsicID()) {
1582bdb91b31SVasileios Kalintiris   default:
1583bdb91b31SVasileios Kalintiris     return false;
1584cbbf8e0aSVasileios Kalintiris   case Intrinsic::bswap: {
1585cbbf8e0aSVasileios Kalintiris     Type *RetTy = II->getCalledFunction()->getReturnType();
1586cbbf8e0aSVasileios Kalintiris 
1587cbbf8e0aSVasileios Kalintiris     MVT VT;
1588cbbf8e0aSVasileios Kalintiris     if (!isTypeSupported(RetTy, VT))
1589cbbf8e0aSVasileios Kalintiris       return false;
1590cbbf8e0aSVasileios Kalintiris 
1591d6b07348SJim Lin     Register SrcReg = getRegForValue(II->getOperand(0));
1592cbbf8e0aSVasileios Kalintiris     if (SrcReg == 0)
1593cbbf8e0aSVasileios Kalintiris       return false;
1594d6b07348SJim Lin     Register DestReg = createResultReg(&Mips::GPR32RegClass);
1595cbbf8e0aSVasileios Kalintiris     if (DestReg == 0)
1596cbbf8e0aSVasileios Kalintiris       return false;
1597cbbf8e0aSVasileios Kalintiris     if (VT == MVT::i16) {
1598cbbf8e0aSVasileios Kalintiris       if (Subtarget->hasMips32r2()) {
1599cbbf8e0aSVasileios Kalintiris         emitInst(Mips::WSBH, DestReg).addReg(SrcReg);
1600cbbf8e0aSVasileios Kalintiris         updateValueMap(II, DestReg);
1601cbbf8e0aSVasileios Kalintiris         return true;
1602cbbf8e0aSVasileios Kalintiris       } else {
1603cbbf8e0aSVasileios Kalintiris         unsigned TempReg[3];
16049d745828SKazu Hirata         for (unsigned &R : TempReg) {
16059d745828SKazu Hirata           R = createResultReg(&Mips::GPR32RegClass);
16069d745828SKazu Hirata           if (R == 0)
1607cbbf8e0aSVasileios Kalintiris             return false;
1608cbbf8e0aSVasileios Kalintiris         }
1609cbbf8e0aSVasileios Kalintiris         emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8);
1610cbbf8e0aSVasileios Kalintiris         emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8);
1611cbbf8e0aSVasileios Kalintiris         emitInst(Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]);
1612cbbf8e0aSVasileios Kalintiris         emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF);
1613cbbf8e0aSVasileios Kalintiris         updateValueMap(II, DestReg);
1614cbbf8e0aSVasileios Kalintiris         return true;
1615cbbf8e0aSVasileios Kalintiris       }
1616cbbf8e0aSVasileios Kalintiris     } else if (VT == MVT::i32) {
1617cbbf8e0aSVasileios Kalintiris       if (Subtarget->hasMips32r2()) {
1618d6b07348SJim Lin         Register TempReg = createResultReg(&Mips::GPR32RegClass);
1619cbbf8e0aSVasileios Kalintiris         emitInst(Mips::WSBH, TempReg).addReg(SrcReg);
1620cbbf8e0aSVasileios Kalintiris         emitInst(Mips::ROTR, DestReg).addReg(TempReg).addImm(16);
1621cbbf8e0aSVasileios Kalintiris         updateValueMap(II, DestReg);
1622cbbf8e0aSVasileios Kalintiris         return true;
1623cbbf8e0aSVasileios Kalintiris       } else {
1624cbbf8e0aSVasileios Kalintiris         unsigned TempReg[8];
16259d745828SKazu Hirata         for (unsigned &R : TempReg) {
16269d745828SKazu Hirata           R = createResultReg(&Mips::GPR32RegClass);
16279d745828SKazu Hirata           if (R == 0)
1628cbbf8e0aSVasileios Kalintiris             return false;
1629cbbf8e0aSVasileios Kalintiris         }
1630cbbf8e0aSVasileios Kalintiris 
1631cbbf8e0aSVasileios Kalintiris         emitInst(Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8);
1632cbbf8e0aSVasileios Kalintiris         emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24);
1633cbbf8e0aSVasileios Kalintiris         emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00);
1634cbbf8e0aSVasileios Kalintiris         emitInst(Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]);
1635cbbf8e0aSVasileios Kalintiris 
1636cbbf8e0aSVasileios Kalintiris         emitInst(Mips::ANDi, TempReg[4]).addReg(SrcReg).addImm(0xFF00);
1637cbbf8e0aSVasileios Kalintiris         emitInst(Mips::SLL, TempReg[5]).addReg(TempReg[4]).addImm(8);
1638cbbf8e0aSVasileios Kalintiris 
1639cbbf8e0aSVasileios Kalintiris         emitInst(Mips::SLL, TempReg[6]).addReg(SrcReg).addImm(24);
1640cbbf8e0aSVasileios Kalintiris         emitInst(Mips::OR, TempReg[7]).addReg(TempReg[3]).addReg(TempReg[5]);
1641cbbf8e0aSVasileios Kalintiris         emitInst(Mips::OR, DestReg).addReg(TempReg[6]).addReg(TempReg[7]);
1642cbbf8e0aSVasileios Kalintiris         updateValueMap(II, DestReg);
1643cbbf8e0aSVasileios Kalintiris         return true;
1644cbbf8e0aSVasileios Kalintiris       }
1645cbbf8e0aSVasileios Kalintiris     }
1646cbbf8e0aSVasileios Kalintiris     return false;
1647cbbf8e0aSVasileios Kalintiris   }
1648bdb91b31SVasileios Kalintiris   case Intrinsic::memcpy:
1649bdb91b31SVasileios Kalintiris   case Intrinsic::memmove: {
1650bdb91b31SVasileios Kalintiris     const auto *MTI = cast<MemTransferInst>(II);
1651bdb91b31SVasileios Kalintiris     // Don't handle volatile.
1652bdb91b31SVasileios Kalintiris     if (MTI->isVolatile())
1653bdb91b31SVasileios Kalintiris       return false;
1654bdb91b31SVasileios Kalintiris     if (!MTI->getLength()->getType()->isIntegerTy(32))
1655bdb91b31SVasileios Kalintiris       return false;
1656bdb91b31SVasileios Kalintiris     const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove";
1657c1e32b3fSKazu Hirata     return lowerCallTo(II, IntrMemName, II->arg_size() - 1);
1658bdb91b31SVasileios Kalintiris   }
1659bdb91b31SVasileios Kalintiris   case Intrinsic::memset: {
1660bdb91b31SVasileios Kalintiris     const MemSetInst *MSI = cast<MemSetInst>(II);
1661bdb91b31SVasileios Kalintiris     // Don't handle volatile.
1662bdb91b31SVasileios Kalintiris     if (MSI->isVolatile())
1663bdb91b31SVasileios Kalintiris       return false;
1664bdb91b31SVasileios Kalintiris     if (!MSI->getLength()->getType()->isIntegerTy(32))
1665bdb91b31SVasileios Kalintiris       return false;
1666c1e32b3fSKazu Hirata     return lowerCallTo(II, "memset", II->arg_size() - 1);
1667bdb91b31SVasileios Kalintiris   }
1668bdb91b31SVasileios Kalintiris   }
1669bdb91b31SVasileios Kalintiris   return false;
1670bdb91b31SVasileios Kalintiris }
1671bdb91b31SVasileios Kalintiris 
selectRet(const Instruction * I)1672d4ea29e6SReed Kotler bool MipsFastISel::selectRet(const Instruction *I) {
1673aa150ed7SReed Kotler   const Function &F = *I->getParent()->getParent();
1674d4ea29e6SReed Kotler   const ReturnInst *Ret = cast<ReturnInst>(I);
1675d4ea29e6SReed Kotler 
1676d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "selectRet\n");
1677b432a3edSSimon Dardis 
1678d4ea29e6SReed Kotler   if (!FuncInfo.CanLowerReturn)
1679d4ea29e6SReed Kotler     return false;
1680aa150ed7SReed Kotler 
1681aa150ed7SReed Kotler   // Build a list of return value registers.
1682aa150ed7SReed Kotler   SmallVector<unsigned, 4> RetRegs;
1683aa150ed7SReed Kotler 
1684d4ea29e6SReed Kotler   if (Ret->getNumOperands() > 0) {
1685aa150ed7SReed Kotler     CallingConv::ID CC = F.getCallingConv();
16869876946aSVasileios Kalintiris 
16879876946aSVasileios Kalintiris     // Do not handle FastCC.
16889876946aSVasileios Kalintiris     if (CC == CallingConv::Fast)
16899876946aSVasileios Kalintiris       return false;
16909876946aSVasileios Kalintiris 
1691aa150ed7SReed Kotler     SmallVector<ISD::OutputArg, 4> Outs;
169281920b0aSMatt Arsenault     GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL);
169356228dabSMehdi Amini 
1694aa150ed7SReed Kotler     // Analyze operands of the call, assigning locations to each operand.
1695aa150ed7SReed Kotler     SmallVector<CCValAssign, 16> ValLocs;
1696aa150ed7SReed Kotler     MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs,
1697aa150ed7SReed Kotler                        I->getContext());
1698aa150ed7SReed Kotler     CCAssignFn *RetCC = RetCC_Mips;
1699aa150ed7SReed Kotler     CCInfo.AnalyzeReturn(Outs, RetCC);
1700aa150ed7SReed Kotler 
1701aa150ed7SReed Kotler     // Only handle a single return value for now.
1702aa150ed7SReed Kotler     if (ValLocs.size() != 1)
1703aa150ed7SReed Kotler       return false;
1704aa150ed7SReed Kotler 
1705aa150ed7SReed Kotler     CCValAssign &VA = ValLocs[0];
1706aa150ed7SReed Kotler     const Value *RV = Ret->getOperand(0);
1707aa150ed7SReed Kotler 
1708aa150ed7SReed Kotler     // Don't bother handling odd stuff for now.
1709aa150ed7SReed Kotler     if ((VA.getLocInfo() != CCValAssign::Full) &&
1710aa150ed7SReed Kotler         (VA.getLocInfo() != CCValAssign::BCvt))
1711aa150ed7SReed Kotler       return false;
1712aa150ed7SReed Kotler 
1713aa150ed7SReed Kotler     // Only handle register returns for now.
1714aa150ed7SReed Kotler     if (!VA.isRegLoc())
1715aa150ed7SReed Kotler       return false;
1716aa150ed7SReed Kotler 
1717d6b07348SJim Lin     Register Reg = getRegForValue(RV);
1718aa150ed7SReed Kotler     if (Reg == 0)
1719aa150ed7SReed Kotler       return false;
1720aa150ed7SReed Kotler 
1721aa150ed7SReed Kotler     unsigned SrcReg = Reg + VA.getValNo();
17220c476111SDaniel Sanders     Register DestReg = VA.getLocReg();
1723aa150ed7SReed Kotler     // Avoid a cross-class copy. This is very unlikely.
1724aa150ed7SReed Kotler     if (!MRI.getRegClass(SrcReg)->contains(DestReg))
1725aa150ed7SReed Kotler       return false;
1726aa150ed7SReed Kotler 
172744ede33aSMehdi Amini     EVT RVEVT = TLI.getValueType(DL, RV->getType());
1728aa150ed7SReed Kotler     if (!RVEVT.isSimple())
1729aa150ed7SReed Kotler       return false;
1730aa150ed7SReed Kotler 
1731aa150ed7SReed Kotler     if (RVEVT.isVector())
1732aa150ed7SReed Kotler       return false;
1733aa150ed7SReed Kotler 
1734aa150ed7SReed Kotler     MVT RVVT = RVEVT.getSimpleVT();
1735aa150ed7SReed Kotler     if (RVVT == MVT::f128)
1736aa150ed7SReed Kotler       return false;
1737aa150ed7SReed Kotler 
1738b432a3edSSimon Dardis     // Do not handle FGR64 returns for now.
1739b432a3edSSimon Dardis     if (RVVT == MVT::f64 && UnsupportedFPMode) {
1740d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode\n");
1741b432a3edSSimon Dardis       return false;
1742b432a3edSSimon Dardis     }
1743b432a3edSSimon Dardis 
1744aa150ed7SReed Kotler     MVT DestVT = VA.getValVT();
1745aa150ed7SReed Kotler     // Special handling for extended integers.
1746aa150ed7SReed Kotler     if (RVVT != DestVT) {
1747aa150ed7SReed Kotler       if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16)
1748aa150ed7SReed Kotler         return false;
1749aa150ed7SReed Kotler 
17501249e746SVasileios Kalintiris       if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) {
1751aa150ed7SReed Kotler         bool IsZExt = Outs[0].Flags.isZExt();
1752aa150ed7SReed Kotler         SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt);
1753aa150ed7SReed Kotler         if (SrcReg == 0)
1754d4ea29e6SReed Kotler           return false;
1755d4ea29e6SReed Kotler       }
17561249e746SVasileios Kalintiris     }
1757aa150ed7SReed Kotler 
1758aa150ed7SReed Kotler     // Make the copy.
1759aa150ed7SReed Kotler     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1760aa150ed7SReed Kotler             TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg);
1761aa150ed7SReed Kotler 
1762aa150ed7SReed Kotler     // Add register to return instruction.
1763aa150ed7SReed Kotler     RetRegs.push_back(VA.getLocReg());
1764aa150ed7SReed Kotler   }
1765aa150ed7SReed Kotler   MachineInstrBuilder MIB = emitInst(Mips::RetRA);
1766aa150ed7SReed Kotler   for (unsigned i = 0, e = RetRegs.size(); i != e; ++i)
1767aa150ed7SReed Kotler     MIB.addReg(RetRegs[i], RegState::Implicit);
1768d4ea29e6SReed Kotler   return true;
1769d4ea29e6SReed Kotler }
1770d4ea29e6SReed Kotler 
selectTrunc(const Instruction * I)1771d4ea29e6SReed Kotler bool MipsFastISel::selectTrunc(const Instruction *I) {
1772d4ea29e6SReed Kotler   // The high bits for a type smaller than the register size are assumed to be
1773d4ea29e6SReed Kotler   // undefined.
1774d4ea29e6SReed Kotler   Value *Op = I->getOperand(0);
1775d4ea29e6SReed Kotler 
1776d4ea29e6SReed Kotler   EVT SrcVT, DestVT;
177744ede33aSMehdi Amini   SrcVT = TLI.getValueType(DL, Op->getType(), true);
177844ede33aSMehdi Amini   DestVT = TLI.getValueType(DL, I->getType(), true);
1779d4ea29e6SReed Kotler 
1780d4ea29e6SReed Kotler   if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8)
1781d4ea29e6SReed Kotler     return false;
1782d4ea29e6SReed Kotler   if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1)
1783d4ea29e6SReed Kotler     return false;
1784d4ea29e6SReed Kotler 
1785d6b07348SJim Lin   Register SrcReg = getRegForValue(Op);
1786d4ea29e6SReed Kotler   if (!SrcReg)
1787d4ea29e6SReed Kotler     return false;
1788d4ea29e6SReed Kotler 
1789d4ea29e6SReed Kotler   // Because the high bits are undefined, a truncate doesn't generate
1790d4ea29e6SReed Kotler   // any code.
1791d4ea29e6SReed Kotler   updateValueMap(I, SrcReg);
1792d4ea29e6SReed Kotler   return true;
1793d4ea29e6SReed Kotler }
1794dde94e4cSEugene Zelenko 
selectIntExt(const Instruction * I)1795d4ea29e6SReed Kotler bool MipsFastISel::selectIntExt(const Instruction *I) {
1796d4ea29e6SReed Kotler   Type *DestTy = I->getType();
1797d4ea29e6SReed Kotler   Value *Src = I->getOperand(0);
1798d4ea29e6SReed Kotler   Type *SrcTy = Src->getType();
1799d4ea29e6SReed Kotler 
1800d4ea29e6SReed Kotler   bool isZExt = isa<ZExtInst>(I);
1801d6b07348SJim Lin   Register SrcReg = getRegForValue(Src);
1802d4ea29e6SReed Kotler   if (!SrcReg)
1803d4ea29e6SReed Kotler     return false;
1804d4ea29e6SReed Kotler 
1805d4ea29e6SReed Kotler   EVT SrcEVT, DestEVT;
180644ede33aSMehdi Amini   SrcEVT = TLI.getValueType(DL, SrcTy, true);
180744ede33aSMehdi Amini   DestEVT = TLI.getValueType(DL, DestTy, true);
1808d4ea29e6SReed Kotler   if (!SrcEVT.isSimple())
1809d4ea29e6SReed Kotler     return false;
1810d4ea29e6SReed Kotler   if (!DestEVT.isSimple())
1811d4ea29e6SReed Kotler     return false;
1812d4ea29e6SReed Kotler 
1813d4ea29e6SReed Kotler   MVT SrcVT = SrcEVT.getSimpleVT();
1814d4ea29e6SReed Kotler   MVT DestVT = DestEVT.getSimpleVT();
1815d6b07348SJim Lin   Register ResultReg = createResultReg(&Mips::GPR32RegClass);
1816d4ea29e6SReed Kotler 
1817d4ea29e6SReed Kotler   if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt))
1818d4ea29e6SReed Kotler     return false;
1819d4ea29e6SReed Kotler   updateValueMap(I, ResultReg);
1820d4ea29e6SReed Kotler   return true;
1821d4ea29e6SReed Kotler }
1822dde94e4cSEugene Zelenko 
emitIntSExt32r1(MVT SrcVT,unsigned SrcReg,MVT DestVT,unsigned DestReg)1823d4ea29e6SReed Kotler bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT,
1824d4ea29e6SReed Kotler                                    unsigned DestReg) {
1825d4ea29e6SReed Kotler   unsigned ShiftAmt;
1826d4ea29e6SReed Kotler   switch (SrcVT.SimpleTy) {
1827d4ea29e6SReed Kotler   default:
1828d4ea29e6SReed Kotler     return false;
1829d4ea29e6SReed Kotler   case MVT::i8:
1830d4ea29e6SReed Kotler     ShiftAmt = 24;
1831d4ea29e6SReed Kotler     break;
1832d4ea29e6SReed Kotler   case MVT::i16:
1833d4ea29e6SReed Kotler     ShiftAmt = 16;
1834d4ea29e6SReed Kotler     break;
1835d4ea29e6SReed Kotler   }
1836d6b07348SJim Lin   Register TempReg = createResultReg(&Mips::GPR32RegClass);
1837d4ea29e6SReed Kotler   emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt);
1838d4ea29e6SReed Kotler   emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt);
1839d4ea29e6SReed Kotler   return true;
1840d4ea29e6SReed Kotler }
1841d4ea29e6SReed Kotler 
emitIntSExt32r2(MVT SrcVT,unsigned SrcReg,MVT DestVT,unsigned DestReg)1842d4ea29e6SReed Kotler bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT,
1843d4ea29e6SReed Kotler                                    unsigned DestReg) {
1844d4ea29e6SReed Kotler   switch (SrcVT.SimpleTy) {
1845d4ea29e6SReed Kotler   default:
1846d4ea29e6SReed Kotler     return false;
1847d4ea29e6SReed Kotler   case MVT::i8:
1848d4ea29e6SReed Kotler     emitInst(Mips::SEB, DestReg).addReg(SrcReg);
1849d4ea29e6SReed Kotler     break;
1850d4ea29e6SReed Kotler   case MVT::i16:
1851d4ea29e6SReed Kotler     emitInst(Mips::SEH, DestReg).addReg(SrcReg);
1852d4ea29e6SReed Kotler     break;
1853d4ea29e6SReed Kotler   }
1854d4ea29e6SReed Kotler   return true;
1855d4ea29e6SReed Kotler }
1856d4ea29e6SReed Kotler 
emitIntSExt(MVT SrcVT,unsigned SrcReg,MVT DestVT,unsigned DestReg)1857d4ea29e6SReed Kotler bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
1858d4ea29e6SReed Kotler                                unsigned DestReg) {
1859d4ea29e6SReed Kotler   if ((DestVT != MVT::i32) && (DestVT != MVT::i16))
1860d4ea29e6SReed Kotler     return false;
1861d4ea29e6SReed Kotler   if (Subtarget->hasMips32r2())
1862d4ea29e6SReed Kotler     return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg);
1863d4ea29e6SReed Kotler   return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg);
1864d4ea29e6SReed Kotler }
1865d4ea29e6SReed Kotler 
emitIntZExt(MVT SrcVT,unsigned SrcReg,MVT DestVT,unsigned DestReg)1866d4ea29e6SReed Kotler bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
1867d4ea29e6SReed Kotler                                unsigned DestReg) {
1868b876b58dSVasileios Kalintiris   int64_t Imm;
1869b876b58dSVasileios Kalintiris 
1870d4ea29e6SReed Kotler   switch (SrcVT.SimpleTy) {
1871d4ea29e6SReed Kotler   default:
1872d4ea29e6SReed Kotler     return false;
1873d4ea29e6SReed Kotler   case MVT::i1:
1874b876b58dSVasileios Kalintiris     Imm = 1;
1875d4ea29e6SReed Kotler     break;
1876d4ea29e6SReed Kotler   case MVT::i8:
1877b876b58dSVasileios Kalintiris     Imm = 0xff;
1878d4ea29e6SReed Kotler     break;
1879d4ea29e6SReed Kotler   case MVT::i16:
1880b876b58dSVasileios Kalintiris     Imm = 0xffff;
1881d5c4196cSReed Kotler     break;
1882d4ea29e6SReed Kotler   }
1883b876b58dSVasileios Kalintiris 
1884b876b58dSVasileios Kalintiris   emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(Imm);
1885d4ea29e6SReed Kotler   return true;
1886d4ea29e6SReed Kotler }
1887d4ea29e6SReed Kotler 
emitIntExt(MVT SrcVT,unsigned SrcReg,MVT DestVT,unsigned DestReg,bool IsZExt)1888d4ea29e6SReed Kotler bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
1889d4ea29e6SReed Kotler                               unsigned DestReg, bool IsZExt) {
18901202f36bSVasileios Kalintiris   // FastISel does not have plumbing to deal with extensions where the SrcVT or
18911202f36bSVasileios Kalintiris   // DestVT are odd things, so test to make sure that they are both types we can
18921202f36bSVasileios Kalintiris   // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise
18931202f36bSVasileios Kalintiris   // bail out to SelectionDAG.
18941202f36bSVasileios Kalintiris   if (((DestVT != MVT::i8) && (DestVT != MVT::i16) && (DestVT != MVT::i32)) ||
18951202f36bSVasileios Kalintiris       ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) && (SrcVT != MVT::i16)))
18961202f36bSVasileios Kalintiris     return false;
1897d4ea29e6SReed Kotler   if (IsZExt)
1898d4ea29e6SReed Kotler     return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg);
1899d4ea29e6SReed Kotler   return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg);
1900d4ea29e6SReed Kotler }
1901d5c4196cSReed Kotler 
emitIntExt(MVT SrcVT,unsigned SrcReg,MVT DestVT,bool isZExt)1902d5c4196cSReed Kotler unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
1903d5c4196cSReed Kotler                                   bool isZExt) {
1904d5c4196cSReed Kotler   unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
1905aa150ed7SReed Kotler   bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt);
1906aa150ed7SReed Kotler   return Success ? DestReg : 0;
1907d5c4196cSReed Kotler }
1908d5c4196cSReed Kotler 
selectDivRem(const Instruction * I,unsigned ISDOpcode)19098fcb3986SVasileios Kalintiris bool MipsFastISel::selectDivRem(const Instruction *I, unsigned ISDOpcode) {
191044ede33aSMehdi Amini   EVT DestEVT = TLI.getValueType(DL, I->getType(), true);
19118fcb3986SVasileios Kalintiris   if (!DestEVT.isSimple())
19128fcb3986SVasileios Kalintiris     return false;
19138fcb3986SVasileios Kalintiris 
19148fcb3986SVasileios Kalintiris   MVT DestVT = DestEVT.getSimpleVT();
19158fcb3986SVasileios Kalintiris   if (DestVT != MVT::i32)
19168fcb3986SVasileios Kalintiris     return false;
19178fcb3986SVasileios Kalintiris 
19188fcb3986SVasileios Kalintiris   unsigned DivOpc;
19198fcb3986SVasileios Kalintiris   switch (ISDOpcode) {
19208fcb3986SVasileios Kalintiris   default:
19218fcb3986SVasileios Kalintiris     return false;
19228fcb3986SVasileios Kalintiris   case ISD::SDIV:
19238fcb3986SVasileios Kalintiris   case ISD::SREM:
19248fcb3986SVasileios Kalintiris     DivOpc = Mips::SDIV;
19258fcb3986SVasileios Kalintiris     break;
19268fcb3986SVasileios Kalintiris   case ISD::UDIV:
19278fcb3986SVasileios Kalintiris   case ISD::UREM:
19288fcb3986SVasileios Kalintiris     DivOpc = Mips::UDIV;
19298fcb3986SVasileios Kalintiris     break;
19308fcb3986SVasileios Kalintiris   }
19318fcb3986SVasileios Kalintiris 
1932d6b07348SJim Lin   Register Src0Reg = getRegForValue(I->getOperand(0));
1933d6b07348SJim Lin   Register Src1Reg = getRegForValue(I->getOperand(1));
19348fcb3986SVasileios Kalintiris   if (!Src0Reg || !Src1Reg)
19358fcb3986SVasileios Kalintiris     return false;
19368fcb3986SVasileios Kalintiris 
19378fcb3986SVasileios Kalintiris   emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg);
19388fcb3986SVasileios Kalintiris   emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7);
19398fcb3986SVasileios Kalintiris 
1940d6b07348SJim Lin   Register ResultReg = createResultReg(&Mips::GPR32RegClass);
19418fcb3986SVasileios Kalintiris   if (!ResultReg)
19428fcb3986SVasileios Kalintiris     return false;
19438fcb3986SVasileios Kalintiris 
19448fcb3986SVasileios Kalintiris   unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM)
19458fcb3986SVasileios Kalintiris                        ? Mips::MFHI
19468fcb3986SVasileios Kalintiris                        : Mips::MFLO;
19478fcb3986SVasileios Kalintiris   emitInst(MFOpc, ResultReg);
19488fcb3986SVasileios Kalintiris 
19498fcb3986SVasileios Kalintiris   updateValueMap(I, ResultReg);
19508fcb3986SVasileios Kalintiris   return true;
19518fcb3986SVasileios Kalintiris }
19528fcb3986SVasileios Kalintiris 
selectShift(const Instruction * I)19537a6b1878SVasileios Kalintiris bool MipsFastISel::selectShift(const Instruction *I) {
19547a6b1878SVasileios Kalintiris   MVT RetVT;
19557a6b1878SVasileios Kalintiris 
19567a6b1878SVasileios Kalintiris   if (!isTypeSupported(I->getType(), RetVT))
19577a6b1878SVasileios Kalintiris     return false;
19587a6b1878SVasileios Kalintiris 
1959d6b07348SJim Lin   Register ResultReg = createResultReg(&Mips::GPR32RegClass);
19607a6b1878SVasileios Kalintiris   if (!ResultReg)
19617a6b1878SVasileios Kalintiris     return false;
19627a6b1878SVasileios Kalintiris 
19637a6b1878SVasileios Kalintiris   unsigned Opcode = I->getOpcode();
19647a6b1878SVasileios Kalintiris   const Value *Op0 = I->getOperand(0);
1965d6b07348SJim Lin   Register Op0Reg = getRegForValue(Op0);
19667a6b1878SVasileios Kalintiris   if (!Op0Reg)
19677a6b1878SVasileios Kalintiris     return false;
19687a6b1878SVasileios Kalintiris 
19697a6b1878SVasileios Kalintiris   // If AShr or LShr, then we need to make sure the operand0 is sign extended.
19707a6b1878SVasileios Kalintiris   if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) {
1971d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
19727a6b1878SVasileios Kalintiris     if (!TempReg)
19737a6b1878SVasileios Kalintiris       return false;
19747a6b1878SVasileios Kalintiris 
197544ede33aSMehdi Amini     MVT Op0MVT = TLI.getValueType(DL, Op0->getType(), true).getSimpleVT();
19767a6b1878SVasileios Kalintiris     bool IsZExt = Opcode == Instruction::LShr;
19777a6b1878SVasileios Kalintiris     if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt))
19787a6b1878SVasileios Kalintiris       return false;
19797a6b1878SVasileios Kalintiris 
19807a6b1878SVasileios Kalintiris     Op0Reg = TempReg;
19817a6b1878SVasileios Kalintiris   }
19827a6b1878SVasileios Kalintiris 
19837a6b1878SVasileios Kalintiris   if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) {
19847a6b1878SVasileios Kalintiris     uint64_t ShiftVal = C->getZExtValue();
19857a6b1878SVasileios Kalintiris 
19867a6b1878SVasileios Kalintiris     switch (Opcode) {
19877a6b1878SVasileios Kalintiris     default:
19887a6b1878SVasileios Kalintiris       llvm_unreachable("Unexpected instruction.");
19897a6b1878SVasileios Kalintiris     case Instruction::Shl:
19907a6b1878SVasileios Kalintiris       Opcode = Mips::SLL;
19917a6b1878SVasileios Kalintiris       break;
19927a6b1878SVasileios Kalintiris     case Instruction::AShr:
19937a6b1878SVasileios Kalintiris       Opcode = Mips::SRA;
19947a6b1878SVasileios Kalintiris       break;
19957a6b1878SVasileios Kalintiris     case Instruction::LShr:
19967a6b1878SVasileios Kalintiris       Opcode = Mips::SRL;
19977a6b1878SVasileios Kalintiris       break;
19987a6b1878SVasileios Kalintiris     }
19997a6b1878SVasileios Kalintiris 
20007a6b1878SVasileios Kalintiris     emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal);
20017a6b1878SVasileios Kalintiris     updateValueMap(I, ResultReg);
20027a6b1878SVasileios Kalintiris     return true;
20037a6b1878SVasileios Kalintiris   }
20047a6b1878SVasileios Kalintiris 
2005d6b07348SJim Lin   Register Op1Reg = getRegForValue(I->getOperand(1));
20067a6b1878SVasileios Kalintiris   if (!Op1Reg)
20077a6b1878SVasileios Kalintiris     return false;
20087a6b1878SVasileios Kalintiris 
20097a6b1878SVasileios Kalintiris   switch (Opcode) {
20107a6b1878SVasileios Kalintiris   default:
20117a6b1878SVasileios Kalintiris     llvm_unreachable("Unexpected instruction.");
20127a6b1878SVasileios Kalintiris   case Instruction::Shl:
20137a6b1878SVasileios Kalintiris     Opcode = Mips::SLLV;
20147a6b1878SVasileios Kalintiris     break;
20157a6b1878SVasileios Kalintiris   case Instruction::AShr:
20167a6b1878SVasileios Kalintiris     Opcode = Mips::SRAV;
20177a6b1878SVasileios Kalintiris     break;
20187a6b1878SVasileios Kalintiris   case Instruction::LShr:
20197a6b1878SVasileios Kalintiris     Opcode = Mips::SRLV;
20207a6b1878SVasileios Kalintiris     break;
20217a6b1878SVasileios Kalintiris   }
20227a6b1878SVasileios Kalintiris 
20237a6b1878SVasileios Kalintiris   emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
20247a6b1878SVasileios Kalintiris   updateValueMap(I, ResultReg);
20257a6b1878SVasileios Kalintiris   return true;
20267a6b1878SVasileios Kalintiris }
20277a6b1878SVasileios Kalintiris 
fastSelectInstruction(const Instruction * I)20285b8bb4d7SJuergen Ributzka bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
202967077b30SReed Kotler   switch (I->getOpcode()) {
203067077b30SReed Kotler   default:
203167077b30SReed Kotler     break;
20329fe3bfd0SReed Kotler   case Instruction::Load:
2033a562b46dSReed Kotler     return selectLoad(I);
2034bab3f23dSReed Kotler   case Instruction::Store:
2035a562b46dSReed Kotler     return selectStore(I);
20368fcb3986SVasileios Kalintiris   case Instruction::SDiv:
20378fcb3986SVasileios Kalintiris     if (!selectBinaryOp(I, ISD::SDIV))
20388fcb3986SVasileios Kalintiris       return selectDivRem(I, ISD::SDIV);
20398fcb3986SVasileios Kalintiris     return true;
20408fcb3986SVasileios Kalintiris   case Instruction::UDiv:
20418fcb3986SVasileios Kalintiris     if (!selectBinaryOp(I, ISD::UDIV))
20428fcb3986SVasileios Kalintiris       return selectDivRem(I, ISD::UDIV);
20438fcb3986SVasileios Kalintiris     return true;
20448fcb3986SVasileios Kalintiris   case Instruction::SRem:
20458fcb3986SVasileios Kalintiris     if (!selectBinaryOp(I, ISD::SREM))
20468fcb3986SVasileios Kalintiris       return selectDivRem(I, ISD::SREM);
20478fcb3986SVasileios Kalintiris     return true;
20488fcb3986SVasileios Kalintiris   case Instruction::URem:
20498fcb3986SVasileios Kalintiris     if (!selectBinaryOp(I, ISD::UREM))
20508fcb3986SVasileios Kalintiris       return selectDivRem(I, ISD::UREM);
20518fcb3986SVasileios Kalintiris     return true;
20527a6b1878SVasileios Kalintiris   case Instruction::Shl:
20537a6b1878SVasileios Kalintiris   case Instruction::LShr:
20547a6b1878SVasileios Kalintiris   case Instruction::AShr:
20557a6b1878SVasileios Kalintiris     return selectShift(I);
205607d3a2f6SReed Kotler   case Instruction::And:
205707d3a2f6SReed Kotler   case Instruction::Or:
205807d3a2f6SReed Kotler   case Instruction::Xor:
205907d3a2f6SReed Kotler     return selectLogicalOp(I);
206062de6b96SReed Kotler   case Instruction::Br:
2061a562b46dSReed Kotler     return selectBranch(I);
206267077b30SReed Kotler   case Instruction::Ret:
2063a562b46dSReed Kotler     return selectRet(I);
20643ebdcc9eSReed Kotler   case Instruction::Trunc:
2065a562b46dSReed Kotler     return selectTrunc(I);
20663ebdcc9eSReed Kotler   case Instruction::ZExt:
20673ebdcc9eSReed Kotler   case Instruction::SExt:
2068a562b46dSReed Kotler     return selectIntExt(I);
2069b9dc248eSReed Kotler   case Instruction::FPTrunc:
2070a562b46dSReed Kotler     return selectFPTrunc(I);
20713ebdcc9eSReed Kotler   case Instruction::FPExt:
2072a562b46dSReed Kotler     return selectFPExt(I);
207312f9488eSReed Kotler   case Instruction::FPToSI:
2074a562b46dSReed Kotler     return selectFPToInt(I, /*isSigned*/ true);
207512f9488eSReed Kotler   case Instruction::FPToUI:
2076a562b46dSReed Kotler     return selectFPToInt(I, /*isSigned*/ false);
2077497311abSReed Kotler   case Instruction::ICmp:
2078497311abSReed Kotler   case Instruction::FCmp:
2079a562b46dSReed Kotler     return selectCmp(I);
2080127f894bSVasileios Kalintiris   case Instruction::Select:
2081127f894bSVasileios Kalintiris     return selectSelect(I);
208267077b30SReed Kotler   }
208367077b30SReed Kotler   return false;
208467077b30SReed Kotler }
2085720c5ca4SReed Kotler 
getRegEnsuringSimpleIntegerWidening(const Value * V,bool IsUnsigned)2086d4ea29e6SReed Kotler unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V,
2087d4ea29e6SReed Kotler                                                            bool IsUnsigned) {
2088d6b07348SJim Lin   Register VReg = getRegForValue(V);
2089d4ea29e6SReed Kotler   if (VReg == 0)
209012f9488eSReed Kotler     return 0;
209144ede33aSMehdi Amini   MVT VMVT = TLI.getValueType(DL, V->getType(), true).getSimpleVT();
2092f10e4798SPetar Jovanovic 
2093f10e4798SPetar Jovanovic   if (VMVT == MVT::i1)
2094f10e4798SPetar Jovanovic     return 0;
2095f10e4798SPetar Jovanovic 
2096d4ea29e6SReed Kotler   if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) {
2097d6b07348SJim Lin     Register TempReg = createResultReg(&Mips::GPR32RegClass);
2098d4ea29e6SReed Kotler     if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned))
2099bab3f23dSReed Kotler       return 0;
2100d4ea29e6SReed Kotler     VReg = TempReg;
2101bab3f23dSReed Kotler   }
2102d4ea29e6SReed Kotler   return VReg;
2103bab3f23dSReed Kotler }
2104bab3f23dSReed Kotler 
simplifyAddress(Address & Addr)21055fb7d8b5SReed Kotler void MipsFastISel::simplifyAddress(Address &Addr) {
21065fb7d8b5SReed Kotler   if (!isInt<16>(Addr.getOffset())) {
21075fb7d8b5SReed Kotler     unsigned TempReg =
21085fb7d8b5SReed Kotler         materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass);
2109d6b07348SJim Lin     Register DestReg = createResultReg(&Mips::GPR32RegClass);
21105fb7d8b5SReed Kotler     emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg());
21115fb7d8b5SReed Kotler     Addr.setReg(DestReg);
21125fb7d8b5SReed Kotler     Addr.setOffset(0);
21135fb7d8b5SReed Kotler   }
21145fb7d8b5SReed Kotler }
21155fb7d8b5SReed Kotler 
fastEmitInst_rr(unsigned MachineInstOpcode,const TargetRegisterClass * RC,unsigned Op0,unsigned Op1)21167f680e15SVasileios Kalintiris unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode,
21177f680e15SVasileios Kalintiris                                        const TargetRegisterClass *RC,
211866506582SNikita Popov                                        unsigned Op0, unsigned Op1) {
21197f680e15SVasileios Kalintiris   // We treat the MUL instruction in a special way because it clobbers
21207f680e15SVasileios Kalintiris   // the HI0 & LO0 registers. The TableGen definition of this instruction can
21217f680e15SVasileios Kalintiris   // mark these registers only as implicitly defined. As a result, the
21227f680e15SVasileios Kalintiris   // register allocator runs out of registers when this instruction is
21237f680e15SVasileios Kalintiris   // followed by another instruction that defines the same registers too.
21247f680e15SVasileios Kalintiris   // We can fix this by explicitly marking those registers as dead.
21257f680e15SVasileios Kalintiris   if (MachineInstOpcode == Mips::MUL) {
2126d6b07348SJim Lin     Register ResultReg = createResultReg(RC);
21277f680e15SVasileios Kalintiris     const MCInstrDesc &II = TII.get(MachineInstOpcode);
21287f680e15SVasileios Kalintiris     Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs());
21297f680e15SVasileios Kalintiris     Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1);
21307f680e15SVasileios Kalintiris     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
213166506582SNikita Popov       .addReg(Op0)
213266506582SNikita Popov       .addReg(Op1)
21337f680e15SVasileios Kalintiris       .addReg(Mips::HI0, RegState::ImplicitDefine | RegState::Dead)
21347f680e15SVasileios Kalintiris       .addReg(Mips::LO0, RegState::ImplicitDefine | RegState::Dead);
21357f680e15SVasileios Kalintiris     return ResultReg;
21367f680e15SVasileios Kalintiris   }
21377f680e15SVasileios Kalintiris 
213866506582SNikita Popov   return FastISel::fastEmitInst_rr(MachineInstOpcode, RC, Op0, Op1);
21397f680e15SVasileios Kalintiris }
21407f680e15SVasileios Kalintiris 
2141720c5ca4SReed Kotler namespace llvm {
2142dde94e4cSEugene Zelenko 
createFastISel(FunctionLoweringInfo & funcInfo,const TargetLibraryInfo * libInfo)2143720c5ca4SReed Kotler FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
2144720c5ca4SReed Kotler                                const TargetLibraryInfo *libInfo) {
2145720c5ca4SReed Kotler   return new MipsFastISel(funcInfo, libInfo);
2146720c5ca4SReed Kotler }
2147dde94e4cSEugene Zelenko 
2148dde94e4cSEugene Zelenko } // end namespace llvm
2149