diff options
author | Nikolai Bozhenov <nikolai.bozhenov@intel.com> | 2018-01-09 11:15:08 +0000 |
---|---|---|
committer | Nikolai Bozhenov <nikolai.bozhenov@intel.com> | 2018-01-09 11:15:08 +0000 |
commit | eededdade956e057d099bea20b769d25374d89c5 (patch) | |
tree | a6f294d0dcbfc00a8a146038dafe568c4f35f372 /llvm/lib/Target/Nios2 | |
parent | 6db41e608f95bd405735b886b8246b1f566e38c6 (diff) | |
download | bcm5719-llvm-eededdade956e057d099bea20b769d25374d89c5.tar.gz bcm5719-llvm-eededdade956e057d099bea20b769d25374d89c5.zip |
[Nios2] Arithmetic instructions for R1 and R2 ISA.
Summary:
This commit enables some of the arithmetic instructions for Nios2 ISA (for both
R1 and R2 revisions), implements facilities required to emit those instructions
and provides LIT tests for added instructions.
Reviewed By: hfinkel
Differential Revision: https://reviews.llvm.org/D41236
Author: belickim <mateusz.belicki@intel.com>
llvm-svn: 322069
Diffstat (limited to 'llvm/lib/Target/Nios2')
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2ISelLowering.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrFormats.td | 66 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrInfo.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrInfo.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrInfo.td | 39 |
5 files changed, 138 insertions, 11 deletions
diff --git a/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp b/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp index 99aa43f960c..008ce157072 100644 --- a/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp +++ b/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp @@ -32,9 +32,38 @@ Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { + // CCValAssign - represent the assignment of + // the return value to a location + SmallVector<CCValAssign, 16> RVLocs; + MachineFunction &MF = DAG.getMachineFunction(); + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); + // Analyze return values. + CCInfo.CheckReturn(Outs, RetCC_Nios2EABI); + SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + SDValue Val = OutVals[i]; + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + if (RVLocs[i].getValVT() != RVLocs[i].getLocVT()) + Val = DAG.getNode(ISD::BITCAST, DL, RVLocs[i].getLocVT(), Val); + + Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); + + // Guarantee that all emitted copies are stuck together with flags. + Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); + } + + if (Flag.getNode()) + RetOps.push_back(Flag); + return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps); } diff --git a/llvm/lib/Target/Nios2/Nios2InstrFormats.td b/llvm/lib/Target/Nios2/Nios2InstrFormats.td index 58578501d80..f57bf03bba3 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrFormats.td +++ b/llvm/lib/Target/Nios2/Nios2InstrFormats.td @@ -20,14 +20,44 @@ class Format<bits<6> val> { bits<6> Value = val; } -def Pseudo : Format<0>; -def FrmI : Format<1>; -def FrmR : Format<2>; -def FrmJ : Format<3>; -def FrmOther : Format<4>; // Instruction w/ a custom format +def Pseudo : Format<0>; +// Nios2 R1 instr formats: +def FrmI : Format<1>; +def FrmR : Format<2>; +def FrmJ : Format<3>; +def FrmOther : Format<4>; // Instruction w/ a custom format +// Nios2 R2 instr 32-bit formats: +def FrmL26 : Format<5>; // corresponds to J format in R1 +def FrmF2I16 : Format<6>; // corresponds to I format in R1 +def FrmF2X4I12 : Format<7>; +def FrmF1X4I12 : Format<8>; +def FrmF1X4L17 : Format<9>; +def FrmF3X6L5 : Format<10>; // corresponds to R format in R1 +def FrmF2X6L10 : Format<11>; +def FrmF3X6 : Format<12>; // corresponds to R format in R1 +def FrmF3X8 : Format<13>; // corresponds to custom format in R1 +// Nios2 R2 instr 16-bit formats: +def FrmI10 : Format<14>; +def FrmT1I7 : Format<15>; +def FrmT2I4 : Format<16>; +def FrmT1X1I6 : Format<17>; +def FrmX1I7 : Format<18>; +def FrmL5I4X1 : Format<19>; +def FrmT2X1L3 : Format<20>; +def FrmT2X1I3 : Format<21>; +def FrmT3X1 : Format<22>; +def FrmT2X3 : Format<23>; +def FrmF1X1 : Format<24>; +def FrmX2L5 : Format<25>; +def FrmF1I5 : Format<26>; +def FrmF2 : Format<27>; -def isNios2r1 : Predicate<"Subtarget->isNios2r1()">; -def isNios2r2 : Predicate<"Subtarget->isNios2r2()">; +//===----------------------------------------------------------------------===// +// Instruction Predicates: +//===----------------------------------------------------------------------===// + +def isNios2r1 : Predicate<"Subtarget->isNios2r1()">; +def isNios2r2 : Predicate<"Subtarget->isNios2r2()">; class PredicateControl { // Predicates related to specific target CPU features @@ -151,6 +181,27 @@ class FJ<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, } //===----------------------------------------------------------------------===// +// Format F3X6 (R2) instruction : <|opx|RSV|C|B|A|opcode|> +//===----------------------------------------------------------------------===// + +class F3X6<bits<6> opx, dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin>: + Nios2R2Inst32<outs, ins, asmstr, pattern, itin, FrmF3X6> { + bits<5> rC; + bits<5> rB; + bits<5> rA; + bits<5> rsv = 0; + + let Opcode = 0x20; /* opcode is always 0x20 (OPX group) for F3X6 instr. */ + + let Inst{31-26} = opx; /* opx stands for opcode extension */ + let Inst{25-21} = rsv; + let Inst{20-16} = rC; + let Inst{15-11} = rB; + let Inst{10-6} = rA; +} + +//===----------------------------------------------------------------------===// // Multiclasses for common instructions of both R1 and R2: //===----------------------------------------------------------------------===// @@ -160,6 +211,7 @@ multiclass CommonInstr_R_F3X6_opx<bits<6> opxR1, bits<6> opxR2, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin> { def NAME#_R1 : FR<opxR1, outs, ins, asmstr, pattern, itin>; + def NAME#_R2 : F3X6<opxR2, outs, ins, asmstr, pattern, itin>; } // Multiclass for instructions that have R format in R1 and F3X6 format in R2 diff --git a/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp b/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp index df435d2715d..9700cba3595 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp +++ b/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp @@ -41,3 +41,14 @@ bool Nios2InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { MBB.erase(MI); return true; } + +void Nios2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + const DebugLoc &DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc) const { + unsigned opc = Subtarget.hasNios2r2() ? Nios2::ADD_R2 : Nios2::ADD_R1; + BuildMI(MBB, I, DL, get(opc)) + .addReg(DestReg, RegState::Define) + .addReg(Nios2::ZERO) + .addReg(SrcReg, getKillRegState(KillSrc)); +} diff --git a/llvm/lib/Target/Nios2/Nios2InstrInfo.h b/llvm/lib/Target/Nios2/Nios2InstrInfo.h index a994d3662db..52f6e7e9c7c 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrInfo.h +++ b/llvm/lib/Target/Nios2/Nios2InstrInfo.h @@ -39,6 +39,10 @@ public: const Nios2RegisterInfo &getRegisterInfo() const { return RI; }; bool expandPostRAPseudo(MachineInstr &MI) const override; + + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, + bool KillSrc) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/Nios2/Nios2InstrInfo.td b/llvm/lib/Target/Nios2/Nios2InstrInfo.td index 7a39b31a25a..dee84f74bcb 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrInfo.td +++ b/llvm/lib/Target/Nios2/Nios2InstrInfo.td @@ -30,6 +30,10 @@ def simm16 : Operand<i32> { // e.g. addi, andi def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; +// Custom return SDNode +def Nios2Ret : SDNode<"Nios2ISD::Ret", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -45,6 +49,16 @@ multiclass ArithLogicRegImm16<bits<6> op, string mnemonic, SDNode opNode, (opNode CPURegs:$rA, immType:$imm))], IIAlu>; +// Arithmetic and logical instructions with 3 register operands. +// Defines R1 and R2 instruction at the same time. +multiclass ArithLogicReg<bits<6> opx, string mnemonic, + SDNode opNode>: + CommonInstr_R_F3X6<opx, (outs CPURegs:$rC), + (ins CPURegs:$rA, CPURegs:$rB), + !strconcat(mnemonic, "\t$rC, $rA, $rB"), + [(set CPURegs:$rC, (opNode CPURegs:$rA, CPURegs:$rB))], + IIAlu>; + multiclass Return<bits<6> opx, dag outs, dag ins, string mnemonic> { let rB = 0, rC = 0, isReturn = 1, @@ -55,14 +69,31 @@ multiclass Return<bits<6> opx, dag outs, dag ins, string mnemonic> { } } -// Custom return SDNode -def Nios2Ret : SDNode<"Nios2ISD::Ret", SDTNone, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - //===----------------------------------------------------------------------===// // Nios2 Instructions //===----------------------------------------------------------------------===// +/// Arithmetic instructions operating on registers. +let isCommutable = 1 , + isReMaterializable = 1 in { + defm ADD : ArithLogicReg<0x31, "add", add>; + defm AND : ArithLogicReg<0x0e, "and", and>; + defm OR : ArithLogicReg<0x16, "or", or>; + defm XOR : ArithLogicReg<0x1e, "xor", xor>; + defm MUL : ArithLogicReg<0x27, "mul", mul>; +} + +let isReMaterializable = 1 in { + defm SUB : ArithLogicReg<0x39, "sub", sub>; +} + +defm DIVU : ArithLogicReg<0x24, "divu", udiv>; +defm DIV : ArithLogicReg<0x25, "div", sdiv>; + +defm SLL : ArithLogicReg<0x13, "sll", shl>; +defm SRL : ArithLogicReg<0x1b, "srl", srl>; +defm SRA : ArithLogicReg<0x3b, "sra", sra>; + /// Arithmetic Instructions (ALU Immediate) defm ADDI : ArithLogicRegImm16<0x04, "addi", add, simm16, immSExt16>; |