diff options
-rw-r--r-- | lib/Target/Mips/Mips16FrameLowering.cpp | 9 | ||||
-rw-r--r-- | lib/Target/Mips/Mips16InstrInfo.td | 44 | ||||
-rw-r--r-- | lib/Target/Mips/Mips16RegisterInfo.cpp | 83 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelDAGToDAG.cpp | 146 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMachineFunction.cpp | 13 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMachineFunction.h | 12 | ||||
-rw-r--r-- | lib/Target/Mips/MipsRegisterInfo.cpp | 17 | ||||
-rw-r--r-- | test/CodeGen/Mips/alloca16.ll | 43 | ||||
-rw-r--r-- | test/CodeGen/Mips/stchar.ll | 90 |
9 files changed, 409 insertions, 48 deletions
diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp index 056a74e..74cffd2 100644 --- a/lib/Target/Mips/Mips16FrameLowering.cpp +++ b/lib/Target/Mips/Mips16FrameLowering.cpp @@ -41,6 +41,11 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const { // Adjust stack. if (isInt<16>(-StackSize)) BuildMI(MBB, MBBI, dl, TII.get(Mips::SaveRaF16)).addImm(StackSize); + + if (hasFP(MF)) + BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) + .addReg(Mips::SP); + } void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, @@ -55,6 +60,10 @@ void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, if (!StackSize) return; + if (hasFP(MF)) + BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) + .addReg(Mips::S0); + // Adjust stack. if (isInt<16>(StackSize)) // assumes stacksize multiple of 8 diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index c7d6feb..79b4757 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -11,11 +11,22 @@ // //===----------------------------------------------------------------------===// // +// +// Mips Address +// +def addr16 : + ComplexPattern<iPTR, 3, "SelectAddr16", [frameindex], [SDNPWantParent]>; // // Address operand def mem16 : Operand<i32> { let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops CPU16Regs, simm16, CPU16Regs); + let EncoderMethod = "getMemEncoding"; +} + +def mem16_ea : Operand<i32> { + let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops CPU16Regs, simm16); let EncoderMethod = "getMemEncoding"; } @@ -119,6 +130,16 @@ class FEXT_RRI16_mem2_ins<bits<5> op, string asmstr, Operand MemOpnd, !strconcat(asmstr, "\t$ry, $addr"), [], itin>; // +// +// EXT-RRI-A instruction format +// + +class FEXT_RRI_A16_mem_ins<bits<1> op, string asmstr, Operand MemOpnd, + InstrItinClass itin>: + FEXT_RRI_A16<op, (outs CPU16Regs:$ry), (ins MemOpnd:$addr), + !strconcat(asmstr, "\t$ry, $addr"), [], itin>; + +// // EXT-SHIFT instruction format // class FEXT_SHIFT16_ins<bits<2> _f, string asmstr, InstrItinClass itin>: @@ -367,6 +388,9 @@ def AddiuRxImmX16: FEXT_RI16_ins<0b01001, "addiu", IIAlu>; def AddiuRxRxImmX16: FEXT_2RI16_ins<0b01001, "addiu", IIAlu>, ArithLogic16Defs<0>; +def AddiuRxRyOffMemX16: + FEXT_RRI_A16_mem_ins<0, "addiu", mem16_ea, IIAlu>; + // // Format: ADDIU rx, pc, immediate MIPS16e @@ -477,8 +501,13 @@ def DivuRxRy16: FRR16_div_ins<0b11011, "divu", IIAlu> { // address register. // -def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIAlu>; - +def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIAlu> { + let isBranch = 1; + let isIndirectBranch = 1; + let hasDelaySlot = 1; + let isTerminator=1; + let isBarrier=1; +} // // Format: LB ry, offset(rx) MIPS16e // Purpose: Load Byte (Extended) @@ -940,7 +969,7 @@ def: shift_rotate_reg16_pat<sra, SravRxRy16>; def: shift_rotate_reg16_pat<srl, SrlvRxRy16>; class LoadM16_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode addr:$addr), (I addr:$addr)>; + Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>; def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16>; def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16>; @@ -949,7 +978,8 @@ def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16>; def: LoadM16_pat<load, LwRxRyOffMemX16>; class StoreM16_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$r, addr:$addr), (I CPU16Regs:$r, addr:$addr)>; + Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr), + (I CPU16Regs:$r, addr16:$addr)>; def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16>; def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16>; @@ -983,6 +1013,11 @@ class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>: Mips16Pat<(cond_op CPU16Regs:$rx, imm_type:$imm16), (I CPU16Regs:$rx, imm_type:$imm16)>; + +def: Mips16Pat<(i32 addr16:$addr), + (AddiuRxRyOffMemX16 addr16:$addr)>; + + // Large (>16 bit) immediate loads def : Mips16Pat<(i32 imm:$imm), (OrRxRxRy16 (SllX16 (LiRxImmX16 (HI16 imm:$imm)), 16), @@ -1451,5 +1486,6 @@ class Wrapper16Pat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: (ADDiuOp RC:$gp, node:$in)>; +def : Wrapper16Pat<tglobaladdr, AddiuRxRxImmX16, CPU16Regs>; def : Wrapper16Pat<tglobaltlsaddr, AddiuRxRxImmX16, CPU16Regs>; diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp index bfc6b6c..47a41d6 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -54,51 +54,60 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, int FrameIndex, uint64_t StackSize, int64_t SPOffset) const { - MachineInstr &MI = *II; - MachineFunction &MF = *MI.getParent()->getParent(); - MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + MachineFrameInfo *MFI = MF.getFrameInfo(); - const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); - int MinCSFI = 0; - int MaxCSFI = -1; + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); + int MinCSFI = 0; + int MaxCSFI = -1; - if (CSI.size()) { - MinCSFI = CSI[0].getFrameIdx(); - MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); - } + if (CSI.size()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); + } - // The following stack frame objects are always - // referenced relative to $sp: - // 1. Outgoing arguments. - // 2. Pointer to dynamically allocated stack space. - // 3. Locations for callee-saved registers. - // Everything else is referenced relative to whatever register - // getFrameRegister() returns. - unsigned FrameReg; + // The following stack frame objects are always + // referenced relative to $sp: + // 1. Outgoing arguments. + // 2. Pointer to dynamically allocated stack space. + // 3. Locations for callee-saved registers. + // Everything else is referenced relative to whatever register + // getFrameRegister() returns. + unsigned FrameReg; - if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) - FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; + if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) + FrameReg = Mips::SP; + else { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + if (TFI->hasFP(MF)) { + FrameReg = Mips::S0; + } + else { + if ((MI.getNumOperands()> OpNo+2) && MI.getOperand(OpNo+2).isReg()) + FrameReg = MI.getOperand(OpNo+2).getReg(); else - FrameReg = getFrameRegister(MF); + FrameReg = Mips::SP; + } + } + // Calculate final offset. + // - There is no need to change the offset if the frame object + // is one of the + // following: an outgoing argument, pointer to a dynamically allocated + // stack space or a $gp restore location, + // - If the frame object is any of the following, + // its offset must be adjusted + // by adding the size of the stack: + // incoming argument, callee-saved register location or local variable. + int64_t Offset; + Offset = SPOffset + (int64_t)StackSize; + Offset += MI.getOperand(OpNo + 1).getImm(); - // Calculate final offset. - // - There is no need to change the offset if the frame object - // is one of the - // following: an outgoing argument, pointer to a dynamically allocated - // stack space or a $gp restore location, - // - If the frame object is any of the following, - // its offset must be adjusted - // by adding the size of the stack: - // incoming argument, callee-saved register location or local variable. - int64_t Offset; - Offset = SPOffset + (int64_t)StackSize; - Offset += MI.getOperand(OpNo + 1).getImm(); + DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); - - MI.getOperand(OpNo).ChangeToRegister(FrameReg, false); - MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); + MI.getOperand(OpNo).ChangeToRegister(FrameReg, false); + MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); } diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 9a5a712..c5fca7f 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -86,6 +86,10 @@ private: SDNode *getGlobalBaseReg(); + SDValue getMips16SPAliasReg(); + + void getMips16SPRefReg(SDNode *parent, SDValue &AliasReg); + std::pair<SDNode*, SDNode*> SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, EVT Ty, bool HasLo, bool HasHi); @@ -94,6 +98,9 @@ private: // Complex Pattern. bool SelectAddr(SDNode *Parent, SDValue N, SDValue &Base, SDValue &Offset); + bool SelectAddr16(SDNode *Parent, SDValue N, SDValue &Base, SDValue &Offset, + SDValue &Alias); + // getImm - Return a target constant with the specified value. inline SDValue getImm(const SDNode *Node, unsigned Imm) { return CurDAG->getTargetConstant(Imm, Node->getValueType(0)); @@ -102,6 +109,7 @@ private: void ProcessFunctionAfterISel(MachineFunction &MF); bool ReplaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&); void InitGlobalBaseReg(MachineFunction &MF); + void InitMips16SPAliasReg(MachineFunction &MF); virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, @@ -220,6 +228,26 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { .addReg(Mips::V0).addReg(Mips::T9); } +// Insert instructions to initialize the Mips16 SP Alias register in the +// first MBB of the function. +// +void MipsDAGToDAGISel::InitMips16SPAliasReg(MachineFunction &MF) { + MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + + if (!MipsFI->mips16SPAliasRegSet()) + return; + + MachineBasicBlock &MBB = MF.front(); + MachineBasicBlock::iterator I = MBB.begin(); + const TargetInstrInfo &TII = *MF.getTarget().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); +} + + bool MipsDAGToDAGISel::ReplaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr& MI) { unsigned DstReg = 0, ZeroReg = 0; @@ -260,6 +288,7 @@ bool MipsDAGToDAGISel::ReplaceUsesWithZeroReg(MachineRegisterInfo *MRI, void MipsDAGToDAGISel::ProcessFunctionAfterISel(MachineFunction &MF) { InitGlobalBaseReg(MF); + InitMips16SPAliasReg(MF); MachineRegisterInfo *MRI = &MF.getRegInfo(); @@ -284,6 +313,14 @@ SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } +/// getMips16SPAliasReg - Output the instructions required to put the +/// SP into a Mips16 accessible aliased register. +SDValue MipsDAGToDAGISel::getMips16SPAliasReg() { + unsigned Mips16SPAliasReg = + MF->getInfo<MipsFunctionInfo>()->getMips16SPAliasReg(); + return CurDAG->getRegister(Mips16SPAliasReg, TLI.getPointerTy()); +} + /// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: @@ -362,6 +399,115 @@ SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { return true; } +void MipsDAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { + SDValue AliasFPReg = CurDAG->getRegister(Mips::S0, TLI.getPointerTy()); + if (Parent) { + switch (Parent->getOpcode()) { + case ISD::LOAD: { + LoadSDNode *SD = dyn_cast<LoadSDNode>(Parent); + switch (SD->getMemoryVT().getSizeInBits()) { + case 8: + case 16: + AliasReg = TM.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 = TM.getFrameLowering()->hasFP(*MF)? + AliasFPReg: getMips16SPAliasReg(); + return; + } + break; + } + } + } + AliasReg = CurDAG->getRegister(Mips::SP, TLI.getPointerTy()); + return; + +} +bool MipsDAGToDAGISel::SelectAddr16( + SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset, + SDValue &Alias) { + EVT ValTy = Addr.getValueType(); + + Alias = CurDAG->getTargetConstant(0, 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, ValTy); + getMips16SPRefReg(Parent, Alias); + return true; + } + // on PIC code Load GA + if (Addr.getOpcode() == MipsISD::Wrapper) { + Base = Addr.getOperand(0); + Offset = Addr.getOperand(1); + return true; + } + if (TM.getRelocationModel() != Reloc::PIC_) { + if ((Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress)) + return false; + } + // Addresses of the form FI+const or FI|const + 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); + + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); + return true; + } + } + // Operand is a result from an ADD. + if (Addr.getOpcode() == ISD::ADD) { + // When loading from constant pools, load the lower address part in + // the instruction itself. Example, instead of: + // lui $2, %hi($CPI1_0) + // addiu $2, $2, %lo($CPI1_0) + // lwc1 $f0, 0($2) + // Generate: + // lui $2, %hi($CPI1_0) + // lwc1 $f0, %lo($CPI1_0)($2) + if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || + Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { + SDValue Opnd0 = Addr.getOperand(1).getOperand(0); + if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || + isa<JumpTableSDNode>(Opnd0)) { + Base = Addr.getOperand(0); + Offset = Opnd0; + return true; + } + } + + // If an indexed floating point load/store can be emitted, return false. + const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent); + + if (LS && + (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && + Subtarget.hasMips32r2Or64()) + return false; + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, ValTy); + return true; +} + /// Select multiply instructions. std::pair<SDNode*, SDNode*> MipsDAGToDAGISel::SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, EVT Ty, diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index 362173e..5ff19ab 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -43,4 +43,17 @@ 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; + RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass; + return Mips16SPAliasReg = MF.getRegInfo().createVirtualRegister(RC); +} + void MipsFunctionInfo::anchor() { } diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index b05f618..f9efe07 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -39,6 +39,11 @@ class MipsFunctionInfo : public MachineFunctionInfo { /// 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; @@ -46,8 +51,8 @@ class MipsFunctionInfo : public MachineFunctionInfo { public: MipsFunctionInfo(MachineFunction& MF) - : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), - VarArgsFrameIndex(0), EmitNOAT(false) + : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), Mips16SPAliasReg(0), + VarArgsFrameIndex(0), EmitNOAT(false) {} unsigned getSRetReturnReg() const { return SRetReturnReg; } @@ -56,6 +61,9 @@ public: bool globalBaseRegSet() const; unsigned getGlobalBaseReg(); + bool mips16SPAliasRegSet() const; + unsigned getMips16SPAliasReg(); + int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 4614dcb..dd1a42b 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -112,11 +112,14 @@ getReservedRegs(const MachineFunction &MF) const { EReg = Mips::FGR64RegClass.end(); Reg != EReg; ++Reg) Reserved.set(*Reg); } - // Reserve FP if this function should have a dedicated frame pointer register. if (MF.getTarget().getFrameLowering()->hasFP(MF)) { - Reserved.set(Mips::FP); - Reserved.set(Mips::FP_64); + if (Subtarget.inMips16Mode()) + Reserved.set(Mips::S0); + else { + Reserved.set(Mips::FP); + Reserved.set(Mips::FP_64); + } } // Reserve hardware registers. @@ -186,8 +189,12 @@ getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); bool IsN64 = Subtarget.isABI_N64(); - return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) : - (IsN64 ? Mips::SP_64 : Mips::SP); + if (Subtarget.inMips16Mode()) + return TFI->hasFP(MF) ? Mips::S0 : Mips::SP; + else + return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) : + (IsN64 ? Mips::SP_64 : Mips::SP); + } unsigned MipsRegisterInfo:: diff --git a/test/CodeGen/Mips/alloca16.ll b/test/CodeGen/Mips/alloca16.ll new file mode 100644 index 0000000..ce2e634 --- /dev/null +++ b/test/CodeGen/Mips/alloca16.ll @@ -0,0 +1,43 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16 + +@iiii = global i32 25, align 4 +@jjjj = global i32 35, align 4 +@kkkk = global i32 100, align 4 +@riii = common global i32 0, align 4 +@rjjj = common global i32 0, align 4 +@rkkk = common global i32 0, align 4 + +define void @test() nounwind { +entry: +; 16: .frame $16,16,$ra +; 16: save $ra, $s0, $s1, 16 +; 16: move $16, $sp +; 16: move ${{[0-9]+}}, $sp +; 16: subu $[[REGISTER:[0-9]+]], ${{[0-9]+}}, ${{[0-9]+}} +; 16: move $sp, $[[REGISTER]] + %0 = load i32* @kkkk, align 4 + %1 = mul i32 %0, 25 + %2 = alloca i32, i32 %1, align 4 + %3 = load i32* @jjjj, align 4 + %4 = load i32* @iiii, align 4 + %arrayidx = getelementptr inbounds i32* %2, i32 %4 + store i32 %3, i32* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds i32* %2, i32 %3 + store i32 %0, i32* %arrayidx1, align 4 + %arrayidx2 = getelementptr inbounds i32* %2, i32 %0 + store i32 %4, i32* %arrayidx2, align 4 + %arrayidx3 = getelementptr inbounds i32* %2, i32 25 + %5 = load i32* %arrayidx3, align 4 + store i32 %5, i32* @riii, align 4 + %arrayidx4 = getelementptr inbounds i32* %2, i32 35 + %6 = load i32* %arrayidx4, align 4 + store i32 %6, i32* @rjjj, align 4 + %arrayidx5 = getelementptr inbounds i32* %2, i32 100 + %7 = load i32* %arrayidx5, align 4 + store i32 %7, i32* @rkkk, align 4 +; 16: move $sp, $16 +; 16: restore $ra, $s0, $s1, 16 + ret void +} + + diff --git a/test/CodeGen/Mips/stchar.ll b/test/CodeGen/Mips/stchar.ll new file mode 100644 index 0000000..c00c9fd --- /dev/null +++ b/test/CodeGen/Mips/stchar.ll @@ -0,0 +1,90 @@ +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16_h +; RUN: llc -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s | FileCheck %s -check-prefix=16_b + +@.str = private unnamed_addr constant [9 x i8] c"%hd %c \0A\00", align 1 +@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]* @.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** @sp, align 4 + %1 = load i16* %0, align 2 + %2 = load i8** @cp, align 4 + %3 = load 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]* @.str, i32 0, i32 0), i32 %conv.i, i32 %conv1.i) nounwind + %4 = load i16** @sp, align 4 + store i16 32, i16* %4, align 2 + %5 = load i8** @cp, align 4 + store i8 97, i8* %5, align 1 + ret void +} + +define void @test() nounwind { +entry: + %s = alloca i16, align 4 + %c = alloca i8, align 4 + store i16 16, i16* %s, align 4 + store i8 99, i8* %c, align 4 + store i16* %s, i16** @sp, align 4 + store i8* %c, i8** @cp, align 4 + %call.i.i = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i32 16, i32 99) nounwind + %0 = load i16** @sp, align 4 + store i16 32, i16* %0, align 2 + %1 = load i8** @cp, align 4 + store i8 97, i8* %1, align 1 + %2 = load i16* %s, align 4 + %3 = load i8* %c, align 4 + %conv.i = sext i16 %2 to i32 + %conv1.i = sext i8 %3 to i32 + %call.i = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i32 %conv.i, i32 %conv1.i) nounwind + ret void +; 16_b: test: +; 16_h: test: +; 16_b: sb ${{[0-9]+}}, [[offset1:[0-9]+]](${{[0-9]+}}) +; 16_b: lb ${{[0-9]+}}, [[offset1]](${{[0-9]+}}) +; 16_h: sh ${{[0-9]+}}, [[offset2:[0-9]+]](${{[0-9]+}}) +; 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]* @.str, i32 0, i32 0), i32 16, i32 99) nounwind + %1 = load i16** @sp, align 4 + store i16 32, i16* %1, align 2 + %2 = load i8** @cp, align 4 + store i8 97, i8* %2, align 1 + %3 = load i16* %s.i, align 4 + %4 = load 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]* @.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 + |