aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-03-20 08:11:30 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-03-20 08:11:30 +0000
commitc70d1849b7b85b06adf7dce856b3b19028fff8f7 (patch)
tree98bd8a21a234e7713b9dc01b081ee5ee30334b6e /lib/Target/ARM
parent5603dcf21e3227e457624e9ff895f4893ca81528 (diff)
downloadexternal_llvm-c70d1849b7b85b06adf7dce856b3b19028fff8f7.zip
external_llvm-c70d1849b7b85b06adf7dce856b3b19028fff8f7.tar.gz
external_llvm-c70d1849b7b85b06adf7dce856b3b19028fff8f7.tar.bz2
Make two piece constant generation as a single instruction. It's re-materialized as a load from constantpool.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35207 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARMAsmPrinter.cpp37
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td48
2 files changed, 55 insertions, 30 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp
index 2073e80..1f052bf 100644
--- a/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -82,6 +82,7 @@ namespace {
void printOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
void printSOImmOperand(const MachineInstr *MI, int opNum);
+ void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
void printSORegOperand(const MachineInstr *MI, int opNum);
void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
@@ -309,14 +310,10 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
}
}
-/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
-/// immediate in bits 0-7.
-void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
- const MachineOperand &MO = MI->getOperand(OpNum);
- assert(MO.isImmediate() && (MO.getImmedValue() < (1 << 12)) &&
- "Not a valid so_imm value!");
- unsigned Imm = ARM_AM::getSOImmValImm(MO.getImmedValue());
- unsigned Rot = ARM_AM::getSOImmValRot(MO.getImmedValue());
+static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) {
+ assert(V < (1 << 12) && "Not a valid so_imm value!");
+ unsigned Imm = ARM_AM::getSOImmValImm(V);
+ unsigned Rot = ARM_AM::getSOImmValRot(V);
// Print low-level immediate formation info, per
// A5.1.3: "Data-processing operands - Immediate".
@@ -329,6 +326,30 @@ void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
}
}
+/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
+/// immediate in bits 0-7.
+void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isImmediate() && "Not a valid so_imm value!");
+ printSOImm(O, MO.getImmedValue(), TAI);
+}
+
+/// printSOImm2PartOperand - SOImm is broken into two pieces using a mov
+/// followed by a or to materialize.
+void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isImmediate() && "Not a valid so_imm value!");
+ unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImmedValue());
+ unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImmedValue());
+ printSOImm(O, ARM_AM::getSOImmVal(V1), TAI);
+ O << "\n\torr ";
+ printOperand(MI, 0);
+ O << ", ";
+ printOperand(MI, 0);
+ O << ", ";
+ printSOImm(O, ARM_AM::getSOImmVal(V2), TAI);
+}
+
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
// REG 0 0 - e.g. R5
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 4d2aba7..bb8b61f 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -147,24 +147,6 @@ def sext_16_node : PatLeaf<(i32 GPR:$a), [{
}]>;
-// Break so_imm's up into two pieces. This handles immediates with up to 16
-// bits set in them. This uses so_imm2part to match and so_imm2part_[12] to
-// get the first/second pieces.
-def so_imm2part : PatLeaf<(imm), [{
- return ARM_AM::isSOImmTwoPartVal((unsigned)N->getValue());
-}]>;
-
-def so_imm2part_1 : SDNodeXForm<imm, [{
- unsigned V = ARM_AM::getSOImmTwoPartFirst((unsigned)N->getValue());
- return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(V), MVT::i32);
-}]>;
-
-def so_imm2part_2 : SDNodeXForm<imm, [{
- unsigned V = ARM_AM::getSOImmTwoPartSecond((unsigned)N->getValue());
- return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(V), MVT::i32);
-}]>;
-
-
//===----------------------------------------------------------------------===//
// Operand Definitions.
@@ -217,6 +199,25 @@ def so_imm : Operand<i32>,
let PrintMethod = "printSOImmOperand";
}
+// Break so_imm's up into two pieces. This handles immediates with up to 16
+// bits set in them. This uses so_imm2part to match and so_imm2part_[12] to
+// get the first/second pieces.
+def so_imm2part : Operand<i32>,
+ PatLeaf<(imm),
+ [{ return ARM_AM::isSOImmTwoPartVal((unsigned)N->getValue()); }]> {
+ let PrintMethod = "printSOImm2PartOperand";
+}
+
+def so_imm2part_1 : SDNodeXForm<imm, [{
+ unsigned V = ARM_AM::getSOImmTwoPartFirst((unsigned)N->getValue());
+ return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(V), MVT::i32);
+}]>;
+
+def so_imm2part_2 : SDNodeXForm<imm, [{
+ unsigned V = ARM_AM::getSOImmTwoPartSecond((unsigned)N->getValue());
+ return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(V), MVT::i32);
+}]>;
+
// Define ARM specific addressing modes.
@@ -371,6 +372,8 @@ 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>;
// Pre-indexed ops
class AI2pr<dag ops, string asm, string cstr, list<dag> pattern>
@@ -1064,14 +1067,15 @@ def LEApcrelJT : AI1<(ops GPR:$dst, i32imm:$label, i32imm:$id),
def : ARMPat<(ARMWrapper tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>;
def : ARMPat<(ARMWrapper tconstpool :$dst), (LEApcrel tconstpool :$dst)>;
def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
- (LEApcrelJT tjumptable:$dst, imm:$id)>;
+ (LEApcrelJT tjumptable:$dst, imm:$id)>;
// Large immediate handling.
// Two piece so_imms.
-def : ARMPat<(i32 so_imm2part:$src),
- (ORRri (MOVi (so_imm2part_1 imm:$src)),
- (so_imm2part_2 imm:$src))>;
+let isReMaterializable = 1 in
+def MOVi2pieces : AI1x2<(ops GPR:$dst, so_imm2part:$src),
+ "mov $dst, $src",
+ [(set GPR:$dst, so_imm2part:$src)]>;
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
(ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)),