aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-05-15 01:29:07 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-05-15 01:29:07 +0000
commit44bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4 (patch)
tree6a1a76ed9f6ef5f903fe0b8571bb7cfe3ab69b1b
parent709fd414e2e5c3f3f282864a16688409ea152706 (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.cpp5
-rw-r--r--lib/Target/ARM/ARMConstantIslandPass.cpp12
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp40
-rw-r--r--lib/Target/ARM/ARMInstrInfo.cpp37
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td357
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td14
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td166
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp96
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp125
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&