[llvm] r322069 - [Nios2] Arithmetic instructions for R1 and R2 ISA.

Nikolai Bozhenov via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 9 03:15:08 PST 2018


Author: n.bozhenov
Date: Tue Jan  9 03:15:08 2018
New Revision: 322069

URL: http://llvm.org/viewvc/llvm-project?rev=322069&view=rev
Log:
[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 at intel.com>

Added:
    llvm/trunk/test/CodeGen/Nios2/add-sub.ll
    llvm/trunk/test/CodeGen/Nios2/mul-div.ll
    llvm/trunk/test/CodeGen/Nios2/shift-rotate.ll
Modified:
    llvm/trunk/lib/Target/Nios2/Nios2ISelLowering.cpp
    llvm/trunk/lib/Target/Nios2/Nios2InstrFormats.td
    llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.cpp
    llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.h
    llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.td

Modified: llvm/trunk/lib/Target/Nios2/Nios2ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Nios2/Nios2ISelLowering.cpp?rev=322069&r1=322068&r2=322069&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Nios2/Nios2ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Nios2/Nios2ISelLowering.cpp Tue Jan  9 03:15:08 2018
@@ -32,9 +32,38 @@ Nios2TargetLowering::LowerReturn(SDValue
                                  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);
 }
 

Modified: llvm/trunk/lib/Target/Nios2/Nios2InstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Nios2/Nios2InstrFormats.td?rev=322069&r1=322068&r2=322069&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Nios2/Nios2InstrFormats.td (original)
+++ llvm/trunk/lib/Target/Nios2/Nios2InstrFormats.td Tue Jan  9 03:15:08 2018
@@ -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,
 }
 
 //===----------------------------------------------------------------------===//
+// 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
                                   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

Modified: llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.cpp?rev=322069&r1=322068&r2=322069&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.cpp Tue Jan  9 03:15:08 2018
@@ -41,3 +41,14 @@ bool Nios2InstrInfo::expandPostRAPseudo(
   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));
+}

Modified: llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.h?rev=322069&r1=322068&r2=322069&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.h (original)
+++ llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.h Tue Jan  9 03:15:08 2018
@@ -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
 

Modified: llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.td?rev=322069&r1=322068&r2=322069&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.td (original)
+++ llvm/trunk/lib/Target/Nios2/Nios2InstrInfo.td Tue Jan  9 03:15:08 2018
@@ -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
 			         (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,
   }
 }
 
-// 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>;
 

Added: llvm/trunk/test/CodeGen/Nios2/add-sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Nios2/add-sub.ll?rev=322069&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Nios2/add-sub.ll (added)
+++ llvm/trunk/test/CodeGen/Nios2/add-sub.ll Tue Jan  9 03:15:08 2018
@@ -0,0 +1,19 @@
+; RUN: llc < %s -march=nios2 2>&1 | FileCheck %s
+; RUN: llc < %s -march=nios2 -target-abi=nios2r2 2>&1 | FileCheck %s
+
+define i32 @add_reg(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: add_reg:
+; CHECK:   add r2, r4, r5
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @sub_reg(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: sub_reg:
+; CHECK:   sub r2, r4, r5
+  %c = sub i32 %a, %b
+  ret i32 %c
+}
+

Added: llvm/trunk/test/CodeGen/Nios2/mul-div.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Nios2/mul-div.ll?rev=322069&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Nios2/mul-div.ll (added)
+++ llvm/trunk/test/CodeGen/Nios2/mul-div.ll Tue Jan  9 03:15:08 2018
@@ -0,0 +1,27 @@
+; RUN: llc < %s -march=nios2 2>&1 | FileCheck %s
+; RUN: llc < %s -march=nios2 -target-abi=nios2r2 2>&1 | FileCheck %s
+
+define i32 @mul_reg(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: mul_reg:
+; CHECK:   mul r2, r4, r5
+  %c = mul i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @div_signed(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: div_signed:
+; CHECK:   div r2, r4, r5
+  %c = sdiv i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @div_unsigned(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: div_unsigned:
+; CHECK:   divu r2, r4, r5
+  %c = udiv i32 %a, %b
+  ret i32 %c
+}
+

Added: llvm/trunk/test/CodeGen/Nios2/shift-rotate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Nios2/shift-rotate.ll?rev=322069&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Nios2/shift-rotate.ll (added)
+++ llvm/trunk/test/CodeGen/Nios2/shift-rotate.ll Tue Jan  9 03:15:08 2018
@@ -0,0 +1,26 @@
+; RUN: llc < %s -march=nios2 2>&1 | FileCheck %s
+; RUN: llc < %s -march=nios2 -target-abi=nios2r2 2>&1 | FileCheck %s
+
+define i32 @sll_reg(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: sll_reg:
+; CHECK:   sll r2, r4, r5
+  %c = shl i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @srl_reg(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: srl_reg:
+; CHECK:   srl r2, r4, r5
+  %c = lshr i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @sra_reg(i32 %a, i32 %b) nounwind {
+entry:
+; CHECK: sra_reg:
+; CHECK:   sra r2, r4, r5
+  %c = ashr i32 %a, %b
+  ret i32 %c
+}




More information about the llvm-commits mailing list