diff options
| author | Daniel Sanders <daniel.sanders@imgtec.com> | 2016-06-16 10:20:59 +0000 |
|---|---|---|
| committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2016-06-16 10:20:59 +0000 |
| commit | de7816b0cd3ffbd9775681c408298febe4c10fe3 (patch) | |
| tree | b87eea33d2ad56a884f14e805d373caea0fbbae8 /llvm/lib/Target | |
| parent | fa4d90d5aa7653aac7b309120b1aea236afcfa1e (diff) | |
| download | bcm5719-llvm-de7816b0cd3ffbd9775681c408298febe4c10fe3.tar.gz bcm5719-llvm-de7816b0cd3ffbd9775681c408298febe4c10fe3.zip | |
[mips][mips16] Fix machine verifier errors about incorrect register classes on load/stores.
Summary:
[ls][bh] and [ls][bh]u cannot use sp-relative addresses and must therefore
lower frameindex nodes such that there is a copy to a CPU16Regs register. This
is now done consistently using a separate addressing mode that does not
permit frameindex nodes.
As part of this I've had to remove an optimization that reduced the number of
instructions needed to work around the lack of sp-relative addresses on [ls][bh]
and [ls][bh]u. This optimization used one of the eight CPU16Regs registers as
a copy of the stack pointer and it's implementation was the root cause of many
of the register vs register class mismatches.
lw/sw can use sp-relative addresses but we ought to ensure that we use the
correct version of lw/sw internally for things like IAS. This is not currently
the case and this change does not fix this. However, this change does clean it
up sufficiently well to fix the machine verifier failures.
Also removed irrelevant functions from stchar.ll.
Reviewers: sdardis
Subscribers: dsanders, sdardis, llvm-commits
Differential Revision: http://reviews.llvm.org/D21062
llvm-svn: 272882
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp | 118 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Mips16InstrInfo.td | 69 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelDAGToDAG.h | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsMachineFunction.cpp | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsMachineFunction.h | 12 |
7 files changed, 76 insertions, 161 deletions
diff --git a/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index b4c4cfed085..6a4f44354b6 100644 --- a/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -91,88 +91,22 @@ void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { .addReg(V2); } -// Insert instructions to initialize the Mips16 SP Alias register in the -// first MBB of the function. -// -void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction &MF) { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - if (!MipsFI->mips16SPAliasRegSet()) - return; - - MachineBasicBlock &MBB = MF.front(); - MachineBasicBlock::iterator I = MBB.begin(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg(); - - BuildMI(MBB, I, DL, TII.get(Mips::MoveR3216), Mips16SPAliasReg) - .addReg(Mips::SP); -} - void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { initGlobalBaseReg(MF); - initMips16SPAliasReg(MF); } -/// getMips16SPAliasReg - Output the instructions required to put the -/// SP into a Mips16 accessible aliased register. -SDValue Mips16DAGToDAGISel::getMips16SPAliasReg() { - unsigned Mips16SPAliasReg = - MF->getInfo<MipsFunctionInfo>()->getMips16SPAliasReg(); - auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); - return CurDAG->getRegister(Mips16SPAliasReg, PtrVT); -} - -void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { - auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); - SDValue AliasFPReg = CurDAG->getRegister(Mips::S0, PtrVT); - if (Parent) { - switch (Parent->getOpcode()) { - case ISD::LOAD: { - LoadSDNode *SD = dyn_cast<LoadSDNode>(Parent); - switch (SD->getMemoryVT().getSizeInBits()) { - case 8: - case 16: - AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) - ? AliasFPReg - : getMips16SPAliasReg(); - return; - } - break; - } - case ISD::STORE: { - StoreSDNode *SD = dyn_cast<StoreSDNode>(Parent); - switch (SD->getMemoryVT().getSizeInBits()) { - case 8: - case 16: - AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) - ? AliasFPReg - : getMips16SPAliasReg(); - return; - } - break; - } - } - } - AliasReg = CurDAG->getRegister(Mips::SP, PtrVT); - return; -} - -bool Mips16DAGToDAGISel::selectAddr16(SDNode *Parent, SDValue Addr, - SDValue &Base, SDValue &Offset, - SDValue &Alias) { +bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, + SDValue &Offset) { SDLoc DL(Addr); EVT ValTy = Addr.getValueType(); - Alias = CurDAG->getTargetConstant(0, DL, ValTy); - // if Address is FI, get the TargetFrameIndex. - if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - Offset = CurDAG->getTargetConstant(0, DL, ValTy); - getMips16SPRefReg(Parent, Alias); - return true; + if (SPAllowed) { + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); + Offset = CurDAG->getTargetConstant(0, DL, ValTy); + return true; + } } // on PIC code Load GA if (Addr.getOpcode() == MipsISD::Wrapper) { @@ -189,15 +123,17 @@ bool Mips16DAGToDAGISel::selectAddr16(SDNode *Parent, SDValue Addr, if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { - // If the first operand is a FI, get the TargetFI Node - if (FrameIndexSDNode *FIN = - dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - getMips16SPRefReg(Parent, Alias); - } else - Base = Addr.getOperand(0); + if (SPAllowed) { + if (FrameIndexSDNode *FIN = + dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); + return true; + } + } + Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); return true; } @@ -222,22 +158,22 @@ bool Mips16DAGToDAGISel::selectAddr16(SDNode *Parent, SDValue Addr, return true; } } - - // If an indexed floating point load/store can be emitted, return false. - const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent); - - if (LS) { - if (LS->getMemoryVT() == MVT::f32 && Subtarget->hasMips4_32r2()) - return false; - if (LS->getMemoryVT() == MVT::f64 && Subtarget->hasMips4_32r2()) - return false; - } } Base = Addr; Offset = CurDAG->getTargetConstant(0, DL, ValTy); return true; } +bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, + SDValue &Offset) { + return selectAddr(false, Addr, Base, Offset); +} + +bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, + SDValue &Offset) { + return selectAddr(true, Addr, Base, Offset); +} + /// Select instructions not customized! Used for /// expanded, promoted and normal instructions bool Mips16DAGToDAGISel::trySelect(SDNode *Node) { diff --git a/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h b/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h index ac3df966fca..7c6a408594c 100644 --- a/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ b/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -27,14 +27,14 @@ private: const SDLoc &DL, EVT Ty, bool HasLo, bool HasHi); - SDValue getMips16SPAliasReg(); - bool runOnMachineFunction(MachineFunction &MF) override; - void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg); - - bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, SDValue &Offset, - SDValue &Alias) override; + bool selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, + SDValue &Offset); + bool selectAddr16(SDValue Addr, SDValue &Base, + SDValue &Offset) override; + bool selectAddr16SP(SDValue Addr, SDValue &Base, + SDValue &Offset) override; bool trySelect(SDNode *Node) override; diff --git a/llvm/lib/Target/Mips/Mips16InstrInfo.td b/llvm/lib/Target/Mips/Mips16InstrInfo.td index 40a7f79acdb..021fb867868 100644 --- a/llvm/lib/Target/Mips/Mips16InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips16InstrInfo.td @@ -14,14 +14,26 @@ // // Mips Address // -def addr16 : - ComplexPattern<iPTR, 3, "selectAddr16", [frameindex], [SDNPWantParent]>; +def addr16 : ComplexPattern<iPTR, 2, "selectAddr16", [frameindex]>; +def addr16sp : ComplexPattern<iPTR, 2, "selectAddr16SP", [frameindex]>; // // Address operand def mem16 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops CPU16Regs, simm16, CPU16RegsPlusSP); + let MIOperandInfo = (ops CPU16Regs, simm16); + let EncoderMethod = "getMemEncoding"; +} + +def mem16sp : Operand<i32> { + let PrintMethod = "printMemOperand"; + // This should be CPUSPReg but the MIPS16 subtarget isn't good enough at + // keeping the sp-relative load and the other varieties separate at the + // moment. This lie fixes the problem sufficiently well to fix the errors + // emitted by -verify-machineinstrs and the output ends up correct as long + // as we use an external assembler (which is already a requirement for MIPS16 + // for several other reasons). + let MIOperandInfo = (ops CPU16RegsPlusSP, simm16); let EncoderMethod = "getMemEncoding"; } @@ -215,19 +227,6 @@ class FEXT_2RI16_ins<bits<5> _op, string asmstr, let Constraints = "$rx_ = $rx"; } - -// this has an explicit sp argument that we ignore to work around a problem -// in the compiler -class FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>; - -class FEXT_RI16_SP_Store_explicit_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs), (ins CPU16Regs:$rx, CPUSPReg:$ry, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>; - // // EXT-RRI instruction format // @@ -851,9 +850,7 @@ def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, II_LW>, MayLoad{ // Purpose: Load Word (SP-Relative, Extended) // To load an SP-relative word from memory as a signed value. // -def LwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b10010, "lw", II_LW>, MayLoad{ - let Uses = [SP]; -} +def LwRxSpImmX16: FEXT_RRI16_mem_ins<0b10010, "lw", mem16sp, II_LW>, MayLoad; def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", II_LW>, MayLoad; @@ -1277,16 +1274,14 @@ def SubuRxRyRz16: FRRR16_ins<0b11, "subu", IIM16Alu>, ArithLogic16Defs<0>; // Purpose: Store Word (Extended) // To store a word to memory. // -def SwRxRyOffMemX16: - FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore; +def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore; // // Format: SW rx, offset(sp) MIPS16e // Purpose: Store Word rx (SP-Relative) // To store an SP-relative word to memory. // -def SwRxSpImmX16: FEXT_RI16_SP_Store_explicit_ins - <0b11010, "sw", II_SW>, MayStore; +def SwRxSpImmX16: FEXT_RRI16_mem2_ins<0b11010, "sw", mem16sp, II_SW>, MayStore; // // @@ -1340,22 +1335,21 @@ def: shift_rotate_reg16_pat<shl, SllvRxRy16>; def: shift_rotate_reg16_pat<sra, SravRxRy16>; def: shift_rotate_reg16_pat<srl, SrlvRxRy16>; -class LoadM16_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>; +class LoadM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> : + Mips16Pat<(OpNode Addr:$addr), (I Addr:$addr)>; -def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16>; -def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16>; -def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16>; -def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16>; -def: LoadM16_pat<load, LwRxRyOffMemX16>; +def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16, addr16>; +def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16, addr16>; +def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16, addr16>; +def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16, addr16>; +def: LoadM16_pat<load, LwRxSpImmX16, addr16sp>; -class StoreM16_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr), - (I CPU16Regs:$r, addr16:$addr)>; +class StoreM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> : + Mips16Pat<(OpNode CPU16Regs:$r, Addr:$addr), (I CPU16Regs:$r, Addr:$addr)>; -def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16>; -def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16>; -def: StoreM16_pat<store, SwRxRyOffMemX16>; +def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16, addr16>; +def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16, addr16>; +def: StoreM16_pat<store, SwRxSpImmX16, addr16sp>; // Unconditional branch class UncondBranch16_pat<SDNode OpNode, Instruction I>: @@ -1401,8 +1395,7 @@ class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>: (I CPU16Regs:$rx, imm_type:$imm16)>; -def: Mips16Pat<(i32 addr16:$addr), - (AddiuRxRyOffMemX16 addr16:$addr)>; +def: Mips16Pat<(i32 addr16sp:$addr), (AddiuRxRyOffMemX16 addr16sp:$addr)>; // Large (>16 bit) immediate loads diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp index 50dc0fb7738..9d8feaa5594 100644 --- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -102,8 +102,14 @@ bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, return false; } -bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Alias) { +bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, + SDValue &Offset) { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, + SDValue &Offset) { llvm_unreachable("Unimplemented function."); return false; } diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.h b/llvm/lib/Target/Mips/MipsISelDAGToDAG.h index c2ac61d774b..2cca7fe26fd 100644 --- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.h @@ -75,8 +75,8 @@ private: virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const; - virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Alias); + virtual bool selectAddr16(SDValue Addr, SDValue &Base, SDValue &Offset); + virtual bool selectAddr16SP(SDValue Addr, SDValue &Base, SDValue &Offset); /// \brief Select constant vector splats. virtual bool selectVSplat(SDNode *N, APInt &Imm, diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/llvm/lib/Target/Mips/MipsMachineFunction.cpp index 3c62d01f6c0..f81e64e06f4 100644 --- a/llvm/lib/Target/Mips/MipsMachineFunction.cpp +++ b/llvm/lib/Target/Mips/MipsMachineFunction.cpp @@ -53,18 +53,6 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); } -bool MipsFunctionInfo::mips16SPAliasRegSet() const { - return Mips16SPAliasReg; -} -unsigned MipsFunctionInfo::getMips16SPAliasReg() { - // Return if it has already been initialized. - if (Mips16SPAliasReg) - return Mips16SPAliasReg; - - const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; - return Mips16SPAliasReg = MF.getRegInfo().createVirtualRegister(RC); -} - void MipsFunctionInfo::createEhDataRegsFI() { for (int I = 0; I < 4; ++I) { const TargetRegisterClass *RC = diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.h b/llvm/lib/Target/Mips/MipsMachineFunction.h index 936e21438b0..c9e5fddc193 100644 --- a/llvm/lib/Target/Mips/MipsMachineFunction.h +++ b/llvm/lib/Target/Mips/MipsMachineFunction.h @@ -30,8 +30,8 @@ namespace llvm { class MipsFunctionInfo : public MachineFunctionInfo { public: MipsFunctionInfo(MachineFunction &MF) - : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), Mips16SPAliasReg(0), - VarArgsFrameIndex(0), CallsEhReturn(false), IsISR(false), SaveS2(false), + : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0), + CallsEhReturn(false), IsISR(false), SaveS2(false), MoveF64ViaSpillFI(-1) {} ~MipsFunctionInfo(); @@ -42,9 +42,6 @@ public: bool globalBaseRegSet() const; unsigned getGlobalBaseReg(); - bool mips16SPAliasRegSet() const; - unsigned getMips16SPAliasReg(); - int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } @@ -101,11 +98,6 @@ private: /// relocation models. unsigned GlobalBaseReg; - /// Mips16SPAliasReg - keeps track of the virtual register initialized for - /// use as an alias for SP for use in load/store of halfword/byte from/to - /// the stack - unsigned Mips16SPAliasReg; - /// VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; |

