forked from OSchip/llvm-project
[mips] Fix definition of mfhi and mflo instructions to read from the whole
accumulator instead of its sub-registers, $hi and $lo. We need this change to prevent a mflo following a mtlo from reading an unpredictable/undefined value, as shown in the following example: mult $6, $7 // result of $6 * $7 is written to $lo and $hi. mflo $2 // read lower 32-bit result from $lo. mtlo $4 // write to $lo. the content of $hi becomes unpredictable. mfhi $3 // read higher 32-bit from $hi, which has an unpredictable value. I don't have a test case for this change that reliably reproduces the problem. llvm-svn: 192119
This commit is contained in:
parent
0aafb58aca
commit
16048332f1
|
@ -129,9 +129,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
|
||||||
MTLO_FM_MM<0x0b5>;
|
MTLO_FM_MM<0x0b5>;
|
||||||
def MTLO_MM : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>,
|
def MTLO_MM : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>,
|
||||||
MTLO_FM_MM<0x0f5>;
|
MTLO_FM_MM<0x0f5>;
|
||||||
def MFHI_MM : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, [HI0]>,
|
def MFHI_MM : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>,
|
||||||
MFLO_FM_MM<0x035>;
|
MFLO_FM_MM<0x035>;
|
||||||
def MFLO_MM : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, [LO0]>,
|
def MFLO_MM : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>,
|
||||||
MFLO_FM_MM<0x075>;
|
MFLO_FM_MM<0x075>;
|
||||||
|
|
||||||
/// Multiply Add/Sub Instructions
|
/// Multiply Add/Sub Instructions
|
||||||
|
|
|
@ -181,8 +181,10 @@ def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU,
|
||||||
let isCodeGenOnly = 1 in {
|
let isCodeGenOnly = 1 in {
|
||||||
def MTHI64 : MoveToLOHI<"mthi", GPR64Opnd, [HI0_64]>, MTLO_FM<0x11>;
|
def MTHI64 : MoveToLOHI<"mthi", GPR64Opnd, [HI0_64]>, MTLO_FM<0x11>;
|
||||||
def MTLO64 : MoveToLOHI<"mtlo", GPR64Opnd, [LO0_64]>, MTLO_FM<0x13>;
|
def MTLO64 : MoveToLOHI<"mtlo", GPR64Opnd, [LO0_64]>, MTLO_FM<0x13>;
|
||||||
def MFHI64 : MoveFromLOHI<"mfhi", GPR64Opnd, [HI0_64]>, MFLO_FM<0x10>;
|
def MFHI64 : MoveFromLOHI<"mfhi", GPR64Opnd, AC0_64>, MFLO_FM<0x10>;
|
||||||
def MFLO64 : MoveFromLOHI<"mflo", GPR64Opnd, [LO0_64]>, MFLO_FM<0x12>;
|
def MFLO64 : MoveFromLOHI<"mflo", GPR64Opnd, AC0_64>, MFLO_FM<0x12>;
|
||||||
|
def PseudoMFHI64 : PseudoMFLOHI<GPR64, ACC128, MipsExtractHI>;
|
||||||
|
def PseudoMFLO64 : PseudoMFLOHI<GPR64, ACC128, MipsExtractLO>;
|
||||||
|
|
||||||
/// Sign Ext In Register Instructions.
|
/// Sign Ext In Register Instructions.
|
||||||
def SEB64 : SignExtInReg<"seb", i8, GPR64Opnd>, SEB_FM<0x10, 0x20>;
|
def SEB64 : SignExtInReg<"seb", i8, GPR64Opnd>, SEB_FM<0x10, 0x20>;
|
||||||
|
@ -297,10 +299,6 @@ def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)),
|
||||||
// bswap MipsPattern
|
// bswap MipsPattern
|
||||||
def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>;
|
def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>;
|
||||||
|
|
||||||
// mflo/hi patterns.
|
|
||||||
def : MipsPat<(i64 (ExtractLOHI ACC128:$ac, imm:$lohi_idx)),
|
|
||||||
(EXTRACT_SUBREG ACC128:$ac, imm:$lohi_idx)>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Instruction aliases
|
// Instruction aliases
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -469,11 +469,14 @@ class MADD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||||
string Constraints = "$acin = $ac";
|
string Constraints = "$acin = $ac";
|
||||||
}
|
}
|
||||||
|
|
||||||
class MFHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> {
|
class MFHI_DESC_BASE<string instr_asm, RegisterOperand RO, SDNode OpNode,
|
||||||
|
InstrItinClass itin> {
|
||||||
dag OutOperandList = (outs GPR32Opnd:$rd);
|
dag OutOperandList = (outs GPR32Opnd:$rd);
|
||||||
dag InOperandList = (ins RO:$ac);
|
dag InOperandList = (ins RO:$ac);
|
||||||
string AsmString = !strconcat(instr_asm, "\t$rd, $ac");
|
string AsmString = !strconcat(instr_asm, "\t$rd, $ac");
|
||||||
|
list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode RO:$ac))];
|
||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
|
int AddedComplexity = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> {
|
class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> {
|
||||||
|
@ -736,8 +739,10 @@ class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr", MipsMAQ_SA_W_PHR>,
|
||||||
Defs<[DSPOutFlag16_19]>;
|
Defs<[DSPOutFlag16_19]>;
|
||||||
|
|
||||||
// Move from/to hi/lo.
|
// Move from/to hi/lo.
|
||||||
class MFHI_DESC : MFHI_DESC_BASE<"mfhi", HI32DSPOpnd, NoItinerary>;
|
class MFHI_DESC : MFHI_DESC_BASE<"mfhi", ACC64DSPOpnd, MipsExtractHI,
|
||||||
class MFLO_DESC : MFHI_DESC_BASE<"mflo", LO32DSPOpnd, NoItinerary>;
|
NoItinerary>;
|
||||||
|
class MFLO_DESC : MFHI_DESC_BASE<"mflo", ACC64DSPOpnd, MipsExtractLO,
|
||||||
|
NoItinerary>;
|
||||||
class MTHI_DESC : MTHI_DESC_BASE<"mthi", HI32DSPOpnd, NoItinerary>;
|
class MTHI_DESC : MTHI_DESC_BASE<"mthi", HI32DSPOpnd, NoItinerary>;
|
||||||
class MTLO_DESC : MTHI_DESC_BASE<"mtlo", LO32DSPOpnd, NoItinerary>;
|
class MTLO_DESC : MTHI_DESC_BASE<"mtlo", LO32DSPOpnd, NoItinerary>;
|
||||||
|
|
||||||
|
@ -1403,11 +1408,6 @@ 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_R1_Pat<MipsEXTR_S_H, EXTR_S_H>;
|
||||||
def : EXTR_W_TY1_R2_Pat<MipsEXTR_S_H, EXTRV_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 ACC64DSP:$ac, imm:$lohi_idx)),
|
|
||||||
(EXTRACT_SUBREG ACC64DSP:$ac, imm:$lohi_idx)>;
|
|
||||||
|
|
||||||
// Indexed load patterns.
|
// Indexed load patterns.
|
||||||
class IndexedLoadPat<SDPatternOperator LoadNode, Instruction Instr> :
|
class IndexedLoadPat<SDPatternOperator LoadNode, Instruction Instr> :
|
||||||
DSPPat<(i32 (LoadNode (add i32:$base, i32:$index))),
|
DSPPat<(i32 (LoadNode (add i32:$base, i32:$index))),
|
||||||
|
|
|
@ -126,7 +126,8 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||||
case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T";
|
case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T";
|
||||||
case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F";
|
case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F";
|
||||||
case MipsISD::TruncIntFP: return "MipsISD::TruncIntFP";
|
case MipsISD::TruncIntFP: return "MipsISD::TruncIntFP";
|
||||||
case MipsISD::ExtractLOHI: return "MipsISD::ExtractLOHI";
|
case MipsISD::ExtractHI: return "MipsISD::ExtractHI";
|
||||||
|
case MipsISD::ExtractLO: return "MipsISD::ExtractLO";
|
||||||
case MipsISD::InsertLOHI: return "MipsISD::InsertLOHI";
|
case MipsISD::InsertLOHI: return "MipsISD::InsertLOHI";
|
||||||
case MipsISD::Mult: return "MipsISD::Mult";
|
case MipsISD::Mult: return "MipsISD::Mult";
|
||||||
case MipsISD::Multu: return "MipsISD::Multu";
|
case MipsISD::Multu: return "MipsISD::Multu";
|
||||||
|
|
|
@ -70,7 +70,8 @@ namespace llvm {
|
||||||
EH_RETURN,
|
EH_RETURN,
|
||||||
|
|
||||||
// Node used to extract integer from accumulator.
|
// Node used to extract integer from accumulator.
|
||||||
ExtractLOHI,
|
ExtractHI,
|
||||||
|
ExtractLO,
|
||||||
|
|
||||||
// Node used to insert integers to accumulator.
|
// Node used to insert integers to accumulator.
|
||||||
InsertLOHI,
|
InsertLOHI,
|
||||||
|
|
|
@ -23,8 +23,7 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
|
||||||
SDTCisInt<4>]>;
|
SDTCisInt<4>]>;
|
||||||
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
||||||
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||||
def SDT_ExtractLOHI : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVT<1, untyped>,
|
def SDT_ExtractLOHI : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVT<1, untyped>]>;
|
||||||
SDTCisVT<2, i32>]>;
|
|
||||||
def SDT_InsertLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
|
def SDT_InsertLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
|
||||||
SDTCisVT<1, i32>,
|
SDTCisVT<1, i32>,
|
||||||
SDTCisSameAs<1, 2>]>;
|
SDTCisSameAs<1, 2>]>;
|
||||||
|
@ -86,8 +85,9 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
|
||||||
[SDNPHasChain, SDNPSideEffect,
|
[SDNPHasChain, SDNPSideEffect,
|
||||||
SDNPOptInGlue, SDNPOutGlue]>;
|
SDNPOptInGlue, SDNPOutGlue]>;
|
||||||
|
|
||||||
// Node used to extract integer from LO/HI register.
|
// Nodes used to extract LO/HI registers.
|
||||||
def ExtractLOHI : SDNode<"MipsISD::ExtractLOHI", SDT_ExtractLOHI>;
|
def MipsExtractHI : SDNode<"MipsISD::ExtractHI", SDT_ExtractLOHI>;
|
||||||
|
def MipsExtractLO : SDNode<"MipsISD::ExtractLO", SDT_ExtractLOHI>;
|
||||||
|
|
||||||
// Node used to insert 32-bit integers to LOHI register pair.
|
// Node used to insert 32-bit integers to LOHI register pair.
|
||||||
def InsertLOHI : SDNode<"MipsISD::InsertLOHI", SDT_InsertLOHI>;
|
def InsertLOHI : SDNode<"MipsISD::InsertLOHI", SDT_InsertLOHI>;
|
||||||
|
@ -697,10 +697,14 @@ class Div<string opstr, InstrItinClass itin, RegisterOperand RO,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move from Hi/Lo
|
// Move from Hi/Lo
|
||||||
class MoveFromLOHI<string opstr, RegisterOperand RO, list<Register> UseRegs>:
|
class PseudoMFLOHI<RegisterClass DstRC, RegisterClass SrcRC, SDNode OpNode>
|
||||||
InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], IIHiLo,
|
: PseudoSE<(outs DstRC:$rd), (ins SrcRC:$hilo),
|
||||||
FrmR, opstr> {
|
[(set DstRC:$rd, (OpNode SrcRC:$hilo))], IIHiLo>;
|
||||||
let Uses = UseRegs;
|
|
||||||
|
class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>:
|
||||||
|
InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], IIHiLo, FrmR,
|
||||||
|
opstr> {
|
||||||
|
let Uses = [UseReg];
|
||||||
let neverHasSideEffects = 1;
|
let neverHasSideEffects = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1035,8 +1039,10 @@ def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, IIIdiv,
|
||||||
|
|
||||||
def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>;
|
def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>;
|
||||||
def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>;
|
def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>;
|
||||||
def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, [HI0]>, MFLO_FM<0x10>;
|
def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>;
|
||||||
def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, [LO0]>, MFLO_FM<0x12>;
|
def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>;
|
||||||
|
def PseudoMFHI : PseudoMFLOHI<GPR32, ACC64, MipsExtractHI>;
|
||||||
|
def PseudoMFLO : PseudoMFLOHI<GPR32, ACC64, MipsExtractLO>;
|
||||||
|
|
||||||
/// Sign Ext In Register Instructions.
|
/// Sign Ext In Register Instructions.
|
||||||
def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd>, SEB_FM<0x10, 0x20>;
|
def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd>, SEB_FM<0x10, 0x20>;
|
||||||
|
@ -1349,10 +1355,6 @@ defm : SetgeImmPats<GPR32, SLTi, SLTiu>;
|
||||||
// bswap pattern
|
// bswap pattern
|
||||||
def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
|
def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
|
||||||
|
|
||||||
// mflo/hi patterns.
|
|
||||||
def : MipsPat<(i32 (ExtractLOHI ACC64:$ac, imm:$lohi_idx)),
|
|
||||||
(EXTRACT_SUBREG ACC64:$ac, imm:$lohi_idx)>;
|
|
||||||
|
|
||||||
// Load halfword/word patterns.
|
// Load halfword/word patterns.
|
||||||
let AddedComplexity = 40 in {
|
let AddedComplexity = 40 in {
|
||||||
let Predicates = [HasStdEnc] in {
|
let Predicates = [HasStdEnc] in {
|
||||||
|
|
|
@ -32,6 +32,21 @@ using namespace llvm;
|
||||||
namespace {
|
namespace {
|
||||||
typedef MachineBasicBlock::iterator Iter;
|
typedef MachineBasicBlock::iterator Iter;
|
||||||
|
|
||||||
|
static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) {
|
||||||
|
if (Mips::ACC64RegClass.contains(Src))
|
||||||
|
return std::make_pair((unsigned)Mips::PseudoMFHI,
|
||||||
|
(unsigned)Mips::PseudoMFLO);
|
||||||
|
|
||||||
|
if (Mips::ACC64DSPRegClass.contains(Src))
|
||||||
|
return std::make_pair((unsigned)Mips::MFHI_DSP, (unsigned)Mips::MFLO_DSP);
|
||||||
|
|
||||||
|
if (Mips::ACC128RegClass.contains(Src))
|
||||||
|
return std::make_pair((unsigned)Mips::PseudoMFHI64,
|
||||||
|
(unsigned)Mips::PseudoMFLO64);
|
||||||
|
|
||||||
|
return std::make_pair(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper class to expand pseudos.
|
/// Helper class to expand pseudos.
|
||||||
class ExpandPseudo {
|
class ExpandPseudo {
|
||||||
public:
|
public:
|
||||||
|
@ -43,10 +58,11 @@ private:
|
||||||
void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
|
void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
|
||||||
void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
|
void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
|
||||||
void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
|
void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
|
||||||
void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
|
void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
|
||||||
|
unsigned MFLoOpc, unsigned RegSize);
|
||||||
bool expandCopy(MachineBasicBlock &MBB, Iter I);
|
bool expandCopy(MachineBasicBlock &MBB, Iter I);
|
||||||
bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
|
bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
|
||||||
unsigned Src, unsigned RegSize);
|
unsigned MFLoOpc);
|
||||||
|
|
||||||
MachineFunction &MF;
|
MachineFunction &MF;
|
||||||
MachineRegisterInfo &MRI;
|
MachineRegisterInfo &MRI;
|
||||||
|
@ -83,11 +99,13 @@ bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) {
|
||||||
expandLoadACC(MBB, I, 8);
|
expandLoadACC(MBB, I, 8);
|
||||||
break;
|
break;
|
||||||
case Mips::STORE_ACC64:
|
case Mips::STORE_ACC64:
|
||||||
|
expandStoreACC(MBB, I, Mips::PseudoMFHI, Mips::PseudoMFLO, 4);
|
||||||
|
break;
|
||||||
case Mips::STORE_ACC64DSP:
|
case Mips::STORE_ACC64DSP:
|
||||||
expandStoreACC(MBB, I, 4);
|
expandStoreACC(MBB, I, Mips::MFHI_DSP, Mips::MFLO_DSP, 4);
|
||||||
break;
|
break;
|
||||||
case Mips::STORE_ACC128:
|
case Mips::STORE_ACC128:
|
||||||
expandStoreACC(MBB, I, 8);
|
expandStoreACC(MBB, I, Mips::PseudoMFHI64, Mips::PseudoMFLO64, 8);
|
||||||
break;
|
break;
|
||||||
case TargetOpcode::COPY:
|
case TargetOpcode::COPY:
|
||||||
if (!expandCopy(MBB, I))
|
if (!expandCopy(MBB, I))
|
||||||
|
@ -171,10 +189,11 @@ void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
|
void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
|
||||||
|
unsigned MFHiOpc, unsigned MFLoOpc,
|
||||||
unsigned RegSize) {
|
unsigned RegSize) {
|
||||||
// copy $vr0, lo
|
// mflo $vr0, src
|
||||||
// store $vr0, FI
|
// store $vr0, FI
|
||||||
// copy $vr1, hi
|
// mfhi $vr1, src
|
||||||
// store $vr1, FI + 4
|
// store $vr1, FI + 4
|
||||||
|
|
||||||
assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
|
assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
|
||||||
|
@ -189,33 +208,29 @@ void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
|
||||||
unsigned VR1 = MRI.createVirtualRegister(RC);
|
unsigned VR1 = MRI.createVirtualRegister(RC);
|
||||||
unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
|
unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
|
||||||
unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
|
unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
|
||||||
unsigned Lo = RegInfo.getSubReg(Src, Mips::sub_lo);
|
|
||||||
unsigned Hi = RegInfo.getSubReg(Src, Mips::sub_hi);
|
|
||||||
DebugLoc DL = I->getDebugLoc();
|
DebugLoc DL = I->getDebugLoc();
|
||||||
|
|
||||||
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(Lo, SrcKill);
|
BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
|
||||||
TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
|
TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
|
||||||
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(Hi, SrcKill);
|
BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
|
||||||
TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
|
TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
|
bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
|
||||||
unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
|
unsigned Src = I->getOperand(1).getReg();
|
||||||
|
std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src);
|
||||||
|
|
||||||
if (Mips::ACC64DSPRegClass.contains(Dst, Src))
|
if (!Opcodes.first)
|
||||||
return expandCopyACC(MBB, I, Dst, Src, 4);
|
return false;
|
||||||
|
|
||||||
if (Mips::ACC128RegClass.contains(Dst, Src))
|
return expandCopyACC(MBB, I, Opcodes.first, Opcodes.second);
|
||||||
return expandCopyACC(MBB, I, Dst, Src, 8);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
|
bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I,
|
||||||
unsigned Src, unsigned RegSize) {
|
unsigned MFHiOpc, unsigned MFLoOpc) {
|
||||||
// copy $vr0, src_lo
|
// mflo $vr0, src
|
||||||
// copy dst_lo, $vr0
|
// copy dst_lo, $vr0
|
||||||
// copy $vr1, src_hi
|
// mfhi $vr1, src
|
||||||
// copy dst_hi, $vr1
|
// copy dst_hi, $vr1
|
||||||
|
|
||||||
const MipsSEInstrInfo &TII =
|
const MipsSEInstrInfo &TII =
|
||||||
|
@ -223,20 +238,20 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
|
||||||
const MipsRegisterInfo &RegInfo =
|
const MipsRegisterInfo &RegInfo =
|
||||||
*static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
*static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||||
|
|
||||||
const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
|
unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
|
||||||
|
unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2;
|
||||||
|
const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize);
|
||||||
unsigned VR0 = MRI.createVirtualRegister(RC);
|
unsigned VR0 = MRI.createVirtualRegister(RC);
|
||||||
unsigned VR1 = MRI.createVirtualRegister(RC);
|
unsigned VR1 = MRI.createVirtualRegister(RC);
|
||||||
unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
|
unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
|
||||||
unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
|
unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
|
||||||
unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
|
unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
|
||||||
unsigned SrcLo = RegInfo.getSubReg(Src, Mips::sub_lo);
|
|
||||||
unsigned SrcHi = RegInfo.getSubReg(Src, Mips::sub_hi);
|
|
||||||
DebugLoc DL = I->getDebugLoc();
|
DebugLoc DL = I->getDebugLoc();
|
||||||
|
|
||||||
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(SrcLo, SrcKill);
|
BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
|
||||||
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
|
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
|
||||||
.addReg(VR0, RegState::Kill);
|
.addReg(VR0, RegState::Kill);
|
||||||
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(SrcHi, SrcKill);
|
BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
|
||||||
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
|
BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
|
||||||
.addReg(VR1, RegState::Kill);
|
.addReg(VR1, RegState::Kill);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -332,15 +332,11 @@ static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
|
||||||
|
|
||||||
// replace uses of adde and addc here
|
// replace uses of adde and addc here
|
||||||
if (!SDValue(ADDCNode, 0).use_empty()) {
|
if (!SDValue(ADDCNode, 0).use_empty()) {
|
||||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLO, DL, MVT::i32, MAdd);
|
||||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
|
||||||
LoIdx);
|
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
|
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
|
||||||
}
|
}
|
||||||
if (!SDValue(ADDENode, 0).use_empty()) {
|
if (!SDValue(ADDENode, 0).use_empty()) {
|
||||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractHI, DL, MVT::i32, MAdd);
|
||||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
|
||||||
HiIdx);
|
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
|
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,15 +404,11 @@ static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
|
||||||
|
|
||||||
// replace uses of sube and subc here
|
// replace uses of sube and subc here
|
||||||
if (!SDValue(SUBCNode, 0).use_empty()) {
|
if (!SDValue(SUBCNode, 0).use_empty()) {
|
||||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLO, DL, MVT::i32, MSub);
|
||||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
|
||||||
LoIdx);
|
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
|
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
|
||||||
}
|
}
|
||||||
if (!SDValue(SUBENode, 0).use_empty()) {
|
if (!SDValue(SUBENode, 0).use_empty()) {
|
||||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractHI, DL, MVT::i32, MSub);
|
||||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
|
||||||
HiIdx);
|
|
||||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
|
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,11 +938,9 @@ SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
|
||||||
SDValue Lo, Hi;
|
SDValue Lo, Hi;
|
||||||
|
|
||||||
if (HasLo)
|
if (HasLo)
|
||||||
Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult,
|
Lo = DAG.getNode(MipsISD::ExtractLO, DL, Ty, Mult);
|
||||||
DAG.getConstant(Mips::sub_lo, MVT::i32));
|
|
||||||
if (HasHi)
|
if (HasHi)
|
||||||
Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult,
|
Hi = DAG.getNode(MipsISD::ExtractHI, DL, Ty, Mult);
|
||||||
DAG.getConstant(Mips::sub_hi, MVT::i32));
|
|
||||||
|
|
||||||
if (!HasLo || !HasHi)
|
if (!HasLo || !HasHi)
|
||||||
return HasLo ? Lo : Hi;
|
return HasLo ? Lo : Hi;
|
||||||
|
@ -969,10 +959,8 @@ static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue extractLOHI(SDValue Op, SDLoc DL, SelectionDAG &DAG) {
|
static SDValue extractLOHI(SDValue Op, SDLoc DL, SelectionDAG &DAG) {
|
||||||
SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op,
|
SDValue Lo = DAG.getNode(MipsISD::ExtractLO, DL, MVT::i32, Op);
|
||||||
DAG.getConstant(Mips::sub_lo, MVT::i32));
|
SDValue Hi = DAG.getNode(MipsISD::ExtractHI, DL, MVT::i32, Op);
|
||||||
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);
|
return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,18 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
|
||||||
case Mips::RetRA:
|
case Mips::RetRA:
|
||||||
expandRetRA(MBB, MI, Mips::RET);
|
expandRetRA(MBB, MI, Mips::RET);
|
||||||
break;
|
break;
|
||||||
|
case Mips::PseudoMFHI:
|
||||||
|
expandPseudoMFHiLo(MBB, MI, Mips::MFHI);
|
||||||
|
break;
|
||||||
|
case Mips::PseudoMFLO:
|
||||||
|
expandPseudoMFHiLo(MBB, MI, Mips::MFLO);
|
||||||
|
break;
|
||||||
|
case Mips::PseudoMFHI64:
|
||||||
|
expandPseudoMFHiLo(MBB, MI, Mips::MFHI64);
|
||||||
|
break;
|
||||||
|
case Mips::PseudoMFLO64:
|
||||||
|
expandPseudoMFHiLo(MBB, MI, Mips::MFLO64);
|
||||||
|
break;
|
||||||
case Mips::PseudoCVT_S_W:
|
case Mips::PseudoCVT_S_W:
|
||||||
expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false);
|
expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false);
|
||||||
break;
|
break;
|
||||||
|
@ -414,6 +426,12 @@ MipsSEInstrInfo::compareOpndSize(unsigned Opc,
|
||||||
return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize);
|
return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator I,
|
||||||
|
unsigned NewOpc) const {
|
||||||
|
BuildMI(MBB, I, I->getDebugLoc(), get(NewOpc), I->getOperand(0).getReg());
|
||||||
|
}
|
||||||
|
|
||||||
void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB,
|
void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator I,
|
MachineBasicBlock::iterator I,
|
||||||
unsigned CvtOpc, unsigned MovOpc,
|
unsigned CvtOpc, unsigned MovOpc,
|
||||||
|
|
|
@ -87,6 +87,9 @@ private:
|
||||||
std::pair<bool, bool> compareOpndSize(unsigned Opc,
|
std::pair<bool, bool> compareOpndSize(unsigned Opc,
|
||||||
const MachineFunction &MF) const;
|
const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
void expandPseudoMFHiLo(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||||
|
unsigned NewOpc) const;
|
||||||
|
|
||||||
/// Expand pseudo Int-to-FP conversion instructions.
|
/// Expand pseudo Int-to-FP conversion instructions.
|
||||||
///
|
///
|
||||||
/// For example, the following pseudo instruction
|
/// For example, the following pseudo instruction
|
||||||
|
|
Loading…
Reference in New Issue