diff options
author | Evan Cheng <evan.cheng@apple.com> | 2007-05-15 01:29:07 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2007-05-15 01:29:07 +0000 |
commit | 44bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4 (patch) | |
tree | 6a1a76ed9f6ef5f903fe0b8571bb7cfe3ab69b1b | |
parent | 709fd414e2e5c3f3f282864a16688409ea152706 (diff) |
Add PredicateOperand to all ARM instructions that have the condition field.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37066 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/ARM/ARMAsmPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantIslandPass.cpp | 12 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 40 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.cpp | 37 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 357 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 14 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrVFP.td | 166 | ||||
-rw-r--r-- | lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 96 | ||||
-rw-r--r-- | lib/Target/ARM/ARMRegisterInfo.cpp | 125 |
9 files changed, 492 insertions, 360 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 0f0a5419dd..c57fbbc019 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -614,8 +614,9 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) { } void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) { - int CC = (int)MI->getOperand(opNum).getImmedValue(); - O << ARMCondCodeToString((ARMCC::CondCodes)CC); + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImmedValue(); + if (CC != ARMCC::AL) + O << ARMCondCodeToString(CC); } void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) { diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 1d76ddcd14..1371cdca46 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -1265,12 +1265,12 @@ bool ARMConstantIslands::UndoLRSpillRestore() { bool MadeChange = false; for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) { MachineInstr *MI = PushPopMIs[i]; - if (MI->getNumOperands() == 1) { - if (MI->getOpcode() == ARM::tPOP_RET && - MI->getOperand(0).getReg() == ARM::PC) - BuildMI(MI->getParent(), TII->get(ARM::tBX_RET)); - MI->eraseFromParent(); - MadeChange = true; + if (MI->getOpcode() == ARM::tPOP_RET && + MI->getOperand(0).getReg() == ARM::PC && + MI->getNumExplicitOperands() == 1) { + BuildMI(MI->getParent(), TII->get(ARM::tBX_RET)); + MI->eraseFromParent(); + MadeChange = true; } } return MadeChange; diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 79d58692e9..5c63921fa9 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -524,6 +524,11 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDOperand Op, return true; } +/// getDefaultPred - Returns a ARMCC::AL immediate node. +static inline SDOperand getDefaultPred(SelectionDAG *CurDAG) { + return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); +} + SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { SDNode *N = Op.Val; @@ -559,9 +564,10 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { CPIdx, CurDAG->getRegister(0, MVT::i32), CurDAG->getTargetConstant(0, MVT::i32), + getDefaultPred(CurDAG), CurDAG->getEntryNode() }; - ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 4); + ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 5); } ReplaceUses(Op, SDOperand(ResNode, 0)); return NULL; @@ -573,10 +579,14 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { case ISD::FrameIndex: { // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. int FI = cast<FrameIndexSDNode>(N)->getIndex(); - unsigned Opc = Subtarget->isThumb() ? ARM::tADDrSPi : ARM::ADDri; SDOperand TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, TFI, - CurDAG->getTargetConstant(0, MVT::i32)); + if (Subtarget->isThumb()) + return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, + CurDAG->getTargetConstant(0, MVT::i32)); + else + return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, TFI, + CurDAG->getTargetConstant(0, MVT::i32), + getDefaultPred(CurDAG)); } case ISD::ADD: { // Select add sp, c to tADDhirr. @@ -606,35 +616,39 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { AddToISelQueue(V); unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1)); SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), - CurDAG->getTargetConstant(ShImm, MVT::i32) + CurDAG->getTargetConstant(ShImm, MVT::i32), + getDefaultPred(CurDAG) }; - return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 4); + return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 5); } if (isPowerOf2_32(RHSV+1)) { // 2^n-1? SDOperand V = Op.getOperand(0); AddToISelQueue(V); unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1)); SDOperand Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), - CurDAG->getTargetConstant(ShImm, MVT::i32) + CurDAG->getTargetConstant(ShImm, MVT::i32), + getDefaultPred(CurDAG) }; - return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 4); + return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 5); } } break; case ARMISD::FMRRD: AddToISelQueue(Op.getOperand(0)); return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32, - Op.getOperand(0)); + Op.getOperand(0), getDefaultPred(CurDAG)); case ARMISD::MULHILOU: AddToISelQueue(Op.getOperand(0)); AddToISelQueue(Op.getOperand(1)); return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32, - Op.getOperand(0), Op.getOperand(1)); + Op.getOperand(0), Op.getOperand(1), + getDefaultPred(CurDAG)); case ARMISD::MULHILOS: AddToISelQueue(Op.getOperand(0)); AddToISelQueue(Op.getOperand(1)); return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32, - Op.getOperand(0), Op.getOperand(1)); + Op.getOperand(0), Op.getOperand(1), + getDefaultPred(CurDAG)); case ISD::LOAD: { LoadSDNode *LD = cast<LoadSDNode>(Op); ISD::MemIndexedMode AM = LD->getAddressingMode(); @@ -674,9 +688,9 @@ SDNode *ARMDAGToDAGISel::Select(SDOperand Op) { AddToISelQueue(Chain); AddToISelQueue(Base); AddToISelQueue(Offset); - SDOperand Ops[] = { Base, Offset, AMOpc, Chain }; + SDOperand Ops[]= { Base, Offset, AMOpc, getDefaultPred(CurDAG), Chain }; return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32, - MVT::Other, Ops, 4); + MVT::Other, Ops, 5); } } // Other cases are autogenerated. diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index de3a7fda4d..3f501a68ae 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -52,7 +52,8 @@ bool ARMInstrInfo::isMoveInstr(const MachineInstr &MI, return true; case ARM::MOVr: case ARM::tMOVr: - assert(MI.getNumOperands() >= 2 && MI.getOperand(0).isRegister() && + assert(MI.getInstrDescriptor()->numOperands >= 2 && + MI.getOperand(0).isRegister() && MI.getOperand(1).isRegister() && "Invalid ARM MOV instruction"); SrcReg = MI.getOperand(1).getReg(); @@ -188,15 +189,17 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, MachineInstr *UpdateMI = NULL; MachineInstr *MemMI = NULL; unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); - unsigned NumOps = MI->getNumOperands(); - bool isLoad = (MI->getInstrDescriptor()->Flags & M_LOAD_FLAG) != 0; + const TargetInstrDescriptor *TID = MI->getInstrDescriptor(); + unsigned NumOps = TID->numOperands; + bool isLoad = (TID->Flags & M_LOAD_FLAG) != 0; const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); const MachineOperand &Base = MI->getOperand(2); - const MachineOperand &Offset = MI->getOperand(NumOps-2); + const MachineOperand &Offset = MI->getOperand(NumOps-3); unsigned WBReg = WB.getReg(); unsigned BaseReg = Base.getReg(); unsigned OffReg = Offset.getReg(); - unsigned OffImm = MI->getOperand(NumOps-1).getImm(); + unsigned OffImm = MI->getOperand(NumOps-2).getImm(); + ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm(); switch (AddrMode) { default: assert(false && "Unknown indexed op!"); @@ -211,15 +214,15 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, // add more than 1 instruction. Abandon! return NULL; UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) - .addReg(BaseReg).addImm(SOImmVal); + .addReg(BaseReg).addImm(SOImmVal).addImm(Pred); } else if (Amt != 0) { ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm); unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt); UpdateMI = BuildMI(get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg) - .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc); + .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc).addImm(Pred); } else UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) - .addReg(BaseReg).addReg(OffReg); + .addReg(BaseReg).addReg(OffReg).addImm(Pred); break; } case ARMII::AddrMode3 : { @@ -228,10 +231,10 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, if (OffReg == 0) // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand. UpdateMI = BuildMI(get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) - .addReg(BaseReg).addImm(Amt); + .addReg(BaseReg).addImm(Amt).addImm(Pred); else UpdateMI = BuildMI(get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) - .addReg(BaseReg).addReg(OffReg); + .addReg(BaseReg).addReg(OffReg).addImm(Pred); break; } } @@ -240,19 +243,19 @@ ARMInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, if (isPre) { if (isLoad) MemMI = BuildMI(get(MemOpc), MI->getOperand(0).getReg()) - .addReg(WBReg).addReg(0).addImm(0); + .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); else MemMI = BuildMI(get(MemOpc)).addReg(MI->getOperand(1).getReg()) - .addReg(WBReg).addReg(0).addImm(0); + .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); NewMIs.push_back(MemMI); NewMIs.push_back(UpdateMI); } else { if (isLoad) MemMI = BuildMI(get(MemOpc), MI->getOperand(0).getReg()) - .addReg(BaseReg).addReg(0).addImm(0); + .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); else MemMI = BuildMI(get(MemOpc)).addReg(MI->getOperand(1).getReg()) - .addReg(BaseReg).addReg(0).addImm(0); + .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); if (WB.isDead()) UpdateMI->getOperand(0).setIsDead(); NewMIs.push_back(UpdateMI); @@ -437,7 +440,8 @@ unsigned ARM::GetInstSize(MachineInstr *MI) { const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo(); // Basic size info comes from the TSFlags field. - unsigned TSFlags = MI->getInstrDescriptor()->TSFlags; + const TargetInstrDescriptor *TID = MI->getInstrDescriptor(); + unsigned TSFlags = TID->TSFlags; switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { default: @@ -463,7 +467,8 @@ unsigned ARM::GetInstSize(MachineInstr *MI) { case ARM::tBR_JTr: { // These are jumptable branches, i.e. a branch followed by an inlined // jumptable. The size is 4 + 4 * number of entries. - unsigned JTI = MI->getOperand(MI->getNumOperands()-2).getJumpTableIndex(); + unsigned NumOps = TID->numOperands; + unsigned JTI = MI->getOperand(NumOps-3).getJumpTableIndex(); MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); assert(JTI < JT.size()); diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 5441212b86..ad2807cc4a 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -340,7 +340,7 @@ class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> { } class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im, - dag ops, string asmstr, string cstr> + string cstr> : Instruction { let Namespace = "ARM"; @@ -354,58 +354,59 @@ class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im, IndexMode IM = im; bits<2> IndexModeBits = IM.Value; - dag OperandList = ops; - let AsmString = asmstr; let Constraints = cstr; } class PseudoInst<dag ops, string asm, list<dag> pattern> - : InstARM<0, AddrModeNone, SizeSpecial, IndexModeNone, ops, asm, ""> { + : InstARM<0, AddrModeNone, SizeSpecial, IndexModeNone, ""> { + let OperandList = ops; + let AsmString = asm; let Pattern = pattern; } -class I<dag ops, AddrMode am, SizeFlagVal sz, IndexMode im, - string asm, string cstr, list<dag> pattern> +// Almost all ARM instructions are predicatable. +class I<dag oprnds, AddrMode am, SizeFlagVal sz, IndexMode im, + string opc, string asm, string cstr, list<dag> pattern> // FIXME: Set all opcodes to 0 for now. - : InstARM<0, am, sz, im, ops, asm, cstr> { + : InstARM<0, am, sz, im, cstr> { + let OperandList = !con(oprnds, (ops pred:$p)); + let AsmString = !strconcat(opc, !strconcat("$p", asm)); let Pattern = pattern; list<Predicate> Predicates = [IsARM]; } -class AI<dag ops, string asm, list<dag> pattern> - : I<ops, AddrModeNone, Size4Bytes, IndexModeNone, asm, "", pattern>; -class AI1<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode1, Size4Bytes, IndexModeNone, asm, "", pattern>; -class AI2<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode2, Size4Bytes, IndexModeNone, asm, "", pattern>; -class AI3<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode3, Size4Bytes, IndexModeNone, asm, "", pattern>; -class AI4<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode4, Size4Bytes, IndexModeNone, asm, "", pattern>; -class AIx2<dag ops, string asm, list<dag> pattern> - : I<ops, AddrModeNone, Size8Bytes, IndexModeNone, asm, "", pattern>; -class AI1x2<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode1, Size8Bytes, IndexModeNone, asm, "", pattern>; +class AI<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrModeNone, Size4Bytes, IndexModeNone, opc, asm, "", pattern>; +class AI1<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode1, Size4Bytes, IndexModeNone, opc, asm, "", pattern>; +class AI2<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode2, Size4Bytes, IndexModeNone, opc, asm, "", pattern>; +class AI3<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode3, Size4Bytes, IndexModeNone, opc, asm, "", pattern>; +class AI4<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode4, Size4Bytes, IndexModeNone, opc, asm, "", pattern>; +class AI1x2<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode1, Size8Bytes, IndexModeNone, opc, asm, "", pattern>; // Pre-indexed ops -class AI2pr<dag ops, string asm, string cstr, list<dag> pattern> - : I<ops, AddrMode2, Size4Bytes, IndexModePre, asm, cstr, pattern>; -class AI3pr<dag ops, string asm, string cstr, list<dag> pattern> - : I<ops, AddrMode3, Size4Bytes, IndexModePre, asm, cstr, pattern>; +class AI2pr<dag ops, string opc, string asm, string cstr, list<dag> pattern> + : I<ops, AddrMode2, Size4Bytes, IndexModePre, opc, asm, cstr, pattern>; +class AI3pr<dag ops, string opc, string asm, string cstr, list<dag> pattern> + : I<ops, AddrMode3, Size4Bytes, IndexModePre, opc, asm, cstr, pattern>; // Post-indexed ops -class AI2po<dag ops, string asm, string cstr, list<dag> pattern> - : I<ops, AddrMode2, Size4Bytes, IndexModePost, asm, cstr, pattern>; -class AI3po<dag ops, string asm, string cstr, list<dag> pattern> - : I<ops, AddrMode3, Size4Bytes, IndexModePost, asm, cstr, pattern>; +class AI2po<dag ops, string opc, string asm, string cstr, list<dag> pattern> + : I<ops, AddrMode2, Size4Bytes, IndexModePost, opc, asm, cstr, pattern>; +class AI3po<dag ops, string opc, string asm, string cstr, list<dag> pattern> + : I<ops, AddrMode3, Size4Bytes, IndexModePost, opc, asm, cstr, pattern>; // BR_JT instructions -class JTI<dag ops, string asm, list<dag> pattern> - : I<ops, AddrModeNone, SizeSpecial, IndexModeNone, asm, "", pattern>; -class JTI1<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode1, SizeSpecial, IndexModeNone, asm, "", pattern>; -class JTI2<dag ops, string asm, list<dag> pattern> - : I<ops, AddrMode2, SizeSpecial, IndexModeNone, asm, "", pattern>; +class JTI<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrModeNone, SizeSpecial, IndexModeNone, opc, asm, "", pattern>; +class JTI1<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode1, SizeSpecial, IndexModeNone, opc, asm, "", pattern>; +class JTI2<dag ops, string opc, string asm, list<dag> pattern> + : I<ops, AddrMode2, SizeSpecial, IndexModeNone, opc, asm, "", pattern>; class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>; @@ -416,13 +417,13 @@ class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>; /// binop that produces a value. multiclass AI1_bin_irs<string opc, PatFrag opnode> { def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b), - !strconcat(opc, " $dst, $a, $b"), + opc, " $dst, $a, $b", [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>; def rr : AI1<(ops GPR:$dst, GPR:$a, GPR:$b), - !strconcat(opc, " $dst, $a, $b"), + opc, " $dst, $a, $b", [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>; def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b), - !strconcat(opc, " $dst, $a, $b"), + opc, " $dst, $a, $b", [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>; } @@ -430,23 +431,23 @@ multiclass AI1_bin_irs<string opc, PatFrag opnode> { /// Similar to AI1_bin_irs except the instruction does not produce a result. multiclass AI1_bin0_irs<string opc, PatFrag opnode> { def ri : AI1<(ops GPR:$a, so_imm:$b), - !strconcat(opc, " $a, $b"), + opc, " $a, $b", [(opnode GPR:$a, so_imm:$b)]>; def rr : AI1<(ops GPR:$a, GPR:$b), - !strconcat(opc, " $a, $b"), + opc, " $a, $b", [(opnode GPR:$a, GPR:$b)]>; def rs : AI1<(ops GPR:$a, so_reg:$b), - !strconcat(opc, " $a, $b"), + opc, " $a, $b", [(opnode GPR:$a, so_reg:$b)]>; } /// AI1_bin_is - Defines a set of (op r, {so_imm|so_reg}) patterns for a binop. multiclass AI1_bin_is<string opc, PatFrag opnode> { def ri : AI1<(ops GPR:$dst, GPR:$a, so_imm:$b), - !strconcat(opc, " $dst, $a, $b"), + opc, " $dst, $a, $b", [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>; def rs : AI1<(ops GPR:$dst, GPR:$a, so_reg:$b), - !strconcat(opc, " $dst, $a, $b"), + opc, " $dst, $a, $b", [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>; } @@ -454,13 +455,13 @@ multiclass AI1_bin_is<string opc, PatFrag opnode> { /// ops. multiclass AI1_unary_irs<string opc, PatFrag opnode> { def i : AI1<(ops GPR:$dst, so_imm:$a), - !strconcat(opc, " $dst, $a"), + opc, " $dst, $a", [(set GPR:$dst, (opnode so_imm:$a))]>; def r : AI1<(ops GPR:$dst, GPR:$a), - !strconcat(opc, " $dst, $a"), + opc, " $dst, $a", [(set GPR:$dst, (opnode GPR:$a))]>; def s : AI1<(ops GPR:$dst, so_reg:$a), - !strconcat(opc, " $dst, $a"), + opc, " $dst, $a", [(set GPR:$dst, (opnode so_reg:$a))]>; } @@ -468,10 +469,10 @@ multiclass AI1_unary_irs<string opc, PatFrag opnode> { /// register and one whose operand is a register rotated by 8/16/24. multiclass AI_unary_rrot<string opc, PatFrag opnode> { def r : AI<(ops GPR:$dst, GPR:$Src), - !strconcat(opc, " $dst, $Src"), + opc, " $dst, $Src", [(set GPR:$dst, (opnode GPR:$Src))]>, Requires<[IsARM, HasV6]>; def r_rot : AI<(ops GPR:$dst, GPR:$Src, i32imm:$rot), - !strconcat(opc, " $dst, $Src, ror $rot"), + opc, " $dst, $Src, ror $rot", [(set GPR:$dst, (opnode (rotr GPR:$Src, rot_imm:$rot)))]>, Requires<[IsARM, HasV6]>; } @@ -480,16 +481,39 @@ multiclass AI_unary_rrot<string opc, PatFrag opnode> { /// register and one whose operand is a register rotated by 8/16/24. multiclass AI_bin_rrot<string opc, PatFrag opnode> { def rr : AI<(ops GPR:$dst, GPR:$LHS, GPR:$RHS), - !strconcat(opc, " $dst, $LHS, $RHS"), + opc, " $dst, $LHS, $RHS", [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>, Requires<[IsARM, HasV6]>; def rr_rot : AI<(ops GPR:$dst, GPR:$LHS, GPR:$RHS, i32imm:$rot), - !strconcat(opc, " $dst, $LHS, $RHS, ror $rot"), + opc, " $dst, $LHS, $RHS, ror $rot", [(set GPR:$dst, (opnode GPR:$LHS, (rotr GPR:$RHS, rot_imm:$rot)))]>, Requires<[IsARM, HasV6]>; } +// Special cases. +class XI<dag oprnds, AddrMode am, SizeFlagVal sz, IndexMode im, + string asm, string cstr, list<dag> pattern> + // FIXME: Set all opcodes to 0 for now. + : InstARM<0, am, sz, im, cstr> { + let OperandList = oprnds; + let AsmString = asm; + let Pattern = pattern; + list<Predicate> Predicates = [IsARM]; +} + +class AXI<dag ops, string asm, list<dag> pattern> + : XI<ops, AddrModeNone, Size4Bytes, IndexModeNone, asm, "", pattern>; +class AXI1<dag ops, string asm, list<dag> pattern> + : XI<ops, AddrMode1, Size4Bytes, IndexModeNone, asm, "", pattern>; +class AXI2<dag ops, string asm, list<dag> pattern> + : XI<ops, AddrMode2, Size4Bytes, IndexModeNone, asm, "", pattern>; +class AXI4<dag ops, string asm, list<dag> pattern> + : XI<ops, AddrMode4, Size4Bytes, IndexModeNone, asm, "", pattern>; + +class AXIx2<dag ops, string asm, list<dag> pattern> + : XI<ops, AddrModeNone, Size8Bytes, IndexModeNone, asm, "", pattern>; + //===----------------------------------------------------------------------===// // Instructions @@ -499,7 +523,7 @@ multiclass AI_bin_rrot<string opc, PatFrag opnode> { // Miscellaneous Instructions. // def IMPLICIT_DEF_GPR : -PseudoInst<(ops GPR:$rD), +PseudoInst<(ops GPR:$rD, pred:$p), "@ IMPLICIT_DEF_GPR $rD", [(set GPR:$rD, (undef))]>; @@ -513,12 +537,12 @@ PseudoInst<(ops cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), "${instid:label} ${cpidx:cpentry}", []>; def ADJCALLSTACKUP : -PseudoInst<(ops i32imm:$amt), +PseudoInst<(ops i32imm:$amt, pred:$p), "@ ADJCALLSTACKUP $amt", [(ARMcallseq_end imm:$amt)]>, Imp<[SP],[SP]>; def ADJCALLSTACKDOWN : -PseudoInst<(ops i32imm:$amt), +PseudoInst<(ops i32imm:$amt, pred:$p), "@ ADJCALLSTACKDOWN $amt", [(ARMcallseq_start imm:$amt)]>, Imp<[SP],[SP]>; @@ -527,12 +551,12 @@ PseudoInst<(ops i32imm:$line, i32imm:$col, i32imm:$file), ".loc $file, $line, $col", [(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>; -def PICADD : AI1<(ops GPR:$dst, GPR:$a, pclabel:$cp), - "$cp:\n\tadd $dst, pc, $a", - [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>; +def PICADD : AXI1<(ops GPR:$dst, GPR:$a, pclabel:$cp, pred:$p), + "$cp:\n\tadd$p $dst, pc, $a", + [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>; let AddedComplexity = 10 in -def PICLD : AI2<(ops GPR:$dst, addrmodepc:$addr), - "${addr:label}:\n\tldr $dst, $addr", +def PICLD : AXI2<(ops GPR:$dst, addrmodepc:$addr, pred:$p), + "${addr:label}:\n\tldr$p $dst, $addr", [(set GPR:$dst, (load addrmodepc:$addr))]>; //===----------------------------------------------------------------------===// @@ -540,53 +564,53 @@ def PICLD : AI2<(ops GPR:$dst, addrmodepc:$addr), // let isReturn = 1, isTerminator = 1 in - def BX_RET : AI<(ops), "bx lr", [(ARMretflag)]>; + def BX_RET : AI<(ops), "bx", " lr", [(ARMretflag)]>; // FIXME: remove when we have a way to marking a MI with these properties. let isLoad = 1, isReturn = 1, isTerminator = 1 in - def LDM_RET : AI4<(ops addrmode4:$addr, reglist:$dst1, variable_ops), - "ldm${addr:submode} $addr, $dst1", + def LDM_RET : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops), + "ldm${p}${addr:submode} $addr, $dst1", []>; let isCall = 1, noResults = 1, Defs = [R0, R1, R2, R3, R12, LR, D0, D1, D2, D3, D4, D5, D6, D7] in { - def BL : AI<(ops i32imm:$func, variable_ops), - "bl ${func:call}", - [(ARMcall tglobaladdr:$func)]>; + def BL : AXI<(ops i32imm:$func, pred:$p, variable_ops), + "bl$p ${func:call}", + [(ARMcall tglobaladdr:$func)]>; // ARMv5T and above - def BLX : AI<(ops GPR:$dst, variable_ops), - "blx $dst", - [(ARMcall GPR:$dst)]>, Requires<[IsARM, HasV5T]>; + def BLX : AXI<(ops GPR:$dst, pred:$p, variable_ops), + "blx$p $dst", + [(ARMcall GPR:$dst)]>, Requires<[IsARM, HasV5T]>; let Uses = [LR] in { // ARMv4T - def BX : AIx2<(ops GPR:$dst, variable_ops), - "mov lr, pc\n\tbx $dst", + def BX : AXIx2<(ops GPR:$dst, pred:$p, variable_ops), + "mov$p lr, pc\n\tbx$p $dst", [(ARMcall_nolink GPR:$dst)]>; } } -let isBranch = 1, isTerminator = 1, isBarrier = 1 in { - def B : AI<(ops brtarget:$dst), "b $dst", - [(br bb:$dst)]>; +let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in { + // B can changed into a Bcc, but it is not "predicated". + def B : AXI<(ops brtarget:$dst), "b $dst", + [(br bb:$dst)]>; + + def Bcc : AXI<(ops brtarget:$dst, ccop:$cc), "b$cc $dst", + [(ARMbrcond bb:$dst, imm:$cc)]>; def BR_JTr : JTI<(ops GPR:$dst, jtblock_operand:$jt, i32imm:$id), - "mov pc, $dst \n$jt", + "mov", " pc, $dst \n$jt", [(ARMbrjt GPR:$dst, tjumptable:$jt, imm:$id)]>; def BR_JTm : JTI2<(ops addrmode2:$dst, jtblock_operand:$jt, i32imm:$id), - "ldr pc, $dst \n$jt", + "ldr", " pc, $dst \n$jt", [(ARMbrjt (i32 (load addrmode2:$dst)), tjumptable:$jt, imm:$id)]>; def BR_JTadd : JTI1<(ops GPR:$dst, GPR:$idx, jtblock_operand:$jt, i32imm:$id), - "add pc, $dst, $idx \n$jt", + "add", " pc, $dst, $idx \n$jt", [(ARMbrjt (add GPR:$dst, GPR:$idx), tjumptable:$jt, imm:$id)]>; } -let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in - def Bcc : AI<(ops brtarget:$dst, ccop:$cc), "b$cc $dst", - [(ARMbrcond bb:$dst, imm:$cc)]>; - //===----------------------------------------------------------------------===// // Load / store Instructions. // @@ -594,117 +618,117 @@ let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in // Load let isLoad = 1 in { def LDR : AI2<(ops GPR:$dst, addrmode2:$addr), - "ldr $dst, $addr", + "ldr", " $dst, $addr", [(set GPR:$dst, (load addrmode2:$addr))]>; // Special LDR for loads from non-pc-relative constpools. let isReMaterializable = 1 in def LDRcp : AI2<(ops GPR:$dst, addrmode2:$addr), - "ldr $dst, $addr", []>; + "ldr", " $dst, $addr", []>; // Loads with zero extension def LDRH : AI3<(ops GPR:$dst, addrmode3:$addr), - "ldrh $dst, $addr", + "ldrh", " $dst, $addr", [(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>; def LDRB : AI2<(ops GPR:$dst, addrmode2:$addr), - "ldrb $dst, $addr", + "ldrb", " $dst, $addr", [(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>; // Loads with sign extension def LDRSH : AI3<(ops GPR:$dst, addrmode3:$addr), - "ldrsh $dst, $addr", + "ldrsh", " $dst, $addr", [(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>; def LDRSB : AI3<(ops GPR:$dst, addrmode3:$addr), - "ldrsb $dst, $addr", + "ldrsb", " $dst, $addr", [(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>; // Load doubleword def LDRD : AI3<(ops GPR:$dst, addrmode3:$addr), - "ldrd $dst, $addr", + "ldrd", " $dst, $addr", []>, Requires<[IsARM, HasV5T]>; // Indexed loads def LDR_PRE : AI2pr<(ops GPR:$dst, GPR:$base_wb, addrmode2:$addr), - "ldr $dst, $addr!", "$addr.base = $base_wb", []>; + "ldr", " $dst, $addr!", "$addr.base = $base_wb", []>; def LDR_POST : AI2po<(ops GPR:$dst, GPR:$base_wb, GPR:$base, am2offset:$offset), - "ldr $dst, [$base], $offset", "$base = $base_wb", []>; + "ldr", " $dst, [$base], $offset", "$base = $base_wb", []>; def LDRH_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr), - "ldrh $dst, $addr!", "$addr.base = $base_wb", []>; + "ldrh", " $dst, $addr!", "$addr.base = $base_wb", []>; def LDRH_POST : AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset), - "ldrh $dst, [$base], $offset", "$base = $base_wb", []>; + "ldrh", " $dst, [$base], $offset", "$base = $base_wb", []>; def LDRB_PRE : AI2pr<(ops GPR:$dst, GPR:$base_wb, addrmode2:$addr), - "ldrb $dst, $addr!", "$addr.base = $base_wb", []>; + "ldrb", " $dst, $addr!", "$addr.base = $base_wb", []>; def LDRB_POST : AI2po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am2offset:$offset), - "ldrb $dst, [$base], $offset", "$base = $base_wb", []>; + "ldrb", " $dst, [$base], $offset", "$base = $base_wb", []>; def LDRSH_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr), - "ldrsh $dst, $addr!", "$addr.base = $base_wb", []>; + "ldrsh", " $dst, $addr!", "$addr.base = $base_wb", []>; def LDRSH_POST: AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset), - "ldrsh $dst, [$base], $offset", "$base = $base_wb", []>; + "ldrsh", " $dst, [$base], $offset", "$base = $base_wb", []>; def LDRSB_PRE : AI3pr<(ops GPR:$dst, GPR:$base_wb, addrmode3:$addr), - "ldrsb $dst, $addr!", "$addr.base = $base_wb", []>; + "ldrsb", " $dst, $addr!", "$addr.base = $base_wb", []>; def LDRSB_POST: AI3po<(ops GPR:$dst, GPR:$base_wb, GPR:$base,am3offset:$offset), - "ldrsb $dst, [$base], $offset", "$base = $base_wb", []>; + "ldrsb", " $dst, [$base], $offset", "$base = $base_wb", []>; } // isLoad // Store let isStore = 1 in { def STR : AI2<(ops GPR:$src, addrmode2:$addr), - "str $src, $addr", + "str", " $src, $addr", [(store GPR:$src, addrmode2:$addr)]>; // Stores with truncate def STRH : AI3<(ops GPR:$src, addrmode3:$addr), - "strh $src, $addr", + "strh", " $src, $addr", [(truncstorei16 GPR:$src, addrmode3:$addr)]>; def STRB : AI2<(ops GPR:$src, addrmode2:$addr), - "strb $src, $addr", + "strb", " $src, $addr", [(truncstorei8 GPR:$src, addrmode2:$addr)]>; // Store doubleword def STRD : AI3<(ops GPR:$src, addrmode3:$addr), - "strd $src, $addr", + "strd", " $src, $addr", []>, Requires<[IsARM, HasV5T]>; // Indexed stores def STR_PRE : AI2pr<(ops GPR:$base_wb, GPR:$src, GPR:$base, am2offset:$offset), - "str $src, [$base, $offset]!", "$base = $base_wb", + "str", " $src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_store GPR:$src, GPR:$base, am2offset:$offset))]>; def STR_POST : AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset), - "str $src, [$base], $offset", "$base = $base_wb", + "str", " $src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_store GPR:$src, GPR:$base, am2offset:$offset))]>; def STRH_PRE : AI3pr<(ops GPR:$base_wb, GPR:$src, GPR:$base,am3offset:$offset), - "strh $src, [$base, $offset]!", "$base = $base_wb", + "strh", " $src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>; def STRH_POST: AI3po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am3offset:$offset), - "strh $src, [$base], $offset", "$base = $base_wb", + "strh", " $src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_truncsti16 GPR:$src, GPR:$base, am3offset:$offset))]>; def STRB_PRE : AI2pr<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset), - "strb $src, [$base, $offset]!", "$base = $base_wb", + "strb", " $src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti8 GPR:$src, GPR:$base, am2offset:$offset))]>; def STRB_POST: AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset), - "strb $src, [$base], $offset", "$base = $base_wb", + "strb", " $src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_truncsti8 GPR:$src, GPR:$base, am2offset:$offset))]>; } // isStore @@ -714,42 +738,41 @@ def STRB_POST: AI2po<(ops GPR:$base_wb, GPR:$src, GPR:$base,am2offset:$offset), // let isLoad = 1 in -def LDM : AI4<(ops addrmode4:$addr, reglist:$dst1, variable_ops), - "ldm${addr:submode} $addr, $dst1", - []>; +def LDM : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops), + "ldm${p}${addr:submode} $addr, $dst1", + []>; let isStore = 1 in -def STM : AI4<(ops addrmode4:$addr, reglist:$src1, variable_ops), - "stm${addr:submode} $addr, $src1", - []>; +def STM : AXI4<(ops addrmode4:$addr, pred:$p, reglist:$src1, variable_ops), + "stm${p}${addr:submode} $addr, $src1", + []>; //===----------------------------------------------------------------------===// // Move Instructions. // def MOVr : AI1<(ops GPR:$dst, GPR:$src), - "mov $dst, $src", []>; + "mov", " $dst, $src", []>; def MOVs : AI1& |