X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsInstrInfo.td;h=06513220b6f474c1bca7b4b3d5d508e8c02e4e8f;hb=0ddff1b5359433faf2eb1c4ff5320ddcbd42f52f;hp=f16a8053358dea5ab09981cff419b79f85cfba75;hpb=eb079a34910fd09947972cedfad18d9cff76a579;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index f16a8053358..06513220b6f 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -1,4 +1,4 @@ -//===- MipsInstrInfo.td - Mips Register defs --------------------*- C++ -*-===// +//===- MipsInstrInfo.td - Target Description for Mips Target -*- tablegen -*-=// // // The LLVM Compiler Infrastructure // @@ -6,6 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// This file contains the Mips implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Instruction format superclass @@ -19,40 +23,88 @@ include "MipsInstrFormats.td" def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; -def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>, - SDTCisSameAs<2, 3>, SDTCisInt<1>]>; -def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, - SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, - SDTCisInt<4>]>; +def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>, + SDTCisSameAs<3, 4>, + SDTCisInt<4>]>; def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def SDT_MipsMAddMSub : SDTypeProfile<0, 4, + [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, + SDTCisSameAs<1, 2>, + SDTCisSameAs<2, 3>]>; +def SDT_MipsDivRem : SDTypeProfile<0, 2, + [SDTCisVT<0, i32>, + SDTCisSameAs<0, 1>]>; + +def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; + +def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, + SDTCisVT<1, iPTR>]>; // Call -def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, - [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>; +def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, + SDNPVariadic]>; -// Hi and Lo nodes are used to handle global addresses. Used on -// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol +// Hi and Lo nodes are used to handle global addresses. Used on +// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol // static model. (nothing to do with Mips Registers Hi and Lo) def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>; +// TlsGd node is used to handle General Dynamic TLS +def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>; + +// TprelHi and TprelLo nodes are used to handle Local Exec TLS +def MipsTprelHi : SDNode<"MipsISD::TprelHi", SDTIntUnaryOp>; +def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>; + +// Thread pointer +def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; + // Return -def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, - SDNPOptInFlag]>; +def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, + SDNPOptInGlue]>; // These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, - [SDNPHasChain, SDNPOutFlag]>; + [SDNPHasChain, SDNPOutGlue]>; def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, - [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; - -// Select Condition Code -def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>; - -// Conditional Move -def MipsCMov : SDNode<"MipsISD::CMov", SDT_MipsCMov>; + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +// MAdd*/MSub* nodes +def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; +def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub, + [SDNPOptInGlue, SDNPOutGlue]>; + +// DivRem(u) nodes +def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem, + [SDNPOutGlue]>; +def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, + [SDNPOutGlue]>; + +// Target constant nodes that are not part of any isel patterns and remain +// unchanged can cause instructions with illegal operands to be emitted. +// Wrapper node patterns give the instruction selector a chance to replace +// target constant nodes that would otherwise remain unchanged with ADDiu +// nodes. Without these wrapper node patterns, the following conditional move +// instrucion is emitted when function cmov2 in test/CodeGen/Mips/cmov.ll is +// compiled: +// movn %got(d)($gp), %got(c)($gp), $4 +// This instruction is illegal since movn can take only register operands. + +def MipsWrapperPIC : SDNode<"MipsISD::WrapperPIC", SDTIntUnaryOp>; + +// Pointer to dynamically allocated stack area. +def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc, + [SDNPHasChain, SDNPInGlue]>; //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. @@ -61,6 +113,8 @@ def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">; def HasBitCount : Predicate<"Subtarget.hasBitCount()">; def HasSwap : Predicate<"Subtarget.hasSwap()">; def HasCondMov : Predicate<"Subtarget.hasCondMov()">; +def IsMips32 : Predicate<"Subtarget.isMips32()">; +def IsMips32r2 : Predicate<"Subtarget.isMips32r2()">; //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. @@ -95,12 +149,7 @@ def HI16 : SDNodeXFormgetValueType(0) == MVT::i32) - return (int32_t)N->getZExtValue() == (short)N->getZExtValue(); - else - return (int64_t)N->getZExtValue() == (short)N->getZExtValue(); -}]>; +def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; // Node immediate fits as 16-bit zero extended on target immediate. // The LO16 param means that only the lower 16 bits of the node @@ -127,93 +176,76 @@ def addr : ComplexPattern; //===----------------------------------------------------------------------===// // Arithmetic 3 register operands -let isCommutable = 1 in class ArithR op, bits<6> func, string instr_asm, SDNode OpNode, - InstrItinClass itin>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; + InstrItinClass itin, bit isComm = 0>: + FR { + let isCommutable = isComm; +} -let isCommutable = 1 in -class ArithOverflowR op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [], IIAlu>; +class ArithOverflowR op, bits<6> func, string instr_asm, + bit isComm = 0>: + FR { + let isCommutable = isComm; +} // Arithmetic 2 register operands class ArithI op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; + FI; class ArithOverflowI op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [], IIAlu>; + FI; // Arithmetic Multiply ADD/SUB -let rd=0 in -class MArithR func, string instr_asm> : - FR< 0x1c, - func, - (outs CPURegs:$rs), - (ins CPURegs:$rt), - !strconcat(instr_asm, "\t$rs, $rt"), - [], IIImul>; +let rd = 0, shamt = 0, Defs = [HI, LO], Uses = [HI, LO] in +class MArithR func, string instr_asm, SDNode op, bit isComm = 0> : + FR<0x1c, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, "\t$rs, $rt"), + [(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul> { + let isCommutable = isComm; +} // Logical +let isCommutable = 1 in class LogicR func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; class LogicI op, string instr_asm, SDNode OpNode>: - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, uimm16:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>; + FI; +let isCommutable = 1 in class LogicNOR op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>; + FR; // Shifts -let rt = 0 in -class LogicR_shift_imm func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, shamt:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu>; +class LogicR_shift_rotate_imm func, bits<5> _rs, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, shamt:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu> { + let rs = _rs; +} -class LogicR_shift_reg func, string instr_asm, SDNode OpNode>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; +class LogicR_shift_rotate_reg func, bits<5> _shamt, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu> { + let shamt = _shamt; +} // Load Upper Imediate class LoadUpper op, string instr_asm>: @@ -226,164 +258,135 @@ class LoadUpper op, string instr_asm>: // Memory Load/Store let canFoldAsLoad = 1, hasDelaySlot = 1 in class LoadM op, string instr_asm, PatFrag OpNode>: - FI< op, - (outs CPURegs:$dst), - (ins mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>; + FI; class StoreM op, string instr_asm, PatFrag OpNode>: - FI< op, - (outs), - (ins CPURegs:$dst, mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(OpNode CPURegs:$dst, addr:$addr)], IIStore>; + FI; // Conditional Branch let isBranch = 1, isTerminator=1, hasDelaySlot = 1 in { class CBranch op, string instr_asm, PatFrag cond_op>: - FI< op, - (outs), - (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), - !strconcat(instr_asm, "\t$a, $b, $offset"), - [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], - IIBranch>; - + FI; class CBranchZero op, string instr_asm, PatFrag cond_op>: - FI< op, - (outs), - (ins CPURegs:$src, brtarget:$offset), - !strconcat(instr_asm, "\t$src, $offset"), - [(brcond (cond_op CPURegs:$src, 0), bb:$offset)], - IIBranch>; + FI; } // SetCC class SetCC_R op, bits<6> func, string instr_asm, PatFrag cond_op>: - FR< op, - func, - (outs CPURegs:$dst), - (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))], - IIAlu>; + FR; class SetCC_I op, string instr_asm, PatFrag cond_op, Operand Od, PatLeaf imm_type>: - FI< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))], - IIAlu>; + FI; // Unconditional branch let isBranch=1, isTerminator=1, isBarrier=1, hasDelaySlot = 1 in class JumpFJ op, string instr_asm>: - FJ< op, - (outs), - (ins brtarget:$target), - !strconcat(instr_asm, "\t$target"), - [(br bb:$target)], IIBranch>; + FJ; let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in class JumpFR op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs), - (ins CPURegs:$target), - !strconcat(instr_asm, "\t$target"), - [(brind CPURegs:$target)], IIBranch>; + FR; // Jump and Link (Call) let isCall=1, hasDelaySlot=1, // All calls clobber the non-callee saved registers... - Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, - K0, K1, F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, - F14, F15, F16, F17, F18, F19], Uses = [GP] in { + Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { class JumpLink op, string instr_asm>: - FJ< op, - (outs), - (ins calltarget:$target, variable_ops), - !strconcat(instr_asm, "\t$target"), - [(MipsJmpLink imm:$target)], IIBranch>; + FJ; let rd=31 in class JumpLinkReg op, bits<6> func, string instr_asm>: - FR< op, - func, - (outs), - (ins CPURegs:$rs, variable_ops), - !strconcat(instr_asm, "\t$rs"), - [(MipsJmpLink CPURegs:$rs)], IIBranch>; + FR; class BranchLink: - FI< 0x1, - (outs), - (ins CPURegs:$rs, brtarget:$target, variable_ops), - !strconcat(instr_asm, "\t$rs, $target"), - [], IIBranch>; + FI<0x1, (outs), (ins CPURegs:$rs, brtarget:$target, variable_ops), + !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch>; } // Mul, Div -class MulDiv func, string instr_asm, InstrItinClass itin>: - FR< 0x00, - func, - (outs), - (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$a, $b"), - [], itin>; +let Defs = [HI, LO] in { + let isCommutable = 1 in + class Mul func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$a, $b"), [], itin>; + + class Div func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, "\t$$zero, $a, $b"), + [(op CPURegs:$a, CPURegs:$b)], itin>; +} // Move from Hi/Lo class MoveFromLOHI func, string instr_asm>: - FR< 0x00, - func, - (outs CPURegs:$dst), - (ins), - !strconcat(instr_asm, "\t$dst"), - [], IIHiLo>; + FR<0x00, func, (outs CPURegs:$dst), (ins), + !strconcat(instr_asm, "\t$dst"), [], IIHiLo>; class MoveToLOHI func, string instr_asm>: - FR< 0x00, - func, - (outs), - (ins CPURegs:$src), - !strconcat(instr_asm, "\t$src"), - [], IIHiLo>; + FR<0x00, func, (outs), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$src"), [], IIHiLo>; class EffectiveAddress : - FI<0x09, - (outs CPURegs:$dst), - (ins mem:$addr), - instr_asm, - [(set CPURegs:$dst, addr:$addr)], IIAlu>; + FI<0x09, (outs CPURegs:$dst), (ins mem:$addr), + instr_asm, [(set CPURegs:$dst, addr:$addr)], IIAlu>; // Count Leading Ones/Zeros in Word -class CountLeading func, string instr_asm, SDNode CountOp>: - FR< 0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (CountOp CPURegs:$src))], IIAlu>; +class CountLeading func, string instr_asm, list pattern>: + FR<0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>, + Requires<[HasBitCount]> { + let shamt = 0; + let rt = rd; +} // Sign Extend in Register. class SignExtInReg func, string instr_asm, ValueType vt>: - FR< 0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; + FR<0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), + [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; // Byte Swap class ByteSwap func, string instr_asm>: - FR< 0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>; + FR<0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src), + !strconcat(instr_asm, "\t$dst, $src"), + [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>; // Conditional Move class CondMov func, string instr_asm, PatLeaf MovCode>: - FR< 0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T, - CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"), - [(set CPURegs:$dst, (MipsCMov CPURegs:$F, CPURegs:$T, - CPURegs:$cond, MovCode))], NoItinerary>; + FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T, + CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"), + [], NoItinerary>; + +// Read Hardware +class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$dst), (ins HWRegs:$src), + "rdhwr\t$dst, $src", [], IIAlu> { + let rs = 0; + let shamt = 0; +} //===----------------------------------------------------------------------===// // Pseudo instructions @@ -406,25 +409,127 @@ def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>; def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>; def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>; +// These macros are inserted to prevent GAS from complaining +// when using the AT register. +def NOAT : MipsPseudo<(outs), (ins), ".set\tnoat", []>; +def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; + // When handling PIC code the assembler needs .cpload and .cprestore // directives. If the real instructions corresponding these directives // are used, we have the same behavior, but get also a bunch of warnings // from the assembler. def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; -def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>; +def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc\n", []>; -// The supported Mips ISAs dont have any instruction close to the SELECT_CC -// operation. The solution is to create a Mips pseudo SELECT_CC instruction -// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally -// replace it for real supported nodes into EmitInstrWithCustomInserter let usesCustomInserter = 1 in { - class PseudoSelCC: - MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, - [(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>; + def ATOMIC_LOAD_ADD_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_add_8\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_add_8 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_ADD_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_add_16\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_add_16 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_ADD_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_add_32\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_add_32 CPURegs:$ptr, CPURegs:$incr))]>; + + def ATOMIC_LOAD_SUB_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_sub_8\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_sub_8 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_SUB_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_sub_16\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_sub_16 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_SUB_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_sub_32\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_sub_32 CPURegs:$ptr, CPURegs:$incr))]>; + + def ATOMIC_LOAD_AND_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_and_8\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_and_8 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_AND_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_and_16\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_and_16 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_AND_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_and_32\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_and_32 CPURegs:$ptr, CPURegs:$incr))]>; + + def ATOMIC_LOAD_OR_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_or_8\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_or_8 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_OR_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_or_16\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_or_16 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_OR_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_or_32\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_or_32 CPURegs:$ptr, CPURegs:$incr))]>; + + def ATOMIC_LOAD_XOR_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_xor_8\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_xor_8 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_XOR_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_xor_16\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_xor_16 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_XOR_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_xor_32\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_xor_32 CPURegs:$ptr, CPURegs:$incr))]>; + + def ATOMIC_LOAD_NAND_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_nand_8\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_nand_8 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_NAND_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_nand_16\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_nand_16 CPURegs:$ptr, CPURegs:$incr))]>; + def ATOMIC_LOAD_NAND_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + "atomic_load_nand_32\t$dst, $ptr, $incr", + [(set CPURegs:$dst, (atomic_load_nand_32 CPURegs:$ptr, CPURegs:$incr))]>; + + def ATOMIC_SWAP_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val), + "atomic_swap_8\t$dst, $ptr, $val", + [(set CPURegs:$dst, (atomic_swap_8 CPURegs:$ptr, CPURegs:$val))]>; + def ATOMIC_SWAP_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val), + "atomic_swap_16\t$dst, $ptr, $val", + [(set CPURegs:$dst, (atomic_swap_16 CPURegs:$ptr, CPURegs:$val))]>; + def ATOMIC_SWAP_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val), + "atomic_swap_32\t$dst, $ptr, $val", + [(set CPURegs:$dst, (atomic_swap_32 CPURegs:$ptr, CPURegs:$val))]>; + + def ATOMIC_CMP_SWAP_I8 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval), + "atomic_cmp_swap_8\t$dst, $ptr, $oldval, $newval", + [(set CPURegs:$dst, + (atomic_cmp_swap_8 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>; + def ATOMIC_CMP_SWAP_I16 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval), + "atomic_cmp_swap_16\t$dst, $ptr, $oldval, $newval", + [(set CPURegs:$dst, + (atomic_cmp_swap_16 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>; + def ATOMIC_CMP_SWAP_I32 : MipsPseudo< + (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval), + "atomic_cmp_swap_32\t$dst, $ptr, $oldval, $newval", + [(set CPURegs:$dst, + (atomic_cmp_swap_32 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>; } -def Select_CC : PseudoSelCC; - //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -444,9 +549,9 @@ def XORi : LogicI<0x0e, "xori", xor>; def LUi : LoadUpper<0x0f, "lui">; /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>; +def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu, 1>; def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>; -def ADD : ArithOverflowR<0x00, 0x20, "add">; +def ADD : ArithOverflowR<0x00, 0x20, "add", 1>; def SUB : ArithOverflowR<0x00, 0x22, "sub">; def SLT : SetCC_R<0x00, 0x2a, "slt", setlt>; def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult>; @@ -456,12 +561,18 @@ def XOR : LogicR<0x26, "xor", xor>; def NOR : LogicNOR<0x00, 0x27, "nor">; /// Shift Instructions -def SLL : LogicR_shift_imm<0x00, "sll", shl>; -def SRL : LogicR_shift_imm<0x02, "srl", srl>; -def SRA : LogicR_shift_imm<0x03, "sra", sra>; -def SLLV : LogicR_shift_reg<0x04, "sllv", shl>; -def SRLV : LogicR_shift_reg<0x06, "srlv", srl>; -def SRAV : LogicR_shift_reg<0x07, "srav", sra>; +def SLL : LogicR_shift_rotate_imm<0x00, 0x00, "sll", shl>; +def SRL : LogicR_shift_rotate_imm<0x02, 0x00, "srl", srl>; +def SRA : LogicR_shift_rotate_imm<0x03, 0x00, "sra", sra>; +def SLLV : LogicR_shift_rotate_reg<0x04, 0x00, "sllv", shl>; +def SRLV : LogicR_shift_rotate_reg<0x06, 0x00, "srlv", srl>; +def SRAV : LogicR_shift_rotate_reg<0x07, 0x00, "srav", sra>; + +// Rotate Instructions +let Predicates = [IsMips32r2] in { + def ROTR : LogicR_shift_rotate_imm<0x02, 0x01, "rotr", rotr>; + def ROTRV : LogicR_shift_rotate_reg<0x06, 0x01, "rotrv", rotr>; +} /// Load and Store Instructions def LB : LoadM<0x20, "lb", sextloadi8>; @@ -473,6 +584,14 @@ def SB : StoreM<0x28, "sb", truncstorei8>; def SH : StoreM<0x29, "sh", truncstorei16>; def SW : StoreM<0x2b, "sw", store>; +/// Load-linked, Store-conditional +let hasDelaySlot = 1 in + def LL : FI<0x30, (outs CPURegs:$dst), (ins mem:$addr), + "ll\t$dst, $addr", [], IILoad>; +let Constraints = "$src = $dst" in + def SC : FI<0x38, (outs CPURegs:$dst), (ins CPURegs:$src, mem:$addr), + "sc\t$src, $addr", [], IIStore>; + /// Jump and Branch Instructions def J : JumpFJ<0x02, "j">; def JR : JumpFR<0x00, 0x08, "jr">; @@ -498,13 +617,11 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target), "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>; -/// Multiply and Divide Instructions. -let Defs = [HI, LO] in { - def MULT : MulDiv<0x18, "mult", IIImul>; - def MULTu : MulDiv<0x19, "multu", IIImul>; - def DIV : MulDiv<0x1a, "div", IIIdiv>; - def DIVu : MulDiv<0x1b, "divu", IIIdiv>; -} +/// Multiply and Divide Instructions. +def MULT : Mul<0x18, "mult", IIImul>; +def MULTu : Mul<0x19, "multu", IIImul>; +def SDIV : Div; +def UDIV : Div; let Defs = [HI] in def MTHI : MoveToLOHI<0x11, "mthi">; @@ -526,10 +643,10 @@ let Predicates = [HasSEInReg] in { } /// Count Leading -let Predicates = [HasBitCount] in { - let rt = 0 in - def CLZ : CountLeading<0b010110, "clz", ctlz>; -} +def CLZ : CountLeading<0b100000, "clz", + [(set CPURegs:$dst, (ctlz CPURegs:$src))]>; +def CLO : CountLeading<0b100001, "clo", + [(set CPURegs:$dst, (ctlz (not CPURegs:$src)))]>; /// Byte Swap let Predicates = [HasSwap] in { @@ -541,10 +658,19 @@ let Predicates = [HasSwap] in { def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>; def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>; -let Predicates = [HasCondMov], isTwoAddress = 1 in { - def MOVN : CondMov<0x0a, "movn", MIPS_CMOV_NZERO>; - def MOVZ : CondMov<0x0b, "movz", MIPS_CMOV_ZERO>; -} +// Conditional moves: +// These instructions are expanded in +// MipsISelLowering::EmitInstrWithCustomInserter if target does not have +// conditional move instructions. +// flag:int, data:int +let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in + class CondMovIntInt funct, string instr_asm> : + FR<0, funct, (outs CPURegs:$dst), + (ins CPURegs:$T, CPURegs:$cond, CPURegs:$F), + !strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>; + +def MOVZ_I : CondMovIntInt<0x0a, "movz">; +def MOVN_I : CondMovIntInt<0x0b, "movn">; /// No operation let addr=0 in @@ -556,15 +682,23 @@ let addr=0 in // can be matched. It's similar to Sparc LEA_ADDRi def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">; -// MADD*/MSUB* are not part of MipsI either. -//def MADD : MArithR<0x00, "madd">; -//def MADDU : MArithR<0x01, "maddu">; -//def MSUB : MArithR<0x04, "msub">; -//def MSUBU : MArithR<0x05, "msubu">; +// DynAlloc node points to dynamically allocated stack space. +// $sp is added to the list of implicitly used registers to prevent dead code +// elimination from removing instructions that modify $sp. +let Uses = [SP] in +def DynAlloc : EffectiveAddress<"addiu\t$dst, ${addr:stackloc}">; + +// MADD*/MSUB* +def MADD : MArithR<0, "madd", MipsMAdd, 1>; +def MADDU : MArithR<1, "maddu", MipsMAddu, 1>; +def MSUB : MArithR<4, "msub", MipsMSub>; +def MSUBU : MArithR<5, "msubu", MipsMSubu>; // MUL is a assembly macro in the current used ISAs. In recent ISA's // it is a real instruction. -//def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; +def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul, 1>, Requires<[IsMips32]>; + +def RDHWR : ReadHardware; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -585,7 +719,7 @@ def : Pat<(subc CPURegs:$lhs, CPURegs:$rhs), (SUBu CPURegs:$lhs, CPURegs:$rhs)>; def : Pat<(addc CPURegs:$lhs, CPURegs:$rhs), (ADDu CPURegs:$lhs, CPURegs:$rhs)>; -def : Pat<(addc CPURegs:$src, imm:$imm), +def : Pat<(addc CPURegs:$src, immSExt16:$imm), (ADDiu CPURegs:$src, imm:$imm)>; // Call @@ -593,13 +727,16 @@ def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), (JAL tglobaladdr:$dst)>; def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), (JAL texternalsym:$dst)>; -def : Pat<(MipsJmpLink CPURegs:$dst), - (JALR CPURegs:$dst)>; +//def : Pat<(MipsJmpLink CPURegs:$dst), +// (JALR CPURegs:$dst)>; // hi/lo relocs def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : Pat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; +def : Pat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)), + (ADDiu CPURegs:$hi, tblockaddress:$lo)>; def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)), @@ -610,11 +747,31 @@ def : Pat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)), (ADDiu CPURegs:$hi, tconstpool:$lo)>; // gp_rel relocs -def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), +def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), (ADDiu CPURegs:$gp, tglobaladdr:$in)>; -def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), +def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), (ADDiu CPURegs:$gp, tconstpool:$in)>; +// tlsgd +def : Pat<(add CPURegs:$gp, (MipsTlsGd tglobaltlsaddr:$in)), + (ADDiu CPURegs:$gp, tglobaltlsaddr:$in)>; + +// tprel hi/lo +def : Pat<(MipsTprelHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; +def : Pat<(add CPURegs:$hi, (MipsTprelLo tglobaltlsaddr:$lo)), + (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>; + +// wrapper_pic +class WrapperPICPat: + Pat<(MipsWrapperPIC node:$in), + (ADDiu GP, node:$in)>; + +def : WrapperPICPat; +def : WrapperPICPat; +def : WrapperPICPat; +def : WrapperPICPat; +def : WrapperPICPat; + // Mips does not have "not", so we expand our way def : Pat<(not CPURegs:$in), (NOR CPURegs:$in, ZERO)>; @@ -651,27 +808,36 @@ def : Pat<(brcond CPURegs:$cond, bb:$dst), (BNE CPURegs:$cond, ZERO, bb:$dst)>; // select patterns -def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs))>; -def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTiu CPURegs:$lh, immSExt16:$rh))>; - -def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$rhs, CPURegs:$lhs))>; -def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs))>; - -def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVZ CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; -def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F), - (MOVN CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>; - -def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F), - (MOVN CPURegs:$F, CPURegs:$T, CPURegs:$cond)>; +multiclass MovzPats { + def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>; + def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>; + def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; + def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select (seteq CPURegs:$lhs, 0), RC:$T, RC:$F), + (MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>; +} + +multiclass MovnPats { + def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + (MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; + def : Pat<(select CPURegs:$cond, RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$cond, RC:$F)>; + def : Pat<(select (setne CPURegs:$lhs, 0), RC:$T, RC:$F), + (MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>; +} + +defm : MovzPats; +defm : MovnPats; // setcc patterns def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), @@ -699,6 +865,9 @@ def : Pat<(setge CPURegs:$lhs, immSExt16:$rhs), def : Pat<(setuge CPURegs:$lhs, immSExt16:$rhs), (XORi (SLTiu CPURegs:$lhs, immSExt16:$rhs), 1)>; +// select MipsDynAlloc +def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; + //===----------------------------------------------------------------------===// // Floating Point Support //===----------------------------------------------------------------------===//