Patch for integer multiply, signed/unsigned, long/long long.
llvm-svn: 165322
This commit is contained in:
parent
62f7fb977c
commit
240322140e
|
@ -10,7 +10,19 @@
|
||||||
// This file describes Mips16 instructions.
|
// This file describes Mips16 instructions.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This are pseudo formats for multiply
|
||||||
|
// This first one can be changed to non pseudo now.
|
||||||
|
//fmul
|
||||||
|
class FMULT16_ins<string asmstr, InstrItinClass itin> :
|
||||||
|
MipsPseudo16<(outs), (ins CPU16Regs:$rx, CPU16Regs:$ry),
|
||||||
|
!strconcat(asmstr, "\t$rx, $ry"), []>;
|
||||||
|
|
||||||
|
class FMULT16_LO_ins<string asmstr, InstrItinClass itin> :
|
||||||
|
MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
|
||||||
|
!strconcat(asmstr, "\t$rx, $ry\n\tmflo\t$rz"), []> {
|
||||||
|
let isCodeGenOnly=1;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// RRR-type instruction format
|
// RRR-type instruction format
|
||||||
//
|
//
|
||||||
|
@ -43,7 +55,11 @@ class FRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> :
|
||||||
FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry),
|
FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry),
|
||||||
!strconcat(asmstr, "\t$rx, $ry"), [], itin> {
|
!strconcat(asmstr, "\t$rx, $ry"), [], itin> {
|
||||||
}
|
}
|
||||||
|
class FRR16_M_ins<bits<5> f, string asmstr,
|
||||||
|
InstrItinClass itin> :
|
||||||
|
FRR16<f, (outs CPU16Regs:$rx), (ins),
|
||||||
|
!strconcat(asmstr, "\t$rx"), [], itin>;
|
||||||
|
|
||||||
class FRxRxRy16_ins<bits<5> f, string asmstr,
|
class FRxRxRy16_ins<bits<5> f, string asmstr,
|
||||||
InstrItinClass itin> :
|
InstrItinClass itin> :
|
||||||
FRR16<f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
|
FRR16<f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry),
|
||||||
|
@ -81,14 +97,13 @@ class FEXT_2RI16_ins<bits<5> _op, string asmstr,
|
||||||
!strconcat(asmstr, "\t$rx, $imm"), [], itin> {
|
!strconcat(asmstr, "\t$rx, $imm"), [], itin> {
|
||||||
let Constraints = "$rx_ = $rx";
|
let Constraints = "$rx_ = $rx";
|
||||||
}
|
}
|
||||||
|
|
||||||
// this has an explicit sp argument that we ignore to work around a problem
|
// this has an explicit sp argument that we ignore to work around a problem
|
||||||
// in the compiler
|
// in the compiler
|
||||||
class FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr,
|
class FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr,
|
||||||
InstrItinClass itin>:
|
InstrItinClass itin>:
|
||||||
FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm),
|
FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm),
|
||||||
!strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin> {
|
!strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// EXT-RRI instruction format
|
// EXT-RRI instruction format
|
||||||
|
@ -244,6 +259,63 @@ def Move32R16: FI8_MOV32R16_ins<"move", IIAlu>;
|
||||||
//
|
//
|
||||||
def MoveR3216: FI8_MOVR3216_ins<"move", IIAlu>;
|
def MoveR3216: FI8_MOVR3216_ins<"move", IIAlu>;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Format: MFHI rx MIPS16e
|
||||||
|
// Purpose: Move From HI Register
|
||||||
|
// To copy the special purpose HI register to a GPR.
|
||||||
|
//
|
||||||
|
def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIAlu> {
|
||||||
|
let Uses = [HI];
|
||||||
|
let neverHasSideEffects = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Format: MFLO rx MIPS16e
|
||||||
|
// Purpose: Move From LO Register
|
||||||
|
// To copy the special purpose LO register to a GPR.
|
||||||
|
//
|
||||||
|
def Mflo16: FRR16_M_ins<0b10010, "mflo", IIAlu> {
|
||||||
|
let Uses = [LO];
|
||||||
|
let neverHasSideEffects = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pseudo Instruction for mult
|
||||||
|
//
|
||||||
|
def MultRxRy16: FMULT16_ins<"mult", IIAlu> {
|
||||||
|
let isCommutable = 1;
|
||||||
|
let neverHasSideEffects = 1;
|
||||||
|
let Defs = [HI, LO];
|
||||||
|
}
|
||||||
|
|
||||||
|
def MultuRxRy16: FMULT16_ins<"multu", IIAlu> {
|
||||||
|
let isCommutable = 1;
|
||||||
|
let neverHasSideEffects = 1;
|
||||||
|
let Defs = [HI, LO];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Format: MULT rx, ry MIPS16e
|
||||||
|
// Purpose: Multiply Word
|
||||||
|
// To multiply 32-bit signed integers.
|
||||||
|
//
|
||||||
|
def MultRxRyRz16: FMULT16_LO_ins<"mult", IIAlu> {
|
||||||
|
let isCommutable = 1;
|
||||||
|
let neverHasSideEffects = 1;
|
||||||
|
let Defs = [HI, LO];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Format: MULTU rx, ry MIPS16e
|
||||||
|
// Purpose: Multiply Unsigned Word
|
||||||
|
// To multiply 32-bit unsigned integers.
|
||||||
|
//
|
||||||
|
def MultuRxRyRz16: FMULT16_LO_ins<"multu", IIAlu> {
|
||||||
|
let isCommutable = 1;
|
||||||
|
let neverHasSideEffects = 1;
|
||||||
|
let Defs = [HI, LO];
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Format: NEG rx, ry MIPS16e
|
// Format: NEG rx, ry MIPS16e
|
||||||
// Purpose: Negate
|
// Purpose: Negate
|
||||||
|
@ -413,6 +485,7 @@ class ArithLogic16_pat<SDNode OpNode, Instruction I> :
|
||||||
|
|
||||||
def: ArithLogic16_pat<add, AdduRxRyRz16>;
|
def: ArithLogic16_pat<add, AdduRxRyRz16>;
|
||||||
def: ArithLogic16_pat<and, AndRxRxRy16>;
|
def: ArithLogic16_pat<and, AndRxRxRy16>;
|
||||||
|
def: ArithLogic16_pat<mul, MultRxRyRz16>;
|
||||||
def: ArithLogic16_pat<or, OrRxRxRy16>;
|
def: ArithLogic16_pat<or, OrRxRxRy16>;
|
||||||
def: ArithLogic16_pat<sub, SubuRxRyRz16>;
|
def: ArithLogic16_pat<sub, SubuRxRyRz16>;
|
||||||
def: ArithLogic16_pat<xor, XorRxRxRy16>;
|
def: ArithLogic16_pat<xor, XorRxRxRy16>;
|
||||||
|
|
|
@ -372,14 +372,16 @@ MipsDAGToDAGISel::SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, EVT Ty,
|
||||||
SDValue InFlag = SDValue(Mul, 0);
|
SDValue InFlag = SDValue(Mul, 0);
|
||||||
|
|
||||||
if (HasLo) {
|
if (HasLo) {
|
||||||
Lo = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64, dl,
|
unsigned Opcode = Subtarget.inMips16Mode() ? Mips::Mflo16 :
|
||||||
Ty, MVT::Glue, InFlag);
|
(Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64);
|
||||||
|
Lo = CurDAG->getMachineNode(Opcode, dl, Ty, MVT::Glue, InFlag);
|
||||||
InFlag = SDValue(Lo, 1);
|
InFlag = SDValue(Lo, 1);
|
||||||
}
|
}
|
||||||
if (HasHi)
|
if (HasHi) {
|
||||||
Hi = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64, dl,
|
unsigned Opcode = Subtarget.inMips16Mode() ? Mips::Mfhi16 :
|
||||||
Ty, InFlag);
|
(Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64);
|
||||||
|
Hi = CurDAG->getMachineNode(Opcode, dl, Ty, InFlag);
|
||||||
|
}
|
||||||
return std::make_pair(Lo, Hi);
|
return std::make_pair(Lo, Hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,8 +445,13 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
|
||||||
/// Mul with two results
|
/// Mul with two results
|
||||||
case ISD::SMUL_LOHI:
|
case ISD::SMUL_LOHI:
|
||||||
case ISD::UMUL_LOHI: {
|
case ISD::UMUL_LOHI: {
|
||||||
if (NodeTy == MVT::i32)
|
if (NodeTy == MVT::i32) {
|
||||||
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
|
if (Subtarget.inMips16Mode())
|
||||||
|
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 :
|
||||||
|
Mips::MultRxRy16);
|
||||||
|
else
|
||||||
|
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT);
|
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT);
|
||||||
|
|
||||||
|
@ -470,8 +477,13 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
|
||||||
}
|
}
|
||||||
case ISD::MULHS:
|
case ISD::MULHS:
|
||||||
case ISD::MULHU: {
|
case ISD::MULHU: {
|
||||||
if (NodeTy == MVT::i32)
|
if (NodeTy == MVT::i32) {
|
||||||
MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
|
if (Subtarget.inMips16Mode())
|
||||||
|
MultOpc = (Opcode == ISD::MULHU ?
|
||||||
|
Mips::MultuRxRy16 : Mips::MultRxRy16);
|
||||||
|
else
|
||||||
|
MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT);
|
MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT);
|
||||||
|
|
||||||
|
|
|
@ -1746,8 +1746,10 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op,
|
||||||
|
|
||||||
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
|
if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) {
|
||||||
// %hi/%lo relocation
|
// %hi/%lo relocation
|
||||||
SDValue BAHi = DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_HI);
|
SDValue BAHi =
|
||||||
SDValue BALo = DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_LO);
|
DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_HI);
|
||||||
|
SDValue BALo =
|
||||||
|
DAG.getTargetBlockAddress(BA, MVT::i32, 0, MipsII::MO_ABS_LO);
|
||||||
SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi);
|
SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi);
|
||||||
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo);
|
SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo);
|
||||||
return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo);
|
return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo);
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
|
||||||
|
|
||||||
|
@iiii = global i32 5, align 4
|
||||||
|
@jjjj = global i32 -6, align 4
|
||||||
|
@kkkk = common global i32 0, align 4
|
||||||
|
|
||||||
|
define void @test() nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = load i32* @iiii, align 4
|
||||||
|
%1 = load i32* @jjjj, align 4
|
||||||
|
%mul = mul nsw i32 %1, %0
|
||||||
|
; 16: mult ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mflo ${{[0-9]+}}
|
||||||
|
|
||||||
|
store i32 %mul, i32* @kkkk, align 4
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
|
||||||
|
|
||||||
|
@iiii = global i64 5, align 8
|
||||||
|
@jjjj = global i64 -6, align 8
|
||||||
|
@kkkk = common global i64 0, align 8
|
||||||
|
|
||||||
|
define void @test() nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = load i64* @iiii, align 8
|
||||||
|
%1 = load i64* @jjjj, align 8
|
||||||
|
%mul = mul nsw i64 %1, %0
|
||||||
|
store i64 %mul, i64* @kkkk, align 8
|
||||||
|
; 16: multu ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mfhi ${{[0-9]+}}
|
||||||
|
; 16: mult ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mflo ${{[0-9]+}}
|
||||||
|
; 16: mult ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mflo ${{[0-9]+}}
|
||||||
|
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16
|
||||||
|
|
||||||
|
@iiii = global i64 5, align 8
|
||||||
|
@jjjj = global i64 6, align 8
|
||||||
|
@kkkk = common global i64 0, align 8
|
||||||
|
@.str = private unnamed_addr constant [20 x i8] c"%lld * %lld = %lld\0A\00", align 1
|
||||||
|
|
||||||
|
define void @test() nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = load i64* @iiii, align 8
|
||||||
|
%1 = load i64* @jjjj, align 8
|
||||||
|
%mul = mul nsw i64 %1, %0
|
||||||
|
store i64 %mul, i64* @kkkk, align 8
|
||||||
|
; 16: multu ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mfhi ${{[0-9]+}}
|
||||||
|
; 16: mult ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mflo ${{[0-9]+}}
|
||||||
|
; 16: mult ${{[0-9]+}}, ${{[0-9]+}}
|
||||||
|
; 16: mflo ${{[0-9]+}}
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
Reference in New Issue