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