[mips] Fix DSP instructions to have explicit accumulator register operands.

Check that instruction selection can select multiply-add/sub DSP instructions
from a pattern that doesn't have intrinsics.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178406 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2013-03-30 01:58:00 +00:00
parent 7e287bfb58
commit 2c2c33a167
4 changed files with 206 additions and 243 deletions

View File

@ -138,10 +138,10 @@ static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeACRegsRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBranchTarget(MCInst &Inst,
unsigned Offset,
@ -484,14 +484,14 @@ static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
return MCDisassembler::Success;
}
static DecodeStatus DecodeACRegsRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo >= 4)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::ACRegsRegClassID, RegNo);
unsigned Reg = getReg(Decoder, Mips::ACRegsDSPRegClassID, RegNo);
Inst.addOperand(MCOperand::CreateReg(Reg));
return MCDisassembler::Success;
}

View File

@ -20,17 +20,18 @@ def immZExt10 : ImmLeaf<i32, [{return isUInt<10>(Imm);}]>;
def immSExt6 : ImmLeaf<i32, [{return isInt<6>(Imm);}]>;
// Mips-specific dsp nodes
def SDT_MipsExtr : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>]>;
def SDT_MipsShilo : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
def SDT_MipsDPA : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>]>;
def SDT_MipsExtr : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
SDTCisVT<2, untyped>]>;
def SDT_MipsShilo : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
SDTCisSameAs<0, 2>, SDTCisVT<1, i32>]>;
def SDT_MipsDPA : SDTypeProfile<1, 3, [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>,
SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
class MipsDSPBase<string Opc, SDTypeProfile Prof> :
SDNode<!strconcat("MipsISD::", Opc), Prof,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
SDNode<!strconcat("MipsISD::", Opc), Prof>;
class MipsDSPSideEffectBase<string Opc, SDTypeProfile Prof> :
SDNode<!strconcat("MipsISD::", Opc), Prof,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPSideEffect]>;
SDNode<!strconcat("MipsISD::", Opc), Prof, [SDNPHasChain, SDNPSideEffect]>;
def MipsEXTP : MipsDSPSideEffectBase<"EXTP", SDT_MipsExtr>;
def MipsEXTPDP : MipsDSPSideEffectBase<"EXTPDP", SDT_MipsExtr>;
@ -40,7 +41,7 @@ def MipsEXTR_R_W : MipsDSPSideEffectBase<"EXTR_R_W", SDT_MipsExtr>;
def MipsEXTR_RS_W : MipsDSPSideEffectBase<"EXTR_RS_W", SDT_MipsExtr>;
def MipsSHILO : MipsDSPBase<"SHILO", SDT_MipsShilo>;
def MipsMTHLIP : MipsDSPBase<"MTHLIP", SDT_MipsShilo>;
def MipsMTHLIP : MipsDSPSideEffectBase<"MTHLIP", SDT_MipsShilo>;
def MipsMULSAQ_S_W_PH : MipsDSPSideEffectBase<"MULSAQ_S_W_PH", SDT_MipsDPA>;
def MipsMAQ_S_W_PHL : MipsDSPSideEffectBase<"MAQ_S_W_PHL", SDT_MipsDPA>;
@ -383,7 +384,7 @@ class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs CPURegs:$rt);
dag InOperandList = (ins ACRegs:$ac, CPURegs:$shift_rs);
dag InOperandList = (ins ACRegsDSP:$ac, CPURegs:$shift_rs);
string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs");
InstrItinClass Itinerary = itin;
list<Register> Defs = [DSPCtrl];
@ -392,46 +393,40 @@ class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs CPURegs:$rt);
dag InOperandList = (ins ACRegs:$ac, uimm16:$shift_rs);
dag InOperandList = (ins ACRegsDSP:$ac, uimm16:$shift_rs);
string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs");
InstrItinClass Itinerary = itin;
list<Register> Defs = [DSPCtrl];
}
class SHILO_R1_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
Instruction realinst> :
PseudoDSP<(outs), (ins simm16:$shift), [(OpNode immSExt6:$shift)]>,
PseudoInstExpansion<(realinst AC0, simm16:$shift)> {
list<Register> Defs = [DSPCtrl, AC0];
list<Register> Uses = [AC0];
InstrItinClass Itinerary = itin;
}
class SHILO_R1_DESC_BASE<string instr_asm> {
dag OutOperandList = (outs ACRegs:$ac);
dag InOperandList = (ins simm16:$shift);
class SHILO_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins simm16:$shift, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$ac, $shift");
list<dag> Pattern = [(set ACRegsDSP:$ac,
(OpNode immSExt6:$shift, ACRegsDSP:$acin))];
list<Register> Defs = [DSPCtrl];
string Constraints = "$acin = $ac";
}
class SHILO_R2_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
Instruction realinst> :
PseudoDSP<(outs), (ins CPURegs:$rs), [(OpNode CPURegs:$rs)]>,
PseudoInstExpansion<(realinst AC0, CPURegs:$rs)> {
list<Register> Defs = [DSPCtrl, AC0];
list<Register> Uses = [AC0];
InstrItinClass Itinerary = itin;
}
class SHILO_R2_DESC_BASE<string instr_asm> {
dag OutOperandList = (outs ACRegs:$ac);
dag InOperandList = (ins CPURegs:$rs);
class SHILO_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins CPURegs:$rs, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$ac, $rs");
list<dag> Pattern = [(set ACRegsDSP:$ac,
(OpNode CPURegs:$rs, ACRegsDSP:$acin))];
list<Register> Defs = [DSPCtrl];
string Constraints = "$acin = $ac";
}
class MTHLIP_DESC_BASE<string instr_asm> {
dag OutOperandList = (outs ACRegs:$ac);
dag InOperandList = (ins CPURegs:$rs);
class MTHLIP_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins CPURegs:$rs, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$rs, $ac");
list<dag> Pattern = [(set ACRegsDSP:$ac,
(OpNode CPURegs:$rs, ACRegsDSP:$acin))];
list<Register> Uses = [DSPCtrl];
string Constraints = "$acin = $ac";
}
class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@ -454,35 +449,37 @@ class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
list<Register> Defs = [DSPCtrl];
}
class DPA_W_PH_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
Instruction realinst> :
PseudoDSP<(outs), (ins CPURegs:$rs, CPURegs:$rt),
[(OpNode CPURegs:$rs, CPURegs:$rt)]>,
PseudoInstExpansion<(realinst AC0, CPURegs:$rs, CPURegs:$rt)> {
list<Register> Defs = [DSPCtrl, AC0];
list<Register> Uses = [AC0];
InstrItinClass Itinerary = itin;
class DPA_W_PH_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
list<dag> Pattern = [(set ACRegsDSP:$ac,
(OpNode CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin))];
list<Register> Defs = [DSPCtrl];
string Constraints = "$acin = $ac";
}
class DPA_W_PH_DESC_BASE<string instr_asm> {
dag OutOperandList = (outs ACRegs:$ac);
class MULT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt);
string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
}
class MULT_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
Instruction realinst> :
PseudoDSP<(outs), (ins CPURegs:$rs, CPURegs:$rt),
[(OpNode CPURegs:$rs, CPURegs:$rt)]>,
PseudoInstExpansion<(realinst AC0, CPURegs:$rs, CPURegs:$rt)> {
list<Register> Defs = [DSPCtrl, AC0];
list<dag> Pattern = [(set ACRegsDSP:$ac, (OpNode CPURegs:$rs, CPURegs:$rt))];
InstrItinClass Itinerary = itin;
int AddedComplexity = 20;
bit isCommutable = 1;
}
class MULT_DESC_BASE<string instr_asm> {
dag OutOperandList = (outs ACRegs:$ac);
dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt);
class MADD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
list<dag> Pattern = [(set ACRegsDSP:$ac,
(OpNode CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin))];
InstrItinClass Itinerary = itin;
int AddedComplexity = 20;
string Constraints = "$acin = $ac";
}
class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> :
@ -717,44 +714,40 @@ class MULQ_RS_PH_DESC : ADDU_QB_DESC_BASE<"mulq_rs.ph", int_mips_mulq_rs_ph,
NoItinerary, DSPRegs, DSPRegs>,
IsCommutable;
class MULSAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsaq_s.w.ph">;
class MULSAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsaq_s.w.ph",
MipsMULSAQ_S_W_PH>;
class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl">;
class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl", MipsMAQ_S_W_PHL>;
class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr">;
class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr", MipsMAQ_S_W_PHR>;
class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl">;
class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl", MipsMAQ_SA_W_PHL>;
class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr">;
class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr", MipsMAQ_SA_W_PHR>;
// Dot product with accumulate/subtract
class DPAU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbl">;
class DPAU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbl", MipsDPAU_H_QBL>;
class DPAU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbr">;
class DPAU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbr", MipsDPAU_H_QBR>;
class DPSU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbl">;
class DPSU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbl", MipsDPSU_H_QBL>;
class DPSU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbr">;
class DPSU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbr", MipsDPSU_H_QBR>;
class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph">;
class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph", MipsDPAQ_S_W_PH>;
class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph">;
class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph", MipsDPSQ_S_W_PH>;
class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w">;
class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w", MipsDPAQ_SA_L_W>;
class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w">;
class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w", MipsDPSQ_SA_L_W>;
class MULT_DSP_DESC : MULT_DESC_BASE<"mult">;
class MULTU_DSP_DESC : MULT_DESC_BASE<"multu">;
class MADD_DSP_DESC : MULT_DESC_BASE<"madd">;
class MADDU_DSP_DESC : MULT_DESC_BASE<"maddu">;
class MSUB_DSP_DESC : MULT_DESC_BASE<"msub">;
class MSUBU_DSP_DESC : MULT_DESC_BASE<"msubu">;
class MULT_DSP_DESC : MULT_DESC_BASE<"mult", MipsMult, NoItinerary>;
class MULTU_DSP_DESC : MULT_DESC_BASE<"multu", MipsMultu, NoItinerary>;
class MADD_DSP_DESC : MADD_DESC_BASE<"madd", MipsMAdd, NoItinerary>;
class MADDU_DSP_DESC : MADD_DESC_BASE<"maddu", MipsMAddu, NoItinerary>;
class MSUB_DSP_DESC : MADD_DESC_BASE<"msub", MipsMSub, NoItinerary>;
class MSUBU_DSP_DESC : MADD_DESC_BASE<"msubu", MipsMSubu, NoItinerary>;
// Comparison
class CMPU_EQ_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.eq.qb",
@ -867,11 +860,11 @@ class EXTR_S_H_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_s.h", MipsEXTR_S_H,
class EXTRV_S_H_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_s.h", MipsEXTR_S_H,
NoItinerary>;
class SHILO_DESC : SHILO_R1_DESC_BASE<"shilo">;
class SHILO_DESC : SHILO_R1_DESC_BASE<"shilo", MipsSHILO>;
class SHILOV_DESC : SHILO_R2_DESC_BASE<"shilov">;
class SHILOV_DESC : SHILO_R2_DESC_BASE<"shilov", MipsSHILO>;
class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip">;
class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip", MipsMTHLIP>;
class RDDSP_DESC : RDDSP_DESC_BASE<"rddsp", int_mips_rddsp, NoItinerary>;
@ -975,23 +968,25 @@ class MULQ_S_PH_DESC : ADDU_QB_DESC_BASE<"mulq_s.ph", int_mips_mulq_s_ph,
IsCommutable;
// Dot product with accumulate/subtract
class DPA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpa.w.ph">;
class DPA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpa.w.ph", MipsDPA_W_PH>;
class DPS_W_PH_DESC : DPA_W_PH_DESC_BASE<"dps.w.ph">;
class DPS_W_PH_DESC : DPA_W_PH_DESC_BASE<"dps.w.ph", MipsDPS_W_PH>;
class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph">;
class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph", MipsDPAQX_S_W_PH>;
class DPAQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_sa.w.ph">;
class DPAQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_sa.w.ph",
MipsDPAQX_SA_W_PH>;
class DPAX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpax.w.ph">;
class DPAX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpax.w.ph", MipsDPAX_W_PH>;
class DPSX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsx.w.ph">;
class DPSX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsx.w.ph", MipsDPSX_W_PH>;
class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph">;
class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph", MipsDPSQX_S_W_PH>;
class DPSQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_sa.w.ph">;
class DPSQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_sa.w.ph",
MipsDPSQX_SA_W_PH>;
class MULSA_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsa.w.ph">;
class MULSA_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsa.w.ph", MipsMULSA_W_PH>;
// Precision reduce/expand
class PRECR_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precr.qb.ph",
@ -1206,71 +1201,6 @@ def PREPEND : PREPEND_ENC, PREPEND_DESC;
}
// Pseudos.
def MULSAQ_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMULSAQ_S_W_PH, NoItinerary,
MULSAQ_S_W_PH>;
def MAQ_S_W_PHL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_S_W_PHL, NoItinerary,
MAQ_S_W_PHL>;
def MAQ_S_W_PHR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_S_W_PHR, NoItinerary,
MAQ_S_W_PHR>;
def MAQ_SA_W_PHL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_SA_W_PHL, NoItinerary,
MAQ_SA_W_PHL>;
def MAQ_SA_W_PHR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_SA_W_PHR, NoItinerary,
MAQ_SA_W_PHR>;
def DPAU_H_QBL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAU_H_QBL, NoItinerary,
DPAU_H_QBL>;
def DPAU_H_QBR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAU_H_QBR, NoItinerary,
DPAU_H_QBR>;
def DPSU_H_QBL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSU_H_QBL, NoItinerary,
DPSU_H_QBL>;
def DPSU_H_QBR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSU_H_QBR, NoItinerary,
DPSU_H_QBR>;
def DPAQ_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQ_S_W_PH, NoItinerary,
DPAQ_S_W_PH>;
def DPSQ_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQ_S_W_PH, NoItinerary,
DPSQ_S_W_PH>;
def DPAQ_SA_L_W_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQ_SA_L_W, NoItinerary,
DPAQ_SA_L_W>;
def DPSQ_SA_L_W_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQ_SA_L_W, NoItinerary,
DPSQ_SA_L_W>;
def MULT_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMULT, NoItinerary, MULT_DSP>,
IsCommutable;
def MULTU_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMULTU, NoItinerary, MULTU_DSP>,
IsCommutable;
def MADD_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMADD_DSP, NoItinerary, MADD_DSP>,
IsCommutable, UseAC;
def MADDU_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMADDU_DSP, NoItinerary, MADDU_DSP>,
IsCommutable, UseAC;
def MSUB_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMSUB_DSP, NoItinerary, MSUB_DSP>,
UseAC;
def MSUBU_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMSUBU_DSP, NoItinerary, MSUBU_DSP>,
UseAC;
def SHILO_PSEUDO : SHILO_R1_PSEUDO_BASE<MipsSHILO, NoItinerary, SHILO>;
def SHILOV_PSEUDO : SHILO_R2_PSEUDO_BASE<MipsSHILO, NoItinerary, SHILOV>;
def MTHLIP_PSEUDO : SHILO_R2_PSEUDO_BASE<MipsMTHLIP, NoItinerary, MTHLIP>;
let Predicates = [HasDSPR2] in {
def DPA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPA_W_PH, NoItinerary, DPA_W_PH>;
def DPS_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPS_W_PH, NoItinerary, DPS_W_PH>;
def DPAQX_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQX_S_W_PH, NoItinerary,
DPAQX_S_W_PH>;
def DPAQX_SA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQX_SA_W_PH, NoItinerary,
DPAQX_SA_W_PH>;
def DPAX_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAX_W_PH, NoItinerary,
DPAX_W_PH>;
def DPSX_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSX_W_PH, NoItinerary,
DPSX_W_PH>;
def DPSQX_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQX_S_W_PH, NoItinerary,
DPSQX_S_W_PH>;
def DPSQX_SA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQX_SA_W_PH, NoItinerary,
DPSQX_SA_W_PH>;
def MULSA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMULSA_W_PH, NoItinerary,
MULSA_W_PH>;
}
/// Pseudo instructions for loading, storing and copying accumulator registers.
let isPseudo = 1 in {
defm LOAD_AC_DSP : LoadM<"load_ac_dsp", ACRegsDSP>;
@ -1304,10 +1234,12 @@ def : DSPPat<(store (v4i8 DSPRegs:$val), addr:$a),
// Extr patterns.
class EXTR_W_TY1_R2_Pat<SDPatternOperator OpNode, Instruction Instr> :
DSPPat<(i32 (OpNode CPURegs:$rs)), (Instr AC0, CPURegs:$rs)>;
DSPPat<(i32 (OpNode CPURegs:$rs, ACRegsDSP:$ac)),
(Instr ACRegsDSP:$ac, CPURegs:$rs)>;
class EXTR_W_TY1_R1_Pat<SDPatternOperator OpNode, Instruction Instr> :
DSPPat<(i32 (OpNode immZExt5:$shift)), (Instr AC0, immZExt5:$shift)>;
DSPPat<(i32 (OpNode immZExt5:$shift, ACRegsDSP:$ac)),
(Instr ACRegsDSP:$ac, immZExt5:$shift)>;
def : EXTR_W_TY1_R1_Pat<MipsEXTP, EXTP>;
def : EXTR_W_TY1_R2_Pat<MipsEXTP, EXTPV>;
@ -1321,3 +1253,8 @@ def : EXTR_W_TY1_R1_Pat<MipsEXTR_RS_W, EXTR_RS_W>;
def : EXTR_W_TY1_R2_Pat<MipsEXTR_RS_W, EXTRV_RS_W>;
def : EXTR_W_TY1_R1_Pat<MipsEXTR_S_H, EXTR_S_H>;
def : EXTR_W_TY1_R2_Pat<MipsEXTR_S_H, EXTRV_S_H>;
// mflo/hi patterns.
let AddedComplexity = 20 in
def : DSPPat<(i32 (ExtractLOHI ACRegsDSP:$ac, imm:$lohi_idx)),
(EXTRACT_SUBREG ACRegsDSP:$ac, imm:$lohi_idx)>;

View File

@ -2050,6 +2050,22 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
return CreateStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7);
}
static SDValue initAccumulator(SDValue In, DebugLoc DL, SelectionDAG &DAG) {
SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
DAG.getConstant(0, MVT::i32));
SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
DAG.getConstant(1, MVT::i32));
return DAG.getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, InLo, InHi);
}
static SDValue extractLOHI(SDValue Op, DebugLoc DL, SelectionDAG &DAG) {
SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op,
DAG.getConstant(Mips::sub_lo, MVT::i32));
SDValue Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op,
DAG.getConstant(Mips::sub_hi, MVT::i32));
return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
}
// This function expands mips intrinsic nodes which have 64-bit input operands
// or output values.
//
@ -2062,48 +2078,51 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
// v1 = copy hi
// out64 = merge-values (v0, v1)
//
static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG,
unsigned Opc, bool HasI64In, bool HasI64Out) {
static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
DebugLoc DL = Op.getDebugLoc();
bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
SDValue Chain = HasChainIn ? Op->getOperand(0) : DAG.getEntryNode();
SmallVector<SDValue, 3> Ops;
unsigned OpNo = 0;
if (HasI64In) {
SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32,
Op->getOperand(1 + HasChainIn),
DAG.getConstant(0, MVT::i32));
SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32,
Op->getOperand(1 + HasChainIn),
DAG.getConstant(1, MVT::i32));
// See if Op has a chain input.
if (HasChainIn)
Ops.push_back(Op->getOperand(OpNo++));
Chain = DAG.getCopyToReg(Chain, DL, Mips::LO, InLo, SDValue());
Chain = DAG.getCopyToReg(Chain, DL, Mips::HI, InHi, Chain.getValue(1));
// The next operand is the intrinsic opcode.
assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant);
Ops.push_back(Chain);
Ops.append(Op->op_begin() + HasChainIn + 2, Op->op_end());
Ops.push_back(Chain.getValue(1));
} else {
Ops.push_back(Chain);
Ops.append(Op->op_begin() + HasChainIn + 1, Op->op_end());
}
// See if the next operand has type i64.
SDValue Opnd = Op->getOperand(++OpNo), In64;
if (!HasI64Out)
return DAG.getNode(Opc, DL, Op->value_begin(), Op->getNumValues(),
Ops.begin(), Ops.size());
if (Opnd.getValueType() == MVT::i64)
In64 = initAccumulator(Opnd, DL, DAG);
else
Ops.push_back(Opnd);
SDValue Intr = DAG.getNode(Opc, DL, DAG.getVTList(MVT::Other, MVT::Glue),
Ops.begin(), Ops.size());
SDValue OutLo = DAG.getCopyFromReg(Intr.getValue(0), DL, Mips::LO, MVT::i32,
Intr.getValue(1));
SDValue OutHi = DAG.getCopyFromReg(OutLo.getValue(1), DL, Mips::HI, MVT::i32,
OutLo.getValue(2));
SDValue Out = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, OutLo, OutHi);
// Push the remaining operands.
for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo)
Ops.push_back(Op->getOperand(OpNo));
// Add In64 to the end of the list.
if (In64.getNode())
Ops.push_back(In64);
// Scan output.
SmallVector<EVT, 2> ResTys;
for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end();
I != E; ++I)
ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I);
// Create node.
SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size());
SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val;
if (!HasChainIn)
return Out;
SDValue Vals[] = { Out, OutHi.getValue(1) };
assert(Val->getValueType(1) == MVT::Other);
SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
return DAG.getMergeValues(Vals, 2, DL);
}
@ -2113,37 +2132,37 @@ SDValue MipsTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
default:
return SDValue();
case Intrinsic::mips_shilo:
return lowerDSPIntr(Op, DAG, MipsISD::SHILO, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::SHILO);
case Intrinsic::mips_dpau_h_qbl:
return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL);
case Intrinsic::mips_dpau_h_qbr:
return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR);
case Intrinsic::mips_dpsu_h_qbl:
return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL);
case Intrinsic::mips_dpsu_h_qbr:
return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR);
case Intrinsic::mips_dpa_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH);
case Intrinsic::mips_dps_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH);
case Intrinsic::mips_dpax_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH);
case Intrinsic::mips_dpsx_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH);
case Intrinsic::mips_mulsa_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH);
case Intrinsic::mips_mult:
return lowerDSPIntr(Op, DAG, MipsISD::MULT, false, true);
return lowerDSPIntr(Op, DAG, MipsISD::Mult);
case Intrinsic::mips_multu:
return lowerDSPIntr(Op, DAG, MipsISD::MULTU, false, true);
return lowerDSPIntr(Op, DAG, MipsISD::Multu);
case Intrinsic::mips_madd:
return lowerDSPIntr(Op, DAG, MipsISD::MADD_DSP, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MAdd);
case Intrinsic::mips_maddu:
return lowerDSPIntr(Op, DAG, MipsISD::MADDU_DSP, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MAddu);
case Intrinsic::mips_msub:
return lowerDSPIntr(Op, DAG, MipsISD::MSUB_DSP, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MSub);
case Intrinsic::mips_msubu:
return lowerDSPIntr(Op, DAG, MipsISD::MSUBU_DSP, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MSubu);
}
}
@ -2153,45 +2172,45 @@ SDValue MipsTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
default:
return SDValue();
case Intrinsic::mips_extp:
return lowerDSPIntr(Op, DAG, MipsISD::EXTP, true, false);
return lowerDSPIntr(Op, DAG, MipsISD::EXTP);
case Intrinsic::mips_extpdp:
return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP, true, false);
return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP);
case Intrinsic::mips_extr_w:
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W, true, false);
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W);
case Intrinsic::mips_extr_r_w:
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W, true, false);
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W);
case Intrinsic::mips_extr_rs_w:
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W, true, false);
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W);
case Intrinsic::mips_extr_s_h:
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H, true, false);
return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H);
case Intrinsic::mips_mthlip:
return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP);
case Intrinsic::mips_mulsaq_s_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH);
case Intrinsic::mips_maq_s_w_phl:
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL);
case Intrinsic::mips_maq_s_w_phr:
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR);
case Intrinsic::mips_maq_sa_w_phl:
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL);
case Intrinsic::mips_maq_sa_w_phr:
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR);
case Intrinsic::mips_dpaq_s_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH);
case Intrinsic::mips_dpsq_s_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH);
case Intrinsic::mips_dpaq_sa_l_w:
return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W);
case Intrinsic::mips_dpsq_sa_l_w:
return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W);
case Intrinsic::mips_dpaqx_s_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH);
case Intrinsic::mips_dpaqx_sa_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH);
case Intrinsic::mips_dpsqx_s_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH);
case Intrinsic::mips_dpsqx_sa_w_ph:
return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH, true, true);
return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH);
}
}

View File

@ -1,7 +1,9 @@
; RUN: llc -march=mips < %s | FileCheck %s
; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=32
; RUN: llc -march=mips -mattr=dsp < %s | FileCheck %s -check-prefix=DSP
; RUN: llc -march=mips -mcpu=mips16 < %s
; CHECK: madd
; 32: madd ${{[0-9]+}}
; DSP: madd $ac
define i64 @madd1(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
@ -12,7 +14,8 @@ entry:
ret i64 %add
}
; CHECK: maddu
; 32: maddu ${{[0-9]+}}
; DSP: maddu $ac
define i64 @madd2(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = zext i32 %a to i64
@ -23,7 +26,8 @@ entry:
ret i64 %add
}
; CHECK: madd
; 32: madd ${{[0-9]+}}
; DSP: madd $ac
define i64 @madd3(i32 %a, i32 %b, i64 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
@ -33,7 +37,8 @@ entry:
ret i64 %add
}
; CHECK: msub
; 32: msub ${{[0-9]+}}
; DSP: msub $ac
define i64 @msub1(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = sext i32 %c to i64
@ -44,7 +49,8 @@ entry:
ret i64 %sub
}
; CHECK: msubu
; 32: msubu ${{[0-9]+}}
; DSP: msubu $ac
define i64 @msub2(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = zext i32 %c to i64
@ -55,7 +61,8 @@ entry:
ret i64 %sub
}
; CHECK: msub
; 32: msub ${{[0-9]+}}
; DSP: msub $ac
define i64 @msub3(i32 %a, i32 %b, i64 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64