[llvm-commits] [llvm] r138791 - in /llvm/trunk: lib/Target/ARM/ARMBaseRegisterInfo.cpp lib/Target/ARM/ARMBaseRegisterInfo.h lib/Target/ARM/ARMISelLowering.cpp lib/Target/ARM/ARMISelLowering.h lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/ARMRegisterInfo.td test/CodeGen/ARM/2011-08-29-SchedCycle.ll test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll
Evan Cheng
evan.cheng at apple.com
Tue Aug 30 10:34:11 PDT 2011
The patch is incomplete. I'm working on a follow up now.
Evan
On Aug 29, 2011, at 6:34 PM, Evan Cheng wrote:
> Author: evancheng
> Date: Mon Aug 29 20:34:54 2011
> New Revision: 138791
>
> URL: http://llvm.org/viewvc/llvm-project?rev=138791&view=rev
> Log:
> Change ARM / Thumb2 addc / adde and subc / sube modeling to use physical
> register dependency (rather than glue them together). This is general
> goodness as it gives scheduler more freedom. However it is motivated by
> a nasty bug in isel.
>
> When a i64 sub is expanded to subc + sube.
> libcall #1
> \
> \ subc
> \ / \
> \ / \
> \ / libcall #2
> sube
>
> If the libcalls are not serialized (i.e. both have chains which are dag
> entry), legalizer can serialize them in arbitrary orders. If it's
> unlucky, it can force libcall #2 before libcall #1 in the above case.
>
> subc
> |
> libcall #2
> |
> libcall #1
> |
> sube
>
> However since subc and sube are "glued" together, this ends up being a
> cycle when the scheduler combine subc and sube as a single scheduling
> unit.
>
> The right solution is to fix LegalizeType too chains the libcalls together.
> However, LegalizeType is not processing nodes in order so that's harder than
> it should be. For now, the move to physical register dependency will do.
>
> rdar://10019576
>
> Added:
> llvm/trunk/test/CodeGen/ARM/2011-08-29-SchedCycle.ll
> Modified:
> llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
> llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
> llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> llvm/trunk/lib/Target/ARM/ARMISelLowering.h
> llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
> llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
> llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td
> llvm/trunk/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll
>
> Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp Mon Aug 29 20:34:54 2011
> @@ -374,6 +374,13 @@
> return ARM::GPRRegisterClass;
> }
>
> +const TargetRegisterClass *
> +ARMBaseRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
> + if (RC == &ARM::CCRRegClass)
> + return 0; // Can't copy CCR registers.
> + return RC;
> +}
> +
> unsigned
> ARMBaseRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
> MachineFunction &MF) const {
>
> Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h (original)
> +++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h Mon Aug 29 20:34:54 2011
> @@ -116,6 +116,8 @@
> unsigned &NewSubIdx) const;
>
> const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const;
> + const TargetRegisterClass*
> + getCrossCopyRegClass(const TargetRegisterClass *RC) const;
>
> const TargetRegisterClass*
> getLargestLegalSuperClass(const TargetRegisterClass *RC) const;
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Aug 29 20:34:54 2011
> @@ -551,6 +551,14 @@
> setOperationAction(ISD::SRL, MVT::i64, Custom);
> setOperationAction(ISD::SRA, MVT::i64, Custom);
>
> + if (!Subtarget->isThumb1Only()) {
> + // FIXME: We should do this for Thumb1 as well.
> + setOperationAction(ISD::ADDC, MVT::i32, Custom);
> + setOperationAction(ISD::ADDE, MVT::i32, Custom);
> + setOperationAction(ISD::SUBC, MVT::i32, Custom);
> + setOperationAction(ISD::SUBE, MVT::i32, Custom);
> + }
> +
> // ARM does not have ROTL.
> setOperationAction(ISD::ROTL, MVT::i32, Expand);
> setOperationAction(ISD::CTTZ, MVT::i32, Custom);
> @@ -813,6 +821,11 @@
> case ARMISD::SRA_FLAG: return "ARMISD::SRA_FLAG";
> case ARMISD::RRX: return "ARMISD::RRX";
>
> + case ARMISD::ADDC: return "ARMISD::ADDC";
> + case ARMISD::ADDE: return "ARMISD::ADDE";
> + case ARMISD::SUBC: return "ARMISD::SUBC";
> + case ARMISD::SUBE: return "ARMISD::SUBE";
> +
> case ARMISD::VMOVRRD: return "ARMISD::VMOVRRD";
> case ARMISD::VMOVDRR: return "ARMISD::VMOVDRR";
>
> @@ -4812,6 +4825,27 @@
> return N0;
> }
>
> +static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
> + EVT VT = Op.getNode()->getValueType(0);
> + SDVTList VTs = DAG.getVTList(VT, MVT::i32);
> +
> + unsigned Opc;
> + bool ExtraOp = false;
> + switch (Op.getOpcode()) {
> + default: assert(0 && "Invalid code");
> + case ISD::ADDC: Opc = ARMISD::ADDC; break;
> + case ISD::ADDE: Opc = ARMISD::ADDE; ExtraOp = true; break;
> + case ISD::SUBC: Opc = ARMISD::SUBC; break;
> + case ISD::SUBE: Opc = ARMISD::SUBE; ExtraOp = true; break;
> + }
> +
> + if (!ExtraOp)
> + return DAG.getNode(Opc, Op->getDebugLoc(), VTs, Op.getOperand(0),
> + Op.getOperand(1));
> + return DAG.getNode(Opc, Op->getDebugLoc(), VTs, Op.getOperand(0),
> + Op.getOperand(1), Op.getOperand(2));
> +}
> +
> SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
> switch (Op.getOpcode()) {
> default: llvm_unreachable("Don't know how to custom lower this!");
> @@ -4859,6 +4893,10 @@
> case ISD::MUL: return LowerMUL(Op, DAG);
> case ISD::SDIV: return LowerSDIV(Op, DAG);
> case ISD::UDIV: return LowerUDIV(Op, DAG);
> + case ISD::ADDC:
> + case ISD::ADDE:
> + case ISD::SUBC:
> + case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
> }
> return SDValue();
> }
> @@ -5208,76 +5246,6 @@
> llvm_unreachable("Expecting a BB with two successors!");
> }
>
> -// FIXME: This opcode table should obviously be expressed in the target
> -// description. We probably just need a "machine opcode" value in the pseudo
> -// instruction. But the ideal solution maybe to simply remove the "S" version
> -// of the opcode altogether.
> -struct AddSubFlagsOpcodePair {
> - unsigned PseudoOpc;
> - unsigned MachineOpc;
> -};
> -
> -static const AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = {
> - {ARM::ADCSri, ARM::ADCri},
> - {ARM::ADCSrr, ARM::ADCrr},
> - {ARM::ADCSrsi, ARM::ADCrsi},
> - {ARM::ADCSrsr, ARM::ADCrsr},
> - {ARM::SBCSri, ARM::SBCri},
> - {ARM::SBCSrr, ARM::SBCrr},
> - {ARM::SBCSrsi, ARM::SBCrsi},
> - {ARM::SBCSrsr, ARM::SBCrsr},
> - {ARM::RSBSri, ARM::RSBri},
> - {ARM::RSBSrr, ARM::RSBrr},
> - {ARM::RSBSrsi, ARM::RSBrsi},
> - {ARM::RSBSrsr, ARM::RSBrsr},
> - {ARM::RSCSri, ARM::RSCri},
> - {ARM::RSCSrsi, ARM::RSCrsi},
> - {ARM::RSCSrsr, ARM::RSCrsr},
> - {ARM::t2ADCSri, ARM::t2ADCri},
> - {ARM::t2ADCSrr, ARM::t2ADCrr},
> - {ARM::t2ADCSrs, ARM::t2ADCrs},
> - {ARM::t2SBCSri, ARM::t2SBCri},
> - {ARM::t2SBCSrr, ARM::t2SBCrr},
> - {ARM::t2SBCSrs, ARM::t2SBCrs},
> - {ARM::t2RSBSri, ARM::t2RSBri},
> - {ARM::t2RSBSrs, ARM::t2RSBrs},
> -};
> -
> -// Convert and Add or Subtract with Carry and Flags to a generic opcode with
> -// CPSR<def> operand. e.g. ADCS (...) -> ADC (... CPSR<def>).
> -//
> -// FIXME: Somewhere we should assert that CPSR<def> is in the correct
> -// position to be recognized by the target descrition as the 'S' bit.
> -bool ARMTargetLowering::RemapAddSubWithFlags(MachineInstr *MI,
> - MachineBasicBlock *BB) const {
> - unsigned OldOpc = MI->getOpcode();
> - unsigned NewOpc = 0;
> -
> - // This is only called for instructions that need remapping, so iterating over
> - // the tiny opcode table is not costly.
> - static const int NPairs =
> - sizeof(AddSubFlagsOpcodeMap) / sizeof(AddSubFlagsOpcodePair);
> - for (const AddSubFlagsOpcodePair *Pair = &AddSubFlagsOpcodeMap[0],
> - *End = &AddSubFlagsOpcodeMap[NPairs]; Pair != End; ++Pair) {
> - if (OldOpc == Pair->PseudoOpc) {
> - NewOpc = Pair->MachineOpc;
> - break;
> - }
> - }
> - if (!NewOpc)
> - return false;
> -
> - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
> - DebugLoc dl = MI->getDebugLoc();
> - MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc));
> - for (unsigned i = 0; i < MI->getNumOperands(); ++i)
> - MIB.addOperand(MI->getOperand(i));
> - AddDefaultPred(MIB);
> - MIB.addReg(ARM::CPSR, RegState::Define); // S bit
> - MI->eraseFromParent();
> - return true;
> -}
> -
> MachineBasicBlock *
> ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
> MachineBasicBlock *BB) const {
> @@ -5286,9 +5254,6 @@
> bool isThumb2 = Subtarget->isThumb2();
> switch (MI->getOpcode()) {
> default: {
> - if (RemapAddSubWithFlags(MI, BB))
> - return BB;
> -
> MI->dump();
> llvm_unreachable("Unexpected instr type to insert");
> }
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Mon Aug 29 20:34:54 2011
> @@ -71,6 +71,11 @@
> SRA_FLAG, // V,Flag = sra_flag X -> sra X, 1 + save carry out.
> RRX, // V = RRX X, Flag -> srl X, 1 + shift in carry flag.
>
> + ADDC, // Add with carry
> + ADDE, // Add using carry
> + SUBC, // Sub with carry
> + SUBE, // Sub using carry
> +
> VMOVRRD, // double to two gprs.
> VMOVDRR, // Two gprs to double.
>
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Aug 29 20:34:54 2011
> @@ -70,6 +70,18 @@
> def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
> SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
>
> +def SDTBinaryArithWithFlags : SDTypeProfile<2, 2,
> + [SDTCisSameAs<0, 2>,
> + SDTCisSameAs<0, 3>,
> + SDTCisInt<0>, SDTCisVT<1, i32>]>;
> +
> +// SDTBinaryArithWithFlagsInOut - RES1, CPSR = op LHS, RHS, CPSR
> +def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3,
> + [SDTCisSameAs<0, 2>,
> + SDTCisSameAs<0, 3>,
> + SDTCisInt<0>,
> + SDTCisVT<1, i32>,
> + SDTCisVT<4, i32>]>;
> // Node definitions.
> def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>;
> def ARMWrapperDYN : SDNode<"ARMISD::WrapperDYN", SDTIntUnaryOp>;
> @@ -120,6 +132,12 @@
> def ARMsra_flag : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>;
> def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInGlue ]>;
>
> +def ARMaddc : SDNode<"ARMISD::ADDC", SDTBinaryArithWithFlags,
> + [SDNPCommutative]>;
> +def ARMsubc : SDNode<"ARMISD::SUBC", SDTBinaryArithWithFlags>;
> +def ARMadde : SDNode<"ARMISD::ADDE", SDTBinaryArithWithFlagsInOut>;
> +def ARMsube : SDNode<"ARMISD::SUBE", SDTBinaryArithWithFlagsInOut>;
> +
> def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>;
> def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP",
> SDT_ARMEH_SJLJ_Setjmp, [SDNPHasChain]>;
> @@ -263,24 +281,11 @@
> let ParserMatchClass = Imm0_65535AsmOperand;
> }
>
> +class BinOpWithFlagFrag<dag res> :
> + PatFrag<(ops node:$LHS, node:$RHS, node:$FLAG), res>;
> class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
> class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
>
> -/// adde and sube predicates - True based on whether the carry flag output
> -/// will be needed or not.
> -def adde_dead_carry :
> - PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS),
> - [{return !N->hasAnyUseOfValue(1);}]>;
> -def sube_dead_carry :
> - PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS),
> - [{return !N->hasAnyUseOfValue(1);}]>;
> -def adde_live_carry :
> - PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS),
> - [{return N->hasAnyUseOfValue(1);}]>;
> -def sube_live_carry :
> - PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS),
> - [{return N->hasAnyUseOfValue(1);}]>;
> -
> // An 'and' node with a single use.
> def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{
> return N->hasOneUse();
> @@ -939,6 +944,161 @@
>
> }
>
> +/// AsI1_rbin_irs - Same as AsI1_bin_irs except the order of operands are
> +/// reversed. The 'rr' form is only defined for the disassembler; for codegen
> +/// it is equivalent to the AsI1_bin_irs counterpart.
> +multiclass AsI1_rbin_irs<bits<4> opcod, string opc,
> + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
> + PatFrag opnode, string baseOpc, bit Commutable = 0> {
> + // The register-immediate version is re-materializable. This is useful
> + // in particular for taking the address of a local.
> + let isReMaterializable = 1 in {
> + def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
> + iii, opc, "\t$Rd, $Rn, $imm",
> + [(set GPR:$Rd, (opnode so_imm:$imm, GPR:$Rn))]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> imm;
> + let Inst{25} = 1;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-0} = imm;
> + }
> + }
> + def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
> + iir, opc, "\t$Rd, $Rn, $Rm",
> + [/* pattern left blank */]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<4> Rm;
> + let Inst{11-4} = 0b00000000;
> + let Inst{25} = 0;
> + let Inst{3-0} = Rm;
> + let Inst{15-12} = Rd;
> + let Inst{19-16} = Rn;
> + }
> +
> + def rsi : AsI1<opcod, (outs GPR:$Rd),
> + (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
> + iis, opc, "\t$Rd, $Rn, $shift",
> + [(set GPR:$Rd, (opnode so_reg_imm:$shift, GPR:$Rn))]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> shift;
> + let Inst{25} = 0;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-5} = shift{11-5};
> + let Inst{4} = 0;
> + let Inst{3-0} = shift{3-0};
> + }
> +
> + def rsr : AsI1<opcod, (outs GPR:$Rd),
> + (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
> + iis, opc, "\t$Rd, $Rn, $shift",
> + [(set GPR:$Rd, (opnode so_reg_reg:$shift, GPR:$Rn))]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> shift;
> + let Inst{25} = 0;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-8} = shift{11-8};
> + let Inst{7} = 0;
> + let Inst{6-5} = shift{6-5};
> + let Inst{4} = 1;
> + let Inst{3-0} = shift{3-0};
> + }
> +
> + // Assembly aliases for optional destination operand when it's the same
> + // as the source operand.
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
> + (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn,
> + so_imm:$imm, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"),
> + (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn,
> + GPR:$Rm, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
> + (!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
> + so_reg_imm:$shift, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
> + (!cast<Instruction>(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn,
> + so_reg_reg:$shift, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> +
> +}
> +
> +/// AsI1_rbin_s_is - Same as AsI1_rbin_s_is except sets 's' bit.
> +let isCodeGenOnly = 1, Defs = [CPSR] in {
> +multiclass AsI1_rbin_s_is<bits<4> opcod, string opc,
> + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
> + PatFrag opnode, bit Commutable = 0> {
> + def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
> + iii, opc, "\t$Rd, $Rn, $imm",
> + [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn))]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> imm;
> + let Inst{25} = 1;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-0} = imm;
> + }
> +
> + def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
> + iir, opc, "\t$Rd, $Rn, $Rm",
> + [/* pattern left blank */]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<4> Rm;
> + let Inst{11-4} = 0b00000000;
> + let Inst{25} = 0;
> + let Inst{3-0} = Rm;
> + let Inst{15-12} = Rd;
> + let Inst{19-16} = Rn;
> + }
> +
> + def rsi : AsI1<opcod, (outs GPR:$Rd),
> + (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
> + iis, opc, "\t$Rd, $Rn, $shift",
> + [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift, GPR:$Rn))]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> shift;
> + let Inst{25} = 0;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-5} = shift{11-5};
> + let Inst{4} = 0;
> + let Inst{3-0} = shift{3-0};
> + }
> +
> + def rsr : AsI1<opcod, (outs GPR:$Rd),
> + (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
> + iis, opc, "\t$Rd, $Rn, $shift",
> + [(set GPR:$Rd, CPSR, (opnode so_reg_reg:$shift, GPR:$Rn))]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> shift;
> + let Inst{25} = 0;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-8} = shift{11-8};
> + let Inst{7} = 0;
> + let Inst{6-5} = shift{6-5};
> + let Inst{4} = 1;
> + let Inst{3-0} = shift{3-0};
> + }
> +}
> +}
> +
> /// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the
> /// instruction modifies the CPSR register.
> let isCodeGenOnly = 1, Defs = [CPSR] in {
> @@ -947,7 +1107,7 @@
> PatFrag opnode, bit Commutable = 0> {
> def ri : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
> iii, opc, "\t$Rd, $Rn, $imm",
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]> {
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm))]> {
> bits<4> Rd;
> bits<4> Rn;
> bits<12> imm;
> @@ -959,7 +1119,7 @@
> }
> def rr : AI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
> iir, opc, "\t$Rd, $Rn, $Rm",
> - [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm))]> {
> bits<4> Rd;
> bits<4> Rn;
> bits<4> Rm;
> @@ -974,7 +1134,7 @@
> def rsi : AI1<opcod, (outs GPR:$Rd),
> (ins GPR:$Rn, so_reg_imm:$shift), DPSoRegImmFrm,
> iis, opc, "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]> {
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_imm:$shift))]> {
> bits<4> Rd;
> bits<4> Rn;
> bits<12> shift;
> @@ -987,10 +1147,10 @@
> let Inst{3-0} = shift{3-0};
> }
>
> - def rsr : AI1<opcod, (outs GPR:$Rd),
> + def rsr : AI1<opcod, (outs GPR:$Rd),
> (ins GPR:$Rn, so_reg_reg:$shift), DPSoRegRegFrm,
> iis, opc, "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]> {
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_reg:$shift))]> {
> bits<4> Rd;
> bits<4> Rn;
> bits<12> shift;
> @@ -1130,10 +1290,10 @@
> /// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
> multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
> string baseOpc, bit Commutable = 0> {
> - let Uses = [CPSR] in {
> + let Defs = [CPSR], Uses = [CPSR] in {
> def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
> DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>,
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_imm:$imm, CPSR))]>,
> Requires<[IsARM]> {
> bits<4> Rd;
> bits<4> Rn;
> @@ -1145,7 +1305,7 @@
> }
> def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
> DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
> - [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>,
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, GPR:$Rm, CPSR))]>,
> Requires<[IsARM]> {
> bits<4> Rd;
> bits<4> Rn;
> @@ -1160,7 +1320,7 @@
> def rsi : AsI1<opcod, (outs GPR:$Rd),
> (ins GPR:$Rn, so_reg_imm:$shift),
> DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]>,
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_imm:$shift, CPSR))]>,
> Requires<[IsARM]> {
> bits<4> Rd;
> bits<4> Rn;
> @@ -1175,7 +1335,7 @@
> def rsr : AsI1<opcod, (outs GPR:$Rd),
> (ins GPR:$Rn, so_reg_reg:$shift),
> DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]>,
> + [(set GPR:$Rd, CPSR, (opnode GPR:$Rn, so_reg_reg:$shift, CPSR))]>,
> Requires<[IsARM]> {
> bits<4> Rd;
> bits<4> Rn;
> @@ -1190,6 +1350,7 @@
> let Inst{3-0} = shift{3-0};
> }
> }
> +
> // Assembly aliases for optional destination operand when it's the same
> // as the source operand.
> def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
> @@ -1214,25 +1375,88 @@
> Requires<[IsARM]>;
> }
>
> -// Carry setting variants
> -// NOTE: CPSR def omitted because it will be handled by the custom inserter.
> -let usesCustomInserter = 1 in {
> -multiclass AI1_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
> - def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
> - 4, IIC_iALUi,
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>;
> - def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
> - 4, IIC_iALUr,
> - [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> {
> - let isCommutable = Commutable;
> +/// AI1_rsc_irs - Define instructions and patterns for rsc
> +multiclass AI1_rsc_irs<bits<4> opcod, string opc, PatFrag opnode,
> + string baseOpc> {
> + let Defs = [CPSR], Uses = [CPSR] in {
> + def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
> + DPFrm, IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
> + [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn, CPSR))]>,
> + Requires<[IsARM]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> imm;
> + let Inst{25} = 1;
> + let Inst{15-12} = Rd;
> + let Inst{19-16} = Rn;
> + let Inst{11-0} = imm;
> }
> - def rsi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
> - 4, IIC_iALUsr,
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_imm:$shift))]>;
> - def rsr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
> - 4, IIC_iALUsr,
> - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]>;
> -}
> + def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
> + DPFrm, IIC_iALUr, opc, "\t$Rd, $Rn, $Rm",
> + [/* pattern left blank */]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<4> Rm;
> + let Inst{11-4} = 0b00000000;
> + let Inst{25} = 0;
> + let Inst{3-0} = Rm;
> + let Inst{15-12} = Rd;
> + let Inst{19-16} = Rn;
> + }
> + def rsi : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
> + DPSoRegImmFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
> + [(set GPR:$Rd, CPSR, (opnode so_reg_imm:$shift, GPR:$Rn, CPSR))]>,
> + Requires<[IsARM]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> shift;
> + let Inst{25} = 0;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-5} = shift{11-5};
> + let Inst{4} = 0;
> + let Inst{3-0} = shift{3-0};
> + }
> + def rsr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
> + DPSoRegRegFrm, IIC_iALUsr, opc, "\t$Rd, $Rn, $shift",
> + [(set GPR:$Rd, CPSR, (opnode so_reg_reg:$shift, GPR:$Rn, CPSR))]>,
> + Requires<[IsARM]> {
> + bits<4> Rd;
> + bits<4> Rn;
> + bits<12> shift;
> + let Inst{25} = 0;
> + let Inst{19-16} = Rn;
> + let Inst{15-12} = Rd;
> + let Inst{11-8} = shift{11-8};
> + let Inst{7} = 0;
> + let Inst{6-5} = shift{6-5};
> + let Inst{4} = 1;
> + let Inst{3-0} = shift{3-0};
> + }
> + }
> +
> + // Assembly aliases for optional destination operand when it's the same
> + // as the source operand.
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $imm"),
> + (!cast<Instruction>(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn,
> + so_imm:$imm, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $Rm"),
> + (!cast<Instruction>(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn,
> + GPR:$Rm, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
> + (!cast<Instruction>(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn,
> + so_reg_imm:$shift, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> + def : InstAlias<!strconcat(opc, "${s}${p} $Rdn, $shift"),
> + (!cast<Instruction>(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn,
> + so_reg_reg:$shift, pred:$p,
> + cc_out:$s)>,
> + Requires<[IsARM]>;
> }
>
> let canFoldAsLoad = 1, isReMaterializable = 1 in {
> @@ -2882,182 +3106,44 @@
> // ADD and SUB with 's' bit set.
> defm ADDS : AI1_bin_s_irs<0b0100, "adds",
> IIC_iALUi, IIC_iALUr, IIC_iALUsr,
> - BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
> + BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>;
> defm SUBS : AI1_bin_s_irs<0b0010, "subs",
> IIC_iALUi, IIC_iALUr, IIC_iALUsr,
> - BinOpFrag<(subc node:$LHS, node:$RHS)>>;
> + BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
>
> defm ADC : AI1_adde_sube_irs<0b0101, "adc",
> - BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>,
> + BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>,
> "ADC", 1>;
> defm SBC : AI1_adde_sube_irs<0b0110, "sbc",
> - BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>,
> + BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>,
> "SBC">;
>
> -// ADC and SUBC with 's' bit set.
> -let usesCustomInserter = 1 in {
> -defm ADCS : AI1_adde_sube_s_irs<
> - BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>;
> -defm SBCS : AI1_adde_sube_s_irs<
> - BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>;
> -}
> -
> -def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
> - IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm",
> - [(set GPR:$Rd, (sub so_imm:$imm, GPR:$Rn))]> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<12> imm;
> - let Inst{25} = 1;
> - let Inst{15-12} = Rd;
> - let Inst{19-16} = Rn;
> - let Inst{11-0} = imm;
> -}
> -
> -def RSBrr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
> - IIC_iALUr, "rsb", "\t$Rd, $Rn, $Rm", []> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<4> Rm;
> - let Inst{11-4} = 0b00000000;
> - let Inst{25} = 0;
> - let Inst{3-0} = Rm;
> - let Inst{15-12} = Rd;
> - let Inst{19-16} = Rn;
> -}
> -
> -def RSBrsi : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
> - DPSoRegImmFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (sub so_reg_imm:$shift, GPR:$Rn))]> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<12> shift;
> - let Inst{25} = 0;
> - let Inst{19-16} = Rn;
> - let Inst{15-12} = Rd;
> - let Inst{11-5} = shift{11-5};
> - let Inst{4} = 0;
> - let Inst{3-0} = shift{3-0};
> -}
> -
> -def RSBrsr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
> - DPSoRegRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (sub so_reg_reg:$shift, GPR:$Rn))]> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<12> shift;
> - let Inst{25} = 0;
> - let Inst{19-16} = Rn;
> - let Inst{15-12} = Rd;
> - let Inst{11-8} = shift{11-8};
> - let Inst{7} = 0;
> - let Inst{6-5} = shift{6-5};
> - let Inst{4} = 1;
> - let Inst{3-0} = shift{3-0};
> -}
> -
> -// RSB with 's' bit set.
> -// NOTE: CPSR def omitted because it will be handled by the custom inserter.
> -let usesCustomInserter = 1 in {
> -def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
> - 4, IIC_iALUi,
> - [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]>;
> -def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
> - 4, IIC_iALUr, []>;
> -def RSBSrsi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
> - 4, IIC_iALUsr,
> - [(set GPR:$Rd, (subc so_reg_imm:$shift, GPR:$Rn))]>;
> -def RSBSrsr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
> - 4, IIC_iALUsr,
> - [(set GPR:$Rd, (subc so_reg_reg:$shift, GPR:$Rn))]>;
> -}
> -
> -let Uses = [CPSR] in {
> -def RSCri : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
> - DPFrm, IIC_iALUi, "rsc", "\t$Rd, $Rn, $imm",
> - [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>,
> - Requires<[IsARM]> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<12> imm;
> - let Inst{25} = 1;
> - let Inst{15-12} = Rd;
> - let Inst{19-16} = Rn;
> - let Inst{11-0} = imm;
> -}
> -def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
> - DPFrm, IIC_iALUr, "rsc", "\t$Rd, $Rn, $Rm", []> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<4> Rm;
> - let Inst{11-4} = 0b00000000;
> - let Inst{25} = 0;
> - let Inst{3-0} = Rm;
> - let Inst{15-12} = Rd;
> - let Inst{19-16} = Rn;
> -}
> -def RSCrsi : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
> - DPSoRegImmFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (sube_dead_carry so_reg_imm:$shift, GPR:$Rn))]>,
> - Requires<[IsARM]> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<12> shift;
> - let Inst{25} = 0;
> - let Inst{19-16} = Rn;
> - let Inst{15-12} = Rd;
> - let Inst{11-5} = shift{11-5};
> - let Inst{4} = 0;
> - let Inst{3-0} = shift{3-0};
> -}
> -def RSCrsr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
> - DPSoRegRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift",
> - [(set GPR:$Rd, (sube_dead_carry so_reg_reg:$shift, GPR:$Rn))]>,
> - Requires<[IsARM]> {
> - bits<4> Rd;
> - bits<4> Rn;
> - bits<12> shift;
> - let Inst{25} = 0;
> - let Inst{19-16} = Rn;
> - let Inst{15-12} = Rd;
> - let Inst{11-8} = shift{11-8};
> - let Inst{7} = 0;
> - let Inst{6-5} = shift{6-5};
> - let Inst{4} = 1;
> - let Inst{3-0} = shift{3-0};
> -}
> -}
> -
> +defm RSB : AsI1_rbin_irs <0b0011, "rsb",
> + IIC_iALUi, IIC_iALUr, IIC_iALUsr,
> + BinOpFrag<(sub node:$LHS, node:$RHS)>, "RSB">;
> +defm RSBS : AsI1_rbin_s_is<0b0011, "rsb",
> + IIC_iALUi, IIC_iALUr, IIC_iALUsr,
> + BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
>
> -// NOTE: CPSR def omitted because it will be handled by the custom inserter.
> -let usesCustomInserter = 1, Uses = [CPSR] in {
> -def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
> - 4, IIC_iALUi,
> - [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>;
> -def RSCSrsi : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_imm:$shift),
> - 4, IIC_iALUsr,
> - [(set GPR:$Rd, (sube_dead_carry so_reg_imm:$shift, GPR:$Rn))]>;
> -def RSCSrsr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg_reg:$shift),
> - 4, IIC_iALUsr,
> - [(set GPR:$Rd, (sube_dead_carry so_reg_reg:$shift, GPR:$Rn))]>;
> -}
> +defm RSC : AI1_rsc_irs<0b0111, "rsc",
> + BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>,
> + "RSC">;
>
> // (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
> // The assume-no-carry-in form uses the negation of the input since add/sub
> // assume opposite meanings of the carry flag (i.e., carry == !borrow).
> // See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
> // details.
> -def : ARMPat<(add GPR:$src, so_imm_neg:$imm),
> - (SUBri GPR:$src, so_imm_neg:$imm)>;
> -def : ARMPat<(addc GPR:$src, so_imm_neg:$imm),
> - (SUBSri GPR:$src, so_imm_neg:$imm)>;
> +def : ARMPat<(add GPR:$src, so_imm_neg:$imm),
> + (SUBri GPR:$src, so_imm_neg:$imm)>;
> +def : ARMPat<(ARMaddc GPR:$src, so_imm_neg:$imm),
> + (SUBSri GPR:$src, so_imm_neg:$imm)>;
> +
> // The with-carry-in form matches bitwise not instead of the negation.
> // Effectively, the inverse interpretation of the carry flag already accounts
> // for part of the negation.
> -def : ARMPat<(adde_dead_carry GPR:$src, so_imm_not:$imm),
> - (SBCri GPR:$src, so_imm_not:$imm)>;
> -def : ARMPat<(adde_live_carry GPR:$src, so_imm_not:$imm),
> - (SBCSri GPR:$src, so_imm_not:$imm)>;
> +def : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR),
> + (SBCri GPR:$src, so_imm_not:$imm)>;
>
> // Note: These are implemented in C++ code, because they have to generate
> // ADD/SUBrs instructions, which use a complex pattern that a xform function
> @@ -4803,29 +4889,6 @@
> def : ARMInstAlias<"push${p} $regs", (STMDB_UPD SP, pred:$p, reglist:$regs)>;
> def : ARMInstAlias<"pop${p} $regs", (LDMIA_UPD SP, pred:$p, reglist:$regs)>;
>
> -// RSB two-operand forms (optional explicit destination operand)
> -def : ARMInstAlias<"rsb${s}${p} $Rdn, $imm",
> - (RSBri GPR:$Rdn, GPR:$Rdn, so_imm:$imm, pred:$p, cc_out:$s)>;
> -def : ARMInstAlias<"rsb${s}${p} $Rdn, $Rm",
> - (RSBrr GPR:$Rdn, GPR:$Rdn, GPR:$Rm, pred:$p, cc_out:$s)>;
> -def : ARMInstAlias<"rsb${s}${p} $Rdn, $shift",
> - (RSBrsi GPR:$Rdn, GPR:$Rdn, so_reg_imm:$shift, pred:$p,
> - cc_out:$s)>;
> -def : ARMInstAlias<"rsb${s}${p} $Rdn, $shift",
> - (RSBrsr GPR:$Rdn, GPR:$Rdn, so_reg_reg:$shift, pred:$p,
> - cc_out:$s)>;
> -// RSC two-operand forms (optional explicit destination operand)
> -def : ARMInstAlias<"rsc${s}${p} $Rdn, $imm",
> - (RSCri GPR:$Rdn, GPR:$Rdn, so_imm:$imm, pred:$p, cc_out:$s)>;
> -def : ARMInstAlias<"rsc${s}${p} $Rdn, $Rm",
> - (RSCrr GPR:$Rdn, GPR:$Rdn, GPR:$Rm, pred:$p, cc_out:$s)>;
> -def : ARMInstAlias<"rsc${s}${p} $Rdn, $shift",
> - (RSCrsi GPR:$Rdn, GPR:$Rdn, so_reg_imm:$shift, pred:$p,
> - cc_out:$s)>;
> -def : ARMInstAlias<"rsc${s}${p} $Rdn, $shift",
> - (RSCrsr GPR:$Rdn, GPR:$Rdn, so_reg_reg:$shift, pred:$p,
> - cc_out:$s)>;
> -
> // SSAT/USAT optional shift operand.
> def : ARMInstAlias<"ssat${p} $Rd, $sat_imm, $Rn",
> (SSAT GPRnopc:$Rd, imm1_32:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>;
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Aug 29 20:34:54 2011
> @@ -582,7 +582,7 @@
> def ri : T2TwoRegImm<
> (outs rGPR:$Rd), (ins GPR:$Rn, t2_so_imm:$imm), iii,
> !strconcat(opc, "s"), ".w\t$Rd, $Rn, $imm",
> - [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_imm:$imm))]> {
> + [(set rGPR:$Rd, CPSR, (opnode GPR:$Rn, t2_so_imm:$imm))]> {
> let Inst{31-27} = 0b11110;
> let Inst{25} = 0;
> let Inst{24-21} = opcod;
> @@ -593,7 +593,7 @@
> def rr : T2ThreeReg<
> (outs rGPR:$Rd), (ins GPR:$Rn, rGPR:$Rm), iir,
> !strconcat(opc, "s"), ".w\t$Rd, $Rn, $Rm",
> - [(set rGPR:$Rd, (opnode GPR:$Rn, rGPR:$Rm))]> {
> + [(set rGPR:$Rd, CPSR, (opnode GPR:$Rn, rGPR:$Rm))]> {
> let isCommutable = Commutable;
> let Inst{31-27} = 0b11101;
> let Inst{26-25} = 0b01;
> @@ -607,7 +607,7 @@
> def rs : T2TwoRegShiftedReg<
> (outs rGPR:$Rd), (ins GPR:$Rn, t2_so_reg:$ShiftedRm), iis,
> !strconcat(opc, "s"), ".w\t$Rd, $Rn, $ShiftedRm",
> - [(set rGPR:$Rd, (opnode GPR:$Rn, t2_so_reg:$ShiftedRm))]> {
> + [(set rGPR:$Rd, CPSR, (opnode GPR:$Rn, t2_so_reg:$ShiftedRm))]> {
> let Inst{31-27} = 0b11101;
> let Inst{26-25} = 0b01;
> let Inst{24-21} = opcod;
> @@ -682,13 +682,13 @@
> /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns
> /// for a binary operation that produces a value and use the carry
> /// bit. It's not predicable.
> -let Uses = [CPSR] in {
> +let Defs = [CPSR], Uses = [CPSR] in {
> multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
> bit Commutable = 0> {
> // shifted imm
> def ri : T2sTwoRegImm<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
> IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
> - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
> + [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, t2_so_imm:$imm, CPSR))]>,
> Requires<[IsThumb2]> {
> let Inst{31-27} = 0b11110;
> let Inst{25} = 0;
> @@ -698,7 +698,7 @@
> // register
> def rr : T2sThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
> opc, ".w\t$Rd, $Rn, $Rm",
> - [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
> + [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, rGPR:$Rm, CPSR))]>,
> Requires<[IsThumb2]> {
> let isCommutable = Commutable;
> let Inst{31-27} = 0b11101;
> @@ -712,7 +712,7 @@
> def rs : T2sTwoRegShiftedReg<
> (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
> IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
> - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
> + [(set rGPR:$Rd, CPSR, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm, CPSR))]>,
> Requires<[IsThumb2]> {
> let Inst{31-27} = 0b11101;
> let Inst{26-25} = 0b01;
> @@ -721,28 +721,6 @@
> }
> }
>
> -// Carry setting variants
> -// NOTE: CPSR def omitted because it will be handled by the custom inserter.
> -let usesCustomInserter = 1 in {
> -multiclass T2I_adde_sube_s_irs<PatFrag opnode, bit Commutable = 0> {
> - // shifted imm
> - def ri : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
> - 4, IIC_iALUi,
> - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>;
> - // register
> - def rr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm),
> - 4, IIC_iALUr,
> - [(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]> {
> - let isCommutable = Commutable;
> - }
> - // shifted register
> - def rs : t2PseudoInst<
> - (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
> - 4, IIC_iALUsi,
> - [(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>;
> -}
> -}
> -
> /// T2I_rbin_s_is - Same as T2I_rbin_irs except sets 's' bit and the register
> /// version is not needed since this is only for codegen.
> let isCodeGenOnly = 1, Defs = [CPSR] in {
> @@ -751,7 +729,7 @@
> def ri : T2TwoRegImm<
> (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi,
> !strconcat(opc, "s"), ".w\t$Rd, $Rn, $imm",
> - [(set rGPR:$Rd, (opnode t2_so_imm:$imm, rGPR:$Rn))]> {
> + [(set rGPR:$Rd, CPSR, (opnode t2_so_imm:$imm, rGPR:$Rn))]> {
> let Inst{31-27} = 0b11110;
> let Inst{25} = 0;
> let Inst{24-21} = opcod;
> @@ -762,7 +740,7 @@
> def rs : T2TwoRegShiftedReg<
> (outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
> IIC_iALUsi, !strconcat(opc, "s"), "\t$Rd, $Rn, $ShiftedRm",
> - [(set rGPR:$Rd, (opnode t2_so_reg:$ShiftedRm, rGPR:$Rn))]> {
> + [(set rGPR:$Rd, CPSR, (opnode t2_so_reg:$ShiftedRm, rGPR:$Rn))]> {
> let Inst{31-27} = 0b11101;
> let Inst{26-25} = 0b01;
> let Inst{24-21} = opcod;
> @@ -1678,25 +1656,21 @@
> // ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants.
> defm t2ADDS : T2I_bin_s_irs <0b1000, "add",
> IIC_iALUi, IIC_iALUr, IIC_iALUsi,
> - BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
> + BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>;
> defm t2SUBS : T2I_bin_s_irs <0b1101, "sub",
> IIC_iALUi, IIC_iALUr, IIC_iALUsi,
> - BinOpFrag<(subc node:$LHS, node:$RHS)>>;
> + BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
>
> defm t2ADC : T2I_adde_sube_irs<0b1010, "adc",
> - BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>;
> + BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, 1>;
> defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc",
> - BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>;
> -defm t2ADCS : T2I_adde_sube_s_irs<BinOpFrag<(adde_live_carry node:$LHS,
> - node:$RHS)>, 1>;
> -defm t2SBCS : T2I_adde_sube_s_irs<BinOpFrag<(sube_live_carry node:$LHS,
> - node:$RHS)>>;
> + BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>>;
>
> // RSB
> defm t2RSB : T2I_rbin_irs <0b1110, "rsb",
> BinOpFrag<(sub node:$LHS, node:$RHS)>>;
> defm t2RSBS : T2I_rbin_s_is <0b1110, "rsb",
> - BinOpFrag<(subc node:$LHS, node:$RHS)>>;
> + BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>;
>
> // (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
> // The assume-no-carry-in form uses the negation of the input since add/sub
> @@ -1713,23 +1687,18 @@
> def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
> (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
> let AddedComplexity = 1 in
> -def : T2Pat<(addc rGPR:$src, imm0_255_neg:$imm),
> +def : T2Pat<(ARMaddc rGPR:$src, imm0_255_neg:$imm),
> (t2SUBSri rGPR:$src, imm0_255_neg:$imm)>;
> -def : T2Pat<(addc rGPR:$src, t2_so_imm_neg:$imm),
> +def : T2Pat<(ARMaddc rGPR:$src, t2_so_imm_neg:$imm),
> (t2SUBSri rGPR:$src, t2_so_imm_neg:$imm)>;
> // The with-carry-in form matches bitwise not instead of the negation.
> // Effectively, the inverse interpretation of the carry flag already accounts
> // for part of the negation.
> let AddedComplexity = 1 in
> -def : T2Pat<(adde_dead_carry rGPR:$src, imm0_255_not:$imm),
> +def : T2Pat<(ARMadde rGPR:$src, imm0_255_not:$imm, CPSR),
> (t2SBCri rGPR:$src, imm0_255_not:$imm)>;
> -def : T2Pat<(adde_dead_carry rGPR:$src, t2_so_imm_not:$imm),
> +def : T2Pat<(ARMadde rGPR:$src, t2_so_imm_not:$imm, CPSR),
> (t2SBCri rGPR:$src, t2_so_imm_not:$imm)>;
> -let AddedComplexity = 1 in
> -def : T2Pat<(adde_live_carry rGPR:$src, imm0_255_not:$imm),
> - (t2SBCSri rGPR:$src, imm0_255_not:$imm)>;
> -def : T2Pat<(adde_live_carry rGPR:$src, t2_so_imm_not:$imm),
> - (t2SBCSri rGPR:$src, t2_so_imm_not:$imm)>;
>
> // Select Bytes -- for disassembly only
>
>
> Modified: llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td Mon Aug 29 20:34:54 2011
> @@ -347,5 +347,6 @@
>
> // Condition code registers.
> def CCR : RegisterClass<"ARM", [i32], 32, (add CPSR)> {
> + let CopyCost = -1; // Don't allow copying of status registers.
> let isAllocatable = 0;
> }
>
> Added: llvm/trunk/test/CodeGen/ARM/2011-08-29-SchedCycle.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-08-29-SchedCycle.ll?rev=138791&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/2011-08-29-SchedCycle.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/2011-08-29-SchedCycle.ll Mon Aug 29 20:34:54 2011
> @@ -0,0 +1,45 @@
> +; RUN: llc %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 -o -
> +
> +; When a i64 sub is expanded to subc + sube.
> +; libcall #1
> +; \
> +; \ subc
> +; \ / \
> +; \ / \
> +; \ / libcall #2
> +; sube
> +;
> +; If the libcalls are not serialized (i.e. both have chains which are dag
> +; entry), legalizer can serialize them in arbitrary orders. If it's
> +; unlucky, it can force libcall #2 before libcall #1 in the above case.
> +;
> +; subc
> +; |
> +; libcall #2
> +; |
> +; libcall #1
> +; |
> +; sube
> +;
> +; However since subc and sube are "glued" together, this ends up being a
> +; cycle when the scheduler combine subc and sube as a single scheduling
> +; unit.
> +;
> +; The right solution is to fix LegalizeType too chains the libcalls together.
> +; However, LegalizeType is not processing nodes in order. The fix now is to
> +; fix subc / sube (and addc / adde) to use physical register dependency instead.
> +; rdar://10019576
> +
> +define void @t() nounwind {
> +entry:
> + %tmp = load i64* undef, align 4
> + %tmp5 = udiv i64 %tmp, 30
> + %tmp13 = and i64 %tmp5, 64739244643450880
> + %tmp16 = sub i64 0, %tmp13
> + %tmp19 = and i64 %tmp16, 63
> + %tmp20 = urem i64 %tmp19, 3
> + %tmp22 = and i64 %tmp16, -272346829004752
> + store i64 %tmp22, i64* undef, align 4
> + store i64 %tmp20, i64* undef, align 4
> + ret void
> +}
>
> Modified: llvm/trunk/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll?rev=138791&r1=138790&r2=138791&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll (original)
> +++ llvm/trunk/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll Mon Aug 29 20:34:54 2011
> @@ -6,8 +6,8 @@
> ; -- The loop following the load should only use a single add-literation
> ; instruction.
> ; CHECK: ldr.64
> -; CHECK: adds r{{[0-9]+}}, #1
> -; CHECK-NOT: adds r{{[0-9]+}}, #1
> +; CHECK: adds r{{[0-9]+}}, r{{[0-9]+}}, #1
> +; CHECK-NOT: adds r{{[0-9]+}}, r{{[0-9]+}}, #1
> ; CHECK: subsections_via_symbols
>
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list