Index: lib/Target/Mips/Mips16ISelDAGToDAG.h =================================================================== --- lib/Target/Mips/Mips16ISelDAGToDAG.h +++ lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -26,14 +26,14 @@ std::pair selectMULT(SDNode *N, unsigned Opc, 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; Index: lib/Target/Mips/Mips16ISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -90,89 +90,22 @@ .addReg(V1).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(); - - 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()->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(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(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(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(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); + Offset = CurDAG->getTargetConstant(0, DL, ValTy); + return true; + } } // on PIC code Load GA @@ -192,15 +125,17 @@ if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { - // If the first operand is a FI, get the TargetFI Node - if (FrameIndexSDNode *FIN = - dyn_cast(Addr.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - getMips16SPRefReg(Parent, Alias); - } else - Base = Addr.getOperand(0); + if (SPAllowed) { + if (FrameIndexSDNode *FIN = + dyn_cast(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; } @@ -226,16 +161,6 @@ return true; } } - - // If an indexed floating point load/store can be emitted, return false. - const LSBaseSDNode *LS = dyn_cast(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; @@ -243,6 +168,16 @@ 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) { Index: lib/Target/Mips/Mips16InstrInfo.td =================================================================== --- lib/Target/Mips/Mips16InstrInfo.td +++ lib/Target/Mips/Mips16InstrInfo.td @@ -14,14 +14,26 @@ // // Mips Address // -def addr16 : - ComplexPattern; +def addr16 : ComplexPattern; +def addr16sp : ComplexPattern; // // Address operand def mem16 : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops CPU16Regs, simm16, CPU16RegsPlusSP); + let MIOperandInfo = (ops CPU16Regs, simm16); + let EncoderMethod = "getMemEncoding"; +} + +def mem16sp : Operand { + 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 @@ 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 _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 _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 @@ // 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 @@ // 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; def: shift_rotate_reg16_pat; -class LoadM16_pat : - Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>; +class LoadM16_pat : + Mips16Pat<(OpNode Addr:$addr), (I Addr:$addr)>; -def: LoadM16_pat; -def: LoadM16_pat; -def: LoadM16_pat; -def: LoadM16_pat; -def: LoadM16_pat; +def: LoadM16_pat; +def: LoadM16_pat; +def: LoadM16_pat; +def: LoadM16_pat; +def: LoadM16_pat; -class StoreM16_pat : - Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr), - (I CPU16Regs:$r, addr16:$addr)>; +class StoreM16_pat : + Mips16Pat<(OpNode CPU16Regs:$r, Addr:$addr), (I CPU16Regs:$r, Addr:$addr)>; -def: StoreM16_pat; -def: StoreM16_pat; -def: StoreM16_pat; +def: StoreM16_pat; +def: StoreM16_pat; +def: StoreM16_pat; // Unconditional branch class UncondBranch16_pat: @@ -1401,8 +1395,7 @@ (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 Index: lib/Target/Mips/MipsISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.h +++ lib/Target/Mips/MipsISelDAGToDAG.h @@ -80,8 +80,8 @@ 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, Index: lib/Target/Mips/MipsISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.cpp +++ lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -108,8 +108,14 @@ 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; } Index: lib/Target/Mips/MipsMachineFunction.h =================================================================== --- lib/Target/Mips/MipsMachineFunction.h +++ lib/Target/Mips/MipsMachineFunction.h @@ -30,8 +30,8 @@ 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 @@ 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 @@ /// 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; Index: lib/Target/Mips/MipsMachineFunction.cpp =================================================================== --- lib/Target/Mips/MipsMachineFunction.cpp +++ lib/Target/Mips/MipsMachineFunction.cpp @@ -53,18 +53,6 @@ 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 = Index: test/CodeGen/Mips/stchar.ll =================================================================== --- test/CodeGen/Mips/stchar.ll +++ test/CodeGen/Mips/stchar.ll @@ -5,32 +5,8 @@ @sp = common global i16* null, align 4 @cp = common global i8* null, align 4 -define void @p1(i16 signext %s, i8 signext %c) nounwind { -entry: - %conv = sext i16 %s to i32 - %conv1 = sext i8 %c to i32 - %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i32 %conv, i32 %conv1) nounwind - ret void -} - declare i32 @printf(i8* nocapture, ...) nounwind -define void @p2() nounwind { -entry: - %0 = load i16*, i16** @sp, align 4 - %1 = load i16, i16* %0, align 2 - %2 = load i8*, i8** @cp, align 4 - %3 = load i8, i8* %2, align 1 - %conv.i = sext i16 %1 to i32 - %conv1.i = sext i8 %3 to i32 - %call.i = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i32 %conv.i, i32 %conv1.i) nounwind - %4 = load i16*, i16** @sp, align 4 - store i16 32, i16* %4, align 2 - %5 = load i8*, i8** @cp, align 4 - store i8 97, i8* %5, align 1 - ret void -} - define void @test() nounwind { entry: %s = alloca i16, align 4 @@ -58,32 +34,6 @@ ; 16_h: lh ${{[0-9]+}}, [[offset2]](${{[0-9]+}}) } -define i32 @main() nounwind { -entry: - %s.i = alloca i16, align 4 - %c.i = alloca i8, align 4 - %0 = bitcast i16* %s.i to i8* - call void @llvm.lifetime.start(i64 -1, i8* %0) nounwind - call void @llvm.lifetime.start(i64 -1, i8* %c.i) nounwind - store i16 16, i16* %s.i, align 4 - store i8 99, i8* %c.i, align 4 - store i16* %s.i, i16** @sp, align 4 - store i8* %c.i, i8** @cp, align 4 - %call.i.i.i = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i32 16, i32 99) nounwind - %1 = load i16*, i16** @sp, align 4 - store i16 32, i16* %1, align 2 - %2 = load i8*, i8** @cp, align 4 - store i8 97, i8* %2, align 1 - %3 = load i16, i16* %s.i, align 4 - %4 = load i8, i8* %c.i, align 4 - %conv.i.i = sext i16 %3 to i32 - %conv1.i.i = sext i8 %4 to i32 - %call.i.i = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i32 %conv.i.i, i32 %conv1.i.i) nounwind - call void @llvm.lifetime.end(i64 -1, i8* %0) nounwind - call void @llvm.lifetime.end(i64 -1, i8* %c.i) nounwind - ret i32 0 -} - declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind Index: test/CodeGen/Mips/stldst.ll =================================================================== --- test/CodeGen/Mips/stldst.ll +++ test/CodeGen/Mips/stldst.ll @@ -33,9 +33,9 @@ %call7 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str, i32 0, i32 0), i32 %0, i32 %1, i32 %add, i32 %add1, i32 %sub, i32 %add2, i32 %add3, i32 %sub4, i32 %sub5, i32 %add6) nounwind ret i32 0 } -; 16: sw ${{[0-9]+}}, {{[0-9]+}} ( $sp ); # 4-byte Folded Spill -; 16: lw ${{[0-9]+}}, {{[0-9]+}} ( $sp ); # 4-byte Folded Reload -; 16: sw ${{[0-9]+}}, {{[0-9]+}} ( $sp ); # 4-byte Folded Spill -; 16: lw ${{[0-9]+}}, {{[0-9]+}} ( $sp ); # 4-byte Folded Reload +; 16: sw ${{[0-9]+}}, {{[0-9]+}}($sp) # 4-byte Folded Spill +; 16: lw ${{[0-9]+}}, {{[0-9]+}}($sp) # 4-byte Folded Reload +; 16: sw ${{[0-9]+}}, {{[0-9]+}}($sp) # 4-byte Folded Spill +; 16: lw ${{[0-9]+}}, {{[0-9]+}}($sp) # 4-byte Folded Reload declare i32 @printf(i8* nocapture, ...) nounwind Index: test/CodeGen/Mips/tailcall.ll =================================================================== --- test/CodeGen/Mips/tailcall.ll +++ test/CodeGen/Mips/tailcall.ll @@ -1,11 +1,12 @@ -; RUN: llc -march=mipsel -relocation-model=pic -enable-mips-tail-calls < %s | \ -; RUN: FileCheck %s -check-prefix=PIC32 -; RUN: llc -march=mipsel -relocation-model=static \ -; RUN: -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=STATIC32 +; RUN: llc -march=mipsel -relocation-model=pic -enable-mips-tail-calls \ +; RUN: -verify-machineinstrs < %s | FileCheck %s -check-prefix=PIC32 +; RUN: llc -march=mipsel -relocation-model=static -enable-mips-tail-calls \ +; RUN: -verify-machineinstrs < %s | FileCheck %s -check-prefix=STATIC32 ; RUN: llc -march=mips64el -mcpu=mips64r2 -enable-mips-tail-calls \ -; RUN: < %s | FileCheck %s -check-prefix=N64 +; RUN: -verify-machineinstrs < %s | FileCheck %s -check-prefix=N64 ; RUN: llc -march=mipsel -mattr=mips16 -relocation-model=pic \ -; RUN: -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=PIC16 +; RUN: -enable-mips-tail-calls -verify-machineinstrs < %s | \ +; RUN: FileCheck %s -check-prefix=PIC16 @g0 = common global i32 0, align 4 @g1 = common global i32 0, align 4