Initial support for some Thumb2 instructions.
Patch by Viktor Kutuzov and Anton Korzh from Access Softek, Inc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73622 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index ca3a9cb..1ed9e80 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -52,8 +52,13 @@
virtual const char *getPassName() const {
return "ARM Instruction Selection";
- }
-
+ }
+
+ /// getI32Imm - Return a target constant with the specified value, of type i32.
+ inline SDValue getI32Imm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i32);
+ }
+
SDNode *Select(SDValue Op);
virtual void InstructionSelect();
bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base,
@@ -84,6 +89,9 @@
bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base,
SDValue &OffImm);
+ bool SelectShifterOperand(SDValue Op, SDValue N,
+ SDValue &BaseReg, SDValue &Opc);
+
bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
SDValue &B, SDValue &C);
@@ -509,8 +517,30 @@
return false;
}
+bool ARMDAGToDAGISel::SelectShifterOperand(SDValue Op,
+ SDValue N,
+ SDValue &BaseReg,
+ SDValue &Opc) {
+ ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
+
+ // Don't match base register only case. That is matched to a separate
+ // lower complexity pattern with explicit register operand.
+ if (ShOpcVal == ARM_AM::no_shift) return false;
+
+ BaseReg = N.getOperand(0);
+ unsigned ShImmVal = 0;
+ if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)))
+ ShImmVal = RHS->getZExtValue() & 31;
+ else
+ return false;
+
+ Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
+
+ return true;
+}
+
bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
- SDValue N,
+ SDValue N,
SDValue &BaseReg,
SDValue &ShReg,
SDValue &Opc) {
@@ -549,6 +579,10 @@
switch (N->getOpcode()) {
default: break;
case ISD::Constant: {
+ // ARMv6T2 and later should materialize imms via MOV / MOVT pair.
+ if (Subtarget->hasV6T2Ops() || Subtarget->hasThumb2())
+ break;
+
unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
bool UseCP = true;
if (Subtarget->isThumb())