diff options
Diffstat (limited to 'llvm/lib/Target/ARM/ARMInstrInfo.td')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrInfo.td | 282 |
1 files changed, 162 insertions, 120 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index c6bcad8e2a82..2a3a4e91eee4 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -14,6 +14,12 @@ // ARM specific DAG Nodes. // +/// Value type used for "condition code" operands. +defvar CondCodeVT = i32; + +/// Value type used for "flags" operands / results (either CPSR or FPSCR_NZCV). +defvar FlagsVT = i32; + // Type profiles. def SDT_ARMCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>; @@ -26,12 +32,19 @@ def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>; def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>; -def SDT_ARMCMov : SDTypeProfile<1, 3, - [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, - SDTCisVT<3, i32>]>; +def SDT_ARMCMov : SDTypeProfile<1, 4, [ + /* any */ // result + SDTCisSameAs<1, 0>, // value on false + SDTCisSameAs<2, 0>, // value on true + SDTCisVT<3, CondCodeVT>, // condition code + SDTCisVT<4, FlagsVT>, // in flags +]>; -def SDT_ARMBrcond : SDTypeProfile<0, 2, - [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>; +def SDT_ARMBrcond : SDTypeProfile<0, 2, [ + SDTCisVT<0, OtherVT>, // target basic block + SDTCisVT<1, CondCodeVT>, // condition code + SDTCisVT<2, FlagsVT>, // in flags +]>; def SDT_ARMBrJT : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>; @@ -50,7 +63,11 @@ def SDT_ARMAnd : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i32>]>; -def SDT_ARMCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; +def SDT_ARMCmp : SDTypeProfile<1, 2, [ + SDTCisVT<0, FlagsVT>, // out flags + SDTCisInt<1>, // lhs + SDTCisSameAs<2, 1> // rhs +]>; def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisPtrTy<1>, SDTCisVT<2, i32>]>; @@ -77,6 +94,18 @@ def SDT_ARMMEMCPY : SDTypeProfile<2, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i32>, SDTCisVT<3, i32>, SDTCisVT<4, i32>]>; +def SDTIntUnaryOpWithFlagsOut : SDTypeProfile<2, 1, [ + SDTCisInt<0>, // result + SDTCisVT<1, FlagsVT>, // out flags + SDTCisSameAs<2, 0> // operand +]>; + +def SDTIntUnaryOpWithFlagsIn : SDTypeProfile<1, 2, [ + SDTCisInt<0>, // result + SDTCisSameAs<1, 0>, // operand + SDTCisVT<1, FlagsVT> // in flags +]>; + def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, [SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, @@ -109,15 +138,17 @@ def ARMSmlaldx : SDNode<"ARMISD::SMLALDX", SDT_LongMac>; def ARMSmlsld : SDNode<"ARMISD::SMLSLD", SDT_LongMac>; def ARMSmlsldx : SDNode<"ARMISD::SMLSLDX", SDT_LongMac>; -def SDT_ARMCSel : SDTypeProfile<1, 3, - [SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, - SDTCisInt<3>, - SDTCisVT<3, i32>]>; +def SDT_ARMCSel : SDTypeProfile<1, 4, [ + /* any */ // result + SDTCisSameAs<1, 0>, // lhs + SDTCisSameAs<2, 0>, // rhs + SDTCisVT<3, CondCodeVT>, // condition code + SDTCisVT<3, FlagsVT> // in flags +]>; -def ARMcsinv : SDNode<"ARMISD::CSINV", SDT_ARMCSel, [SDNPOptInGlue]>; -def ARMcsneg : SDNode<"ARMISD::CSNEG", SDT_ARMCSel, [SDNPOptInGlue]>; -def ARMcsinc : SDNode<"ARMISD::CSINC", SDT_ARMCSel, [SDNPOptInGlue]>; +def ARMcsinv : SDNode<"ARMISD::CSINV", SDT_ARMCSel>; +def ARMcsneg : SDNode<"ARMISD::CSNEG", SDT_ARMCSel>; +def ARMcsinc : SDNode<"ARMISD::CSINC", SDT_ARMCSel>; def SDT_MulHSR : SDTypeProfile<1, 3, [SDTCisVT<0,i32>, SDTCisSameAs<0, 1>, @@ -158,15 +189,13 @@ def ARMseretglue : SDNode<"ARMISD::SERET_GLUE", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; def ARMintretglue : SDNode<"ARMISD::INTRET_GLUE", SDT_ARMcall, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -def ARMcmov : SDNode<"ARMISD::CMOV", SDT_ARMCMov, - [SDNPInGlue]>; +def ARMcmov : SDNode<"ARMISD::CMOV", SDT_ARMCMov>; def ARMssat : SDNode<"ARMISD::SSAT", SDTIntSatNoShOp, []>; def ARMusat : SDNode<"ARMISD::USAT", SDTIntSatNoShOp, []>; -def ARMbrcond : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond, - [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>; +def ARMbrcond : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond, [SDNPHasChain]>; def ARMbrjt : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT, [SDNPHasChain]>; @@ -176,14 +205,11 @@ def ARMbr2jt : SDNode<"ARMISD::BR2_JT", SDT_ARMBr2JT, def ARMBcci64 : SDNode<"ARMISD::BCC_i64", SDT_ARMBCC_i64, [SDNPHasChain]>; -def ARMcmp : SDNode<"ARMISD::CMP", SDT_ARMCmp, - [SDNPOutGlue]>; +def ARMcmp : SDNode<"ARMISD::CMP", SDT_ARMCmp>; -def ARMcmn : SDNode<"ARMISD::CMN", SDT_ARMCmp, - [SDNPOutGlue]>; +def ARMcmn : SDNode<"ARMISD::CMN", SDT_ARMCmp>; -def ARMcmpZ : SDNode<"ARMISD::CMPZ", SDT_ARMCmp, - [SDNPOutGlue, SDNPCommutative]>; +def ARMcmpZ : SDNode<"ARMISD::CMPZ", SDT_ARMCmp, [SDNPCommutative]>; def ARMpic_add : SDNode<"ARMISD::PIC_ADD", SDT_ARMPICAdd>; @@ -191,9 +217,9 @@ def ARMasrl : SDNode<"ARMISD::ASRL", SDT_ARMIntShiftParts, []>; def ARMlsrl : SDNode<"ARMISD::LSRL", SDT_ARMIntShiftParts, []>; def ARMlsll : SDNode<"ARMISD::LSLL", SDT_ARMIntShiftParts, []>; -def ARMsrl_glue : SDNode<"ARMISD::SRL_GLUE", SDTIntUnaryOp, [SDNPOutGlue]>; -def ARMsra_glue : SDNode<"ARMISD::SRA_GLUE", SDTIntUnaryOp, [SDNPOutGlue]>; -def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInGlue ]>; +def ARMlsrs1 : SDNode<"ARMISD::LSRS1", SDTIntUnaryOpWithFlagsOut>; +def ARMasrs1 : SDNode<"ARMISD::ASRS1", SDTIntUnaryOpWithFlagsOut>; +def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOpWithFlagsIn>; def ARMaddc : SDNode<"ARMISD::ADDC", SDTBinaryArithWithFlags, [SDNPCommutative]>; @@ -371,12 +397,14 @@ def ARMVCCElse : PatLeaf<(i32 2)>; // imm_neg_XFORM - Return the negation of an i32 immediate value. def imm_neg_XFORM : SDNodeXForm<imm, [{ - return CurDAG->getTargetConstant(-(int)N->getZExtValue(), SDLoc(N), MVT::i32); + return CurDAG->getSignedTargetConstant(-(int)N->getZExtValue(), SDLoc(N), + MVT::i32); }]>; // imm_not_XFORM - Return the complement of a i32 immediate value. def imm_not_XFORM : SDNodeXForm<imm, [{ - return CurDAG->getTargetConstant(~(int)N->getZExtValue(), SDLoc(N), MVT::i32); + return CurDAG->getSignedTargetConstant(~(int)N->getZExtValue(), SDLoc(N), + MVT::i32); }]>; def gi_imm_not_XFORM : GICustomOperandRenderer<"renderInvertedImm">, GISDNodeXFormEquiv<imm_not_XFORM>; @@ -1197,25 +1225,25 @@ def PostIdxRegShiftedAsmOperand : AsmOperandClass { let ParserMethod = "parsePostIdxReg"; } def am2offset_reg : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode2OffsetReg", - [], [SDNPWantRoot]> { + ComplexPattern<i32, 2, "SelectAddrMode2OffsetReg"> { let EncoderMethod = "getAddrMode2OffsetOpValue"; let PrintMethod = "printAddrMode2OffsetOperand"; // When using this for assembly, it's always as a post-index offset. let ParserMatchClass = PostIdxRegShiftedAsmOperand; let MIOperandInfo = (ops GPRnopc, i32imm); + let WantsRoot = true; } // FIXME: am2offset_imm should only need the immediate, not the GPR. Having // the GPR is purely vestigal at this point. def AM2OffsetImmAsmOperand : AsmOperandClass { let Name = "AM2OffsetImm"; } def am2offset_imm : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode2OffsetImm", - [], [SDNPWantRoot]> { + ComplexPattern<i32, 2, "SelectAddrMode2OffsetImm"> { let EncoderMethod = "getAddrMode2OffsetOpValue"; let PrintMethod = "printAddrMode2OffsetOperand"; let ParserMatchClass = AM2OffsetImmAsmOperand; let MIOperandInfo = (ops GPRnopc, i32imm); + let WantsRoot = true; } @@ -1247,13 +1275,12 @@ def AM3OffsetAsmOperand : AsmOperandClass { let Name = "AM3Offset"; let ParserMethod = "parseAM3Offset"; } -def am3offset : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode3Offset", - [], [SDNPWantRoot]> { +def am3offset : MemOperand, ComplexPattern<i32, 2, "SelectAddrMode3Offset"> { let EncoderMethod = "getAddrMode3OffsetOpValue"; let PrintMethod = "printAddrMode3OffsetOperand"; let ParserMatchClass = AM3OffsetAsmOperand; let MIOperandInfo = (ops GPR, i32imm); + let WantsRoot = true; } // ldstm_mode := {ia, ib, da, db} @@ -1300,40 +1327,39 @@ def addrmode5fp16 : AddrMode5FP16 { // addrmode6 := reg with optional alignment // def AddrMode6AsmOperand : AsmOperandClass { let Name = "AlignedMemory"; } -def addrmode6 : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{ +def addrmode6 : MemOperand, ComplexPattern<i32, 2, "SelectAddrMode6"> { let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm:$align); let EncoderMethod = "getAddrMode6AddressOpValue"; let DecoderMethod = "DecodeAddrMode6Operand"; let ParserMatchClass = AddrMode6AsmOperand; + let WantsParent = true; } -def am6offset : MemOperand, - ComplexPattern<i32, 1, "SelectAddrMode6Offset", - [], [SDNPWantRoot]> { +def am6offset : MemOperand, ComplexPattern<i32, 1, "SelectAddrMode6Offset"> { let PrintMethod = "printAddrMode6OffsetOperand"; let MIOperandInfo = (ops GPR); let EncoderMethod = "getAddrMode6OffsetOpValue"; let DecoderMethod = "DecodeGPRRegisterClass"; + let WantsRoot = true; } // Special version of addrmode6 to handle alignment encoding for VST1/VLD1 // (single element from one lane) for size 32. -def addrmode6oneL32 : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{ +def addrmode6oneL32 : MemOperand, ComplexPattern<i32, 2, "SelectAddrMode6"> { let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm); let EncoderMethod = "getAddrMode6OneLane32AddressOpValue"; + let WantsParent = true; } // Base class for addrmode6 with specific alignment restrictions. -class AddrMode6Align : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{ +class AddrMode6Align : MemOperand, ComplexPattern<i32, 2, "SelectAddrMode6"> { let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm:$align); let EncoderMethod = "getAddrMode6AddressOpValue"; let DecoderMethod = "DecodeAddrMode6Operand"; + let WantsParent = true; } // Special version of addrmode6 to handle no allowed alignment encoding for @@ -1404,22 +1430,23 @@ def addrmode6align64or128or256 : AddrMode6Align { // Special version of addrmode6 to handle alignment encoding for VLD-dup // instructions, specifically VLD4-dup. -def addrmode6dup : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{ +def addrmode6dup : MemOperand, ComplexPattern<i32, 2, "SelectAddrMode6"> { let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm); let EncoderMethod = "getAddrMode6DupAddressOpValue"; // FIXME: This is close, but not quite right. The alignment specifier is // different. let ParserMatchClass = AddrMode6AsmOperand; + let WantsParent = true; } // Base class for addrmode6dup with specific alignment restrictions. class AddrMode6DupAlign : MemOperand, - ComplexPattern<i32, 2, "SelectAddrMode6", [], [SDNPWantParent]>{ + ComplexPattern<i32, 2, "SelectAddrMode6"> { let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm); let EncoderMethod = "getAddrMode6DupAddressOpValue"; + let WantsParent = true; } // Special version of addrmode6 to handle no allowed alignment encoding for @@ -1759,7 +1786,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc, string rrDecoderMethod = ""> { def ri : AI1<opcod, (outs), (ins GPR:$Rn, mod_imm:$imm), DPFrm, iii, opc, "\t$Rn, $imm", - [(opnode GPR:$Rn, mod_imm:$imm)]>, + [(set CPSR, (opnode GPR:$Rn, mod_imm:$imm))]>, Sched<[WriteCMP, ReadALU]> { bits<4> Rn; bits<12> imm; @@ -1773,7 +1800,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc, } def rr : AI1<opcod, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, iir, opc, "\t$Rn, $Rm", - [(opnode GPR:$Rn, GPR:$Rm)]>, + [(set CPSR, (opnode GPR:$Rn, GPR:$Rm))]>, Sched<[WriteCMP, ReadALU, ReadALU]> { bits<4> Rn; bits<4> Rm; @@ -1791,7 +1818,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc, def rsi : AI1<opcod, (outs), (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, iis, opc, "\t$Rn, $shift", - [(opnode GPR:$Rn, so_reg_imm:$shift)]>, + [(set CPSR, (opnode GPR:$Rn, so_reg_imm:$shift))]>, Sched<[WriteCMPsi, ReadALU]> { bits<4> Rn; bits<12> shift; @@ -1808,7 +1835,7 @@ multiclass AI1_cmp_irs<bits<4> opcod, string opc, def rsr : AI1<opcod, (outs), (ins GPRnopc:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, iis, opc, "\t$Rn, $shift", - [(opnode GPRnopc:$Rn, so_reg_reg:$shift)]>, + [(set CPSR, (opnode GPRnopc:$Rn, so_reg_reg:$shift))]>, Sched<[WriteCMPsr, ReadALU]> { bits<4> Rn; bits<12> shift; @@ -2376,13 +2403,13 @@ def UDF : AInoP<(outs), (ins imm0_65535:$imm16), MiscFrm, NoItinerary, * - In ARM: UDF #60896; * - In Thumb: UDF #254 followed by a branch-to-self. */ -let isBarrier = 1, isTerminator = 1 in +let isTrap = 1 in def TRAPNaCl : AXI<(outs), (ins), MiscFrm, NoItinerary, "trap", [(trap)]>, Requires<[IsARM,UseNaClTrap]> { let Inst = 0xe7fedef0; } -let isBarrier = 1, isTerminator = 1 in +let isTrap = 1 in def TRAP : AXI<(outs), (ins), MiscFrm, NoItinerary, "trap", [(trap)]>, Requires<[IsARM,DontUseNaClTrap]> { @@ -3293,7 +3320,7 @@ def STRH_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), } - +let mayStore = 1, hasSideEffects = 0 in { def STRH_PRE : AI3ldstidx<0b1011, 0, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode3_pre:$addr), IndexModePre, StMiscFrm, IIC_iStore_bh_ru, @@ -3325,6 +3352,7 @@ def STRH_POST : AI3ldstidx<0b1011, 0, 0, (outs GPR:$Rn_wb), let Inst{3-0} = offset{3-0}; // imm3_0/Rm let DecoderMethod = "DecodeAddrMode3Instruction"; } +} // mayStore = 1, hasSideEffects = 0 let mayStore = 1, hasSideEffects = 0, hasExtraSrcRegAllocReq = 1 in { def STRD_PRE : AI3ldstidx<0b1111, 0, 1, (outs GPR:$Rn_wb), @@ -3360,6 +3388,8 @@ def STRD_POST: AI3ldstidx<0b1111, 0, 0, (outs GPR:$Rn_wb), // STRT, STRBT, and STRHT +let mayStore = 1, hasSideEffects = 0 in { + def STRBT_POST_REG : AI2ldstidx<0, 1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset), IndexModePost, StFrm, IIC_iStore_bh_ru, @@ -3400,7 +3430,6 @@ def STRBT_POST : ARMAsmPseudo<"strbt${q} $Rt, $addr", (ins GPR:$Rt, addr_offset_none:$addr, pred:$q)>; -let mayStore = 1, hasSideEffects = 0 in { def STRT_POST_REG : AI2ldstidx<0, 0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset), IndexModePost, StFrm, IIC_iStore_ru, @@ -3436,7 +3465,6 @@ def STRT_POST_IMM let Inst{11-0} = offset{11-0}; let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } -} def STRT_POST : ARMAsmPseudo<"strt${q} $Rt, $addr", @@ -3465,7 +3493,6 @@ multiclass AI3strT<bits<4> op, string opc> { } } - defm STRHT : AI3strT<0b1011, "strht">; def STL : AIstrrel<0b00, (outs), (ins GPR:$Rt, addr_offset_none:$addr), @@ -3475,6 +3502,8 @@ def STLB : AIstrrel<0b10, (outs), (ins GPR:$Rt, addr_offset_none:$addr), def STLH : AIstrrel<0b11, (outs), (ins GPR:$Rt, addr_offset_none:$addr), NoItinerary, "stlh", "\t$Rt, $addr", []>; +} // mayStore = 1, hasSideEffects = 0 + //===----------------------------------------------------------------------===// // Load / store multiple Instructions. // @@ -3728,20 +3757,17 @@ def : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>, Requires<[IsARM, HasV6T2]>; let Uses = [CPSR] in -def RRX: PseudoInst<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVsi, - [(set GPR:$Rd, (ARMrrx GPR:$Rm))]>, UnaryDP, - Requires<[IsARM]>, Sched<[WriteALU]>; - -// These aren't really mov instructions, but we have to define them this way -// due to glue operands. +def RRX : PseudoInst<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVsi, + [(set GPR:$Rd, (ARMrrx GPR:$Rm, CPSR))]>, + UnaryDP, Requires<[IsARM]>, Sched<[WriteALU]>; let Defs = [CPSR] in { -def MOVsrl_glue : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, - [(set GPR:$dst, (ARMsrl_glue GPR:$src))]>, UnaryDP, - Sched<[WriteALU]>, Requires<[IsARM]>; -def MOVsra_glue : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, - [(set GPR:$dst, (ARMsra_glue GPR:$src))]>, UnaryDP, - Sched<[WriteALU]>, Requires<[IsARM]>; + def LSRs1 : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + [(set GPR:$dst, CPSR, (ARMlsrs1 GPR:$src))]>, + UnaryDP, Sched<[WriteALU]>, Requires<[IsARM]>; + def ASRs1 : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + [(set GPR:$dst, CPSR, (ARMasrs1 GPR:$src))]>, + UnaryDP, Sched<[WriteALU]>, Requires<[IsARM]>; } //===----------------------------------------------------------------------===// @@ -4741,6 +4767,7 @@ def : ARMV6Pat<(int_arm_smusdx GPRnopc:$Rn, GPRnopc:$Rm), //===----------------------------------------------------------------------===// // Division Instructions (ARMv7-A with virtualization extension) // +let TwoOperandAliasConstraint = "$Rn = $Rd" in { def SDIV : ADivA1I<0b001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iDIV, "sdiv", "\t$Rd, $Rn, $Rm", [(set GPR:$Rd, (sdiv GPR:$Rn, GPR:$Rm))]>, @@ -4752,6 +4779,7 @@ def UDIV : ADivA1I<0b011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iDIV, [(set GPR:$Rd, (udiv GPR:$Rn, GPR:$Rm))]>, Requires<[IsARM, HasDivideInARM]>, Sched<[WriteDIV]>; +} //===----------------------------------------------------------------------===// // Misc. Arithmetic Instructions. @@ -4929,7 +4957,7 @@ def : ARMPat<(ARMcmpZ so_reg_reg:$rhs, 0), let isCompare = 1, Defs = [CPSR] in { def CMNri : AI1<0b1011, (outs), (ins GPR:$Rn, mod_imm:$imm), DPFrm, IIC_iCMPi, "cmn", "\t$Rn, $imm", - [(ARMcmn GPR:$Rn, mod_imm:$imm)]>, + [(set CPSR, (ARMcmn GPR:$Rn, mod_imm:$imm))]>, Sched<[WriteCMP, ReadALU]> { bits<4> Rn; bits<12> imm; @@ -4945,8 +4973,8 @@ def CMNri : AI1<0b1011, (outs), (ins GPR:$Rn, mod_imm:$imm), DPFrm, IIC_iCMPi, // CMN register-register/shift def CMNzrr : AI1<0b1011, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, IIC_iCMPr, "cmn", "\t$Rn, $Rm", - [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))> - GPR:$Rn, GPR:$Rm)]>, Sched<[WriteCMP, ReadALU, ReadALU]> { + [(set CPSR, (BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))> + GPR:$Rn, GPR:$Rm))]>, Sched<[WriteCMP, ReadALU, ReadALU]> { bits<4> Rn; bits<4> Rm; let isCommutable = 1; @@ -4963,8 +4991,8 @@ def CMNzrr : AI1<0b1011, (outs), (ins GPR:$Rn, GPR:$Rm), DPFrm, IIC_iCMPr, def CMNzrsi : AI1<0b1011, (outs), (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm, IIC_iCMPsr, "cmn", "\t$Rn, $shift", - [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))> - GPR:$Rn, so_reg_imm:$shift)]>, + [(set CPSR, (BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))> + GPR:$Rn, so_reg_imm:$shift))]>, Sched<[WriteCMPsi, ReadALU]> { bits<4> Rn; bits<12> shift; @@ -4982,8 +5010,8 @@ def CMNzrsi : AI1<0b1011, (outs), def CMNzrsr : AI1<0b1011, (outs), (ins GPRnopc:$Rn, so_reg_reg:$shift), DPSoRegRegFrm, IIC_iCMPsr, "cmn", "\t$Rn, $shift", - [(BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))> - GPRnopc:$Rn, so_reg_reg:$shift)]>, + [(set CPSR, (BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))> + GPRnopc:$Rn, so_reg_reg:$shift))]>, Sched<[WriteCMPsr, ReadALU]> { bits<4> Rn; bits<12> shift; @@ -5038,65 +5066,74 @@ let hasSideEffects = 0 in { let isCommutable = 1, isSelect = 1 in def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, GPR:$Rm, cmovpred:$p), - 4, IIC_iCMOVr, - [(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, - cmovpred:$p))]>, + (ins GPR:$false, GPR:$Rm, pred:$p), + 4, IIC_iCMOVr, []>, RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; def MOVCCsi : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, so_reg_imm:$shift, cmovpred:$p), - 4, IIC_iCMOVsr, - [(set GPR:$Rd, - (ARMcmov GPR:$false, so_reg_imm:$shift, - cmovpred:$p))]>, + (ins GPR:$false, so_reg_imm:$shift, pred:$p), + 4, IIC_iCMOVsr, []>, RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; def MOVCCsr : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, so_reg_reg:$shift, cmovpred:$p), - 4, IIC_iCMOVsr, - [(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_reg:$shift, - cmovpred:$p))]>, + (ins GPR:$false, so_reg_reg:$shift, pred:$p), + 4, IIC_iCMOVsr, []>, RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; let isMoveImm = 1 in def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, imm0_65535_expr:$imm, cmovpred:$p), - 4, IIC_iMOVi, - [(set GPR:$Rd, (ARMcmov GPR:$false, imm0_65535:$imm, - cmovpred:$p))]>, + (ins GPR:$false, imm0_65535_expr:$imm, pred:$p), + 4, IIC_iMOVi, []>, RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>, Sched<[WriteALU]>; let isMoveImm = 1 in def MOVCCi : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, mod_imm:$imm, cmovpred:$p), - 4, IIC_iCMOVi, - [(set GPR:$Rd, (ARMcmov GPR:$false, mod_imm:$imm, - cmovpred:$p))]>, + (ins GPR:$false, mod_imm:$imm, pred:$p), + 4, IIC_iCMOVi, []>, RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; // Two instruction predicate mov immediate. let isMoveImm = 1 in def MOVCCi32imm : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, i32imm:$src, cmovpred:$p), - 8, IIC_iCMOVix2, - [(set GPR:$Rd, (ARMcmov GPR:$false, imm:$src, - cmovpred:$p))]>, + (ins GPR:$false, i32imm:$src, pred:$p), + 8, IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>; let isMoveImm = 1 in def MVNCCi : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, mod_imm:$imm, cmovpred:$p), - 4, IIC_iCMOVi, - [(set GPR:$Rd, (ARMcmov GPR:$false, mod_imm_not:$imm, - cmovpred:$p))]>, + (ins GPR:$false, mod_imm:$imm, pred:$p), + 4, IIC_iCMOVi, []>, RegConstraint<"$false = $Rd">, Sched<[WriteALU]>; } // hasSideEffects +// The following patterns have to be defined out-of-line because the number +// of instruction operands does not match the number of SDNode operands +// (`pred` counts as one operand). + +def : ARMPat<(ARMcmov i32:$false, i32:$Rm, imm:$cc, CPSR), + (MOVCCr $false, $Rm, imm:$cc, CPSR)>; + +def : ARMPat<(ARMcmov i32:$false, so_reg_imm:$shift, imm:$cc, CPSR), + (MOVCCsi $false, so_reg_imm:$shift, imm:$cc, CPSR)>; + +def : ARMPat<(ARMcmov i32:$false, so_reg_reg:$shift, imm:$cc, CPSR), + (MOVCCsr $false, so_reg_reg:$shift, imm:$cc, CPSR)>; + +def : ARMV6T2Pat<(ARMcmov i32:$false, imm0_65535:$imm, imm:$cc, CPSR), + (MOVCCi16 $false, imm0_65535:$imm, imm:$cc, CPSR)>; + +def : ARMPat<(ARMcmov i32:$false, mod_imm:$imm, imm:$cc, CPSR), + (MOVCCi $false, mod_imm:$imm, imm:$cc, CPSR)>; + +def : ARMPat<(ARMcmov i32:$false, mod_imm_not:$imm, imm:$cc, CPSR), + (MVNCCi $false, mod_imm_not:$imm, imm:$cc, CPSR)>; + +def : ARMV6T2Pat<(ARMcmov i32:$false, imm:$src, imm:$cc, CPSR), + (MOVCCi32imm $false, imm:$src, imm:$cc, CPSR)>; //===----------------------------------------------------------------------===// // Atomic operations intrinsics @@ -5597,15 +5634,19 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm, list<dag> pattern> { } } +let mayLoad = 1 in { defm LDC : LdStCop <1, 0, "ldc", [(int_arm_ldc timm:$cop, timm:$CRd, addrmode5:$addr)]>; defm LDCL : LdStCop <1, 1, "ldcl", [(int_arm_ldcl timm:$cop, timm:$CRd, addrmode5:$addr)]>; defm LDC2 : LdSt2Cop<1, 0, "ldc2", [(int_arm_ldc2 timm:$cop, timm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>; defm LDC2L : LdSt2Cop<1, 1, "ldc2l", [(int_arm_ldc2l timm:$cop, timm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>; +} +let mayStore = 1 in { defm STC : LdStCop <0, 0, "stc", [(int_arm_stc timm:$cop, timm:$CRd, addrmode5:$addr)]>; defm STCL : LdStCop <0, 1, "stcl", [(int_arm_stcl timm:$cop, timm:$CRd, addrmode5:$addr)]>; defm STC2 : LdSt2Cop<0, 0, "stc2", [(int_arm_stc2 timm:$cop, timm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>; defm STC2L : LdSt2Cop<0, 1, "stc2l", [(int_arm_stc2l timm:$cop, timm:$CRd, addrmode5:$addr)]>, Requires<[IsARM,PreV8]>; +} } // DecoderNamespace = "CoProc" @@ -6507,8 +6548,21 @@ def CMP_SWAP_32 : PseudoInst<(outs GPR:$Rd, GPR:$temp), (ins GPR:$addr, GPR:$desired, GPR:$new), NoItinerary, []>, Sched<[]>; -def CMP_SWAP_64 : PseudoInst<(outs GPRPair:$Rd, GPR:$temp), - (ins GPR:$addr, GPRPair:$desired, GPRPair:$new), +// The addr_temp and addr_temp_out operands are logically a pair of GPR +// operands: +// * addr is an input, holding the address to swap. +// * temp is a earlyclobber output, used internally in the expansion of the +// pseudo-inst. +// These are combined into one GPRPair operand to ensure that register +// allocation always succeeds. In the worst case there are only 4 GPRPair +// registers available, of which this instruction needs 3 for the other +// operands. If these operands weren't combined they would also use two GPR +// registers, which could overlap with two different GPRPairs, causing +// allocation to fail. With them combined, we need to allocate 4 GPRPairs, +// which will always succeed. +let Constraints = "@earlyclobber $Rd,$addr_temp_out = $addr_temp" in +def CMP_SWAP_64 : PseudoInst<(outs GPRPair:$Rd, GPRPair:$addr_temp_out), + (ins GPRPair:$addr_temp, GPRPair:$desired, GPRPair:$new), NoItinerary, []>, Sched<[]>; } @@ -6534,15 +6588,3 @@ let isPseudo = 1 in { let isTerminator = 1 in def SEH_EpilogEnd : PseudoInst<(outs), (ins), NoItinerary, []>, Sched<[]>; } - - -//===----------------------------------------------------------------------===// -// Pseudo Instructions for use when early-clobber is defined and Greedy Register -// Allocation is used. This ensures the constraint is used properly. -//===----------------------------------------------------------------------===// -let isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { - def PseudoARMInitUndefMQPR : PseudoInst<(outs MQPR:$vd), (ins), NoItinerary, []>; - def PseudoARMInitUndefSPR : PseudoInst<(outs SPR:$sd), (ins), NoItinerary, []>; - def PseudoARMInitUndefDPR_VFP2 : PseudoInst<(outs DPR_VFP2:$dd), (ins), NoItinerary, []>; - def PseudoARMInitUndefGPR : PseudoInst<(outs GPR:$rd), (ins), NoItinerary, []>; -} |
