Added isLegalAddressExpression(). Only allows X +/- C for now.
[oota-llvm.git] / lib / Target / ARM / ARMISelLowering.cpp
index f111d8786b6f75a27683a2bab7fafaa29941685b..40ede7409aca8e2b396db11eb19362a2f9e3064c 100644 (file)
@@ -22,6 +22,7 @@
 #include "ARMTargetMachine.h"
 #include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
+#include "llvm/Instruction.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -30,6 +31,7 @@
 #include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/VectorExtras.h"
+#include "llvm/Support/MathExtras.h"
 using namespace llvm;
 
 ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
@@ -167,7 +169,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::LOCATION, MVT::Other, Expand);
   setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
   // FIXME - use subtarget debug flags
-  if (Subtarget->isTargetDarwin())
+  if (!Subtarget->isTargetDarwin())
     setOperationAction(ISD::LABEL, MVT::Other, Expand);
 
   setOperationAction(ISD::RET,           MVT::Other, Custom);
@@ -1268,17 +1270,104 @@ ARMTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
 //                           ARM Optimization Hooks
 //===----------------------------------------------------------------------===//
 
-/// isLegalAddressImmediate - Return true if the integer value or
-/// GlobalValue can be used as the offset of the target addressing mode.
-bool ARMTargetLowering::isLegalAddressImmediate(int64_t V) const {
-  // ARM allows a 12-bit immediate field.
-  return V == V & ((1LL << 12) - 1);
+/// isLegalAddressExpression - Return true if the binary expression made up of
+/// specified opcode, operands, and type can be folded into target addressing
+/// mode for load / store of the given type.
+bool ARMTargetLowering::isLegalAddressExpression(unsigned Opc, Value *Op0,
+                                             Value *Op1, const Type *Ty) const {
+  if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
+    if (Opc == Instruction::Add)
+      return isLegalAddressImmediate(Op1C->getSExtValue(), Ty);
+    if (Opc == Instruction::Sub)
+      return isLegalAddressImmediate(-Op1C->getSExtValue(), Ty);
+  }
+  return false;
+}
+
+/// isLegalAddressImmediate - Return true if the integer value can be used
+/// as the offset of the target addressing mode for load / store of the
+/// given type.
+bool ARMTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{
+  if (V == 0)
+    return true;
+
+  MVT::ValueType VT = getValueType(Ty);
+  if (Subtarget->isThumb()) {
+    if (V < 0)
+      return false;
+
+    unsigned Scale = 1;
+    switch (VT) {
+    default: return false;
+    case MVT::i1:
+    case MVT::i8:
+      // Scale == 1;
+      break;
+    case MVT::i16:
+      // Scale == 2;
+      Scale = 2;
+      break;
+    case MVT::i32:
+      // Scale == 4;
+      Scale = 4;
+      break;
+    }
+
+    if ((V & (Scale - 1)) != 0)
+      return false;
+    V /= Scale;
+    return V == V & ((1LL << 5) - 1);
+  }
+
+  if (V < 0)
+    V = - V;
+  switch (VT) {
+  default: return false;
+  case MVT::i1:
+  case MVT::i8:
+  case MVT::i32:
+    // +- imm12
+    return V == V & ((1LL << 12) - 1);
+  case MVT::i16:
+    // +- imm8
+    return V == V & ((1LL << 8) - 1);
+  case MVT::f32:
+  case MVT::f64:
+    if (!Subtarget->hasVFP2())
+      return false;
+    if ((V % 3) != 0)
+      return false;
+    V >>= 2;
+    return V == V & ((1LL << 8) - 1);
+  }
 }
 
 bool ARMTargetLowering::isLegalAddressImmediate(GlobalValue *GV) const {
   return false;
 }
 
+/// isLegalAddressScale - Return true if the integer value can be used as
+/// the scale of the target addressing mode for load / store of the given
+/// type.
+bool ARMTargetLowering::isLegalAddressScale(int64_t S, const Type *Ty) const {
+  if (Subtarget->isThumb())
+    return false;
+
+  MVT::ValueType VT = getValueType(Ty);
+  switch (VT) {
+  default: return false;
+  case MVT::i1:
+  case MVT::i8:
+  case MVT::i32:
+    // r + r
+    if (S == 2)
+      return true;
+    // r + r << imm
+    S &= ~1;
+    return isPowerOf2_32(S);
+  }
+}
+
 static bool getIndexedAddressParts(SDNode *Ptr, MVT::ValueType VT,
                                    bool isSEXTLoad, SDOperand &Base,
                                    SDOperand &Offset, bool &isInc,