Build constants using instructions mov/orr or mvn/eor.
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Fri, 12 Jan 2007 20:35:49 +0000 (20:35 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Fri, 12 Jan 2007 20:35:49 +0000 (20:35 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33141 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMCommon.cpp [new file with mode: 0644]
lib/Target/ARM/ARMCommon.h [new file with mode: 0644]
lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMRegisterInfo.cpp
test/CodeGen/ARM/constants.ll
test/CodeGen/ARM/fp.ll
test/CodeGen/ARM/fpmem.ll

diff --git a/lib/Target/ARM/ARMCommon.cpp b/lib/Target/ARM/ARMCommon.cpp
new file mode 100644 (file)
index 0000000..fd37573
--- /dev/null
@@ -0,0 +1,84 @@
+//===-- ARMCommon.cpp - Define support functions for ARM --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//
+//===----------------------------------------------------------------------===//
+#include "ARMCommon.h"
+
+static inline unsigned rotateL(unsigned x, unsigned n){
+  return ((x << n) | (x  >> (32 - n)));
+}
+
+static inline unsigned rotateR(unsigned x, unsigned n){
+  return ((x >> n) | (x  << (32 - n)));
+}
+
+// finds the end position of largest sequence of zeros in binary representation
+// of 'immediate'.
+static int findLargestZeroSequence(unsigned immediate){
+  int max_zero_pos = 0;
+  int max_zero_length = 0;
+  int zero_pos;
+  int zero_length;
+  int pos = 0;
+  int end_pos;
+
+  while ((immediate & 0x3) == 0) {
+    immediate = rotateR(immediate, 2);
+    pos+=2;
+  }
+  end_pos = pos+32;
+
+  while (pos<end_pos){
+    while (((immediate & 0x3) != 0)&&(pos<end_pos)) {
+      immediate = rotateR(immediate, 2);
+      pos+=2;
+    }
+    zero_pos = pos;
+    while (((immediate & 0x3) == 0)&&(pos<end_pos)) {
+      immediate = rotateR(immediate, 2);
+      pos+=2;
+    }
+    zero_length = pos - zero_pos;
+    if (zero_length > max_zero_length){
+      max_zero_length = zero_length;
+      max_zero_pos = zero_pos % 32;
+    }
+
+  }
+
+  return (max_zero_pos + max_zero_length) % 32;
+}
+
+std::vector<unsigned> splitImmediate(unsigned immediate){
+  std::vector<unsigned> immediatePieces;
+
+  if (immediate == 0){
+    immediatePieces.push_back(0);
+  } else {
+    int start_pos = findLargestZeroSequence(immediate);
+    unsigned immediate_tmp = rotateR(immediate, start_pos);
+    int pos = 0;
+    while (pos < 32){
+      while(((immediate_tmp&0x3) == 0)&&(pos<32)){
+        immediate_tmp = rotateR(immediate_tmp,2);
+        pos+=2;
+      }
+      if (pos < 32){
+        immediatePieces.push_back(rotateL(immediate_tmp&0xFF,
+                                          (start_pos + pos) % 32 ));
+        immediate_tmp = rotateR(immediate_tmp,8);
+        pos+=8;
+      }
+    }
+  }
+  return immediatePieces;
+}
diff --git a/lib/Target/ARM/ARMCommon.h b/lib/Target/ARM/ARMCommon.h
new file mode 100644 (file)
index 0000000..c35150b
--- /dev/null
@@ -0,0 +1,22 @@
+//===-- ARMCommon.h - Define support functions for ARM ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the "Instituto Nokia de Tecnologia" and
+// is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARM_COMMON_H
+#define ARM_COMMON_H
+
+#include <vector>
+
+std::vector<unsigned> splitImmediate(unsigned immediate);
+
+#endif
index ef28a90004dee88c01ad9c1ee0dd16a805120d63..2a5f3e360cae2337f99876ecafccd2a914d3e292 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "ARM.h"
 #include "ARMTargetMachine.h"
+#include "ARMCommon.h"
 #include "llvm/CallingConv.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
@@ -27,6 +28,7 @@
 #include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
 #include <vector>
 using namespace llvm;
 
@@ -103,8 +105,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::VAEND,         MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
 
-  setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
-  setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
+  setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
+  setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
 
   setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
   setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
@@ -543,6 +545,70 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
   return CPI;
 }
 
+SDOperand LegalizeImmediate(uint32_t immediate, SelectionDAG &DAG,
+                            bool canReturnConstant){
+  SDOperand Shift = DAG.getTargetConstant(0, MVT::i32);
+  SDOperand ShiftType = DAG.getTargetConstant(ARMShift::LSL, MVT::i32);
+  std::vector<unsigned>immediatePieces = splitImmediate(immediate);
+  if (immediatePieces.size()>1){
+    unsigned movInst = ARM::MOV;
+    unsigned orInst = ARM::ORR;
+    SDNode *node;
+    //try mvn
+    std::vector<unsigned>immediateNegPieces = splitImmediate(~immediate);
+    if (immediatePieces.size() > immediateNegPieces.size()) {
+      //use mvn/eor
+      movInst = ARM::MVN;
+      orInst = ARM::EOR;
+      immediatePieces = immediateNegPieces;
+    }
+    SDOperand n = DAG.getTargetConstant(immediatePieces[0], MVT::i32);
+    node = DAG.getTargetNode(movInst, MVT::i32, n, Shift, ShiftType);
+    std::vector<unsigned>::iterator it;
+    for (it=immediatePieces.begin()+1; it != immediatePieces.end(); ++it){
+      n = DAG.getTargetConstant(*it, MVT::i32);
+      SDOperand ops[] = {SDOperand(node, 0), n, Shift, ShiftType};
+      node = DAG.getTargetNode(orInst, MVT::i32, ops, 4);
+    }
+    return SDOperand(node, 0);
+  } else {
+    if (canReturnConstant)
+      return DAG.getTargetConstant(immediate, MVT::i32);
+    else {
+      SDOperand n = DAG.getTargetConstant(immediate, MVT::i32);
+      SDNode *node = DAG.getTargetNode(ARM::MOV,  MVT::i32, n, Shift,
+                                       ShiftType);
+      return SDOperand(node, 0);
+    }
+  }
+}
+
+static SDOperand LowerConstantFP(SDOperand Op, SelectionDAG &DAG) {
+  MVT::ValueType VT = Op.getValueType();
+  SDOperand Shift     = DAG.getTargetConstant(0, MVT::i32);
+  SDOperand ShiftType = DAG.getTargetConstant(ARMShift::LSL, MVT::i32);
+  SDNode *node;
+  switch (VT) {
+  default: assert(0 && "VT!=f32 && VT!=f64");
+  case MVT::f32: {
+    float val = cast<ConstantFPSDNode>(Op)->getValue();
+    uint32_t i32_val = FloatToBits(val);
+    SDOperand c = LegalizeImmediate(i32_val, DAG, false);
+    node = DAG.getTargetNode(ARM::FMSR, MVT::f32, c);
+    break;
+  }
+  case MVT::f64: {
+    double val = cast<ConstantFPSDNode>(Op)->getValue();
+    uint64_t i64_val = DoubleToBits(val);
+    SDOperand hi = LegalizeImmediate(Hi_32(i64_val), DAG, false);
+    SDOperand lo = LegalizeImmediate(Lo_32(i64_val), DAG, false);
+    node = DAG.getTargetNode(ARM::FMDRR, MVT::f64, lo, hi);
+    break;
+  }
+  }
+  return SDOperand(node, 0);
+}
+
 static SDOperand LowerGlobalAddress(SDOperand Op,
                                    SelectionDAG &DAG) {
   GlobalValue  *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
@@ -849,6 +915,8 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
     abort();
   case ISD::ConstantPool:
     return LowerConstantPool(Op, DAG);
+  case ISD::ConstantFP:
+    return LowerConstantFP(Op, DAG);
   case ISD::GlobalAddress:
     return LowerGlobalAddress(Op, DAG);
   case ISD::FP_TO_SINT:
@@ -942,26 +1010,12 @@ bool ARMDAGToDAGISel::SelectAddrMode1(SDOperand Op,
   switch(N.getOpcode()) {
   case ISD::Constant: {
     uint32_t val = cast<ConstantSDNode>(N)->getValue();
-    if(!isRotInt8Immediate(val)) {
-      SDOperand Z = CurDAG->getTargetConstant(0,     MVT::i32);
-      SDNode *n;
-      if (isRotInt8Immediate(~val)) {
-        SDOperand C = CurDAG->getTargetConstant(~val,  MVT::i32);
-        n           = CurDAG->getTargetNode(ARM::MVN,  MVT::i32, C, Z, Z);
-     } else {
-        Constant    *C = ConstantInt::get(Type::Int32Ty, val);
-        int  alignment = 2;
-        SDOperand Addr = CurDAG->getTargetConstantPool(C, MVT::i32, alignment);
-        n              = CurDAG->getTargetNode(ARM::LDR,  MVT::i32, Addr, Z);
-      }
-      Arg            = SDOperand(n, 0);
-    } else
-      Arg            = CurDAG->getTargetConstant(val,    MVT::i32);
-
-    Shift     = CurDAG->getTargetConstant(0,             MVT::i32);
-    ShiftType = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
+    Shift        = CurDAG->getTargetConstant(0, MVT::i32);
+    ShiftType    = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
+    Arg = LegalizeImmediate(val, *CurDAG, true);
     return true;
   }
+
   case ISD::SRA:
     Arg       = N.getOperand(0);
     Shift     = N.getOperand(1);
index 404ebee0f48722079159894614f4b7807e034ec2..4890e3094fe6e0af0111ef7bf00a6ca0127d4806 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "ARM.h"
 #include "ARMRegisterInfo.h"
+#include "ARMCommon.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
@@ -35,82 +36,18 @@ static bool hasFP(const MachineFunction &MF) {
   return NoFramePointerElim || MFI->hasVarSizedObjects();
 }
 
-static inline unsigned rotateL(unsigned x, unsigned n){
-  return ((x << n) | (x  >> (32 - n)));
-}
-
-static inline unsigned rotateR(unsigned x, unsigned n){
-  return ((x >> n) | (x  << (32 - n)));
-}
-
-// finds the end position of largest sequence of zeros in binary representation
-// of 'immediate'.
-static int findLargestZeroSequence(unsigned immediate){
-  int max_zero_pos;
-  int max_zero_length = 0;
-  int zero_pos;
-  int zero_length;
-  int pos = 0;
-  int end_pos;
-
-  while ((immediate & 0x3) == 0) {
-    immediate = rotateR(immediate, 2);
-    pos+=2;
-  }
-  end_pos = pos+32;
-
-  while (pos<end_pos){
-    while ((immediate & 0x3) != 0) {
-      immediate = rotateR(immediate, 2);
-      pos+=2;
-    }
-    zero_pos = pos;
-    while ((immediate & 0x3) == 0) {
-      immediate = rotateR(immediate, 2);
-      pos+=2;
-    }
-    zero_length = pos - zero_pos;
-    if (zero_length > max_zero_length){
-      max_zero_length = zero_length;
-      max_zero_pos = zero_pos % 32;
-    }
-
-  }
-
-  return (max_zero_pos + max_zero_length) % 32;
-}
-
 static void splitInstructionWithImmediate(MachineBasicBlock &BB,
                                       MachineBasicBlock::iterator I,
                                       const TargetInstrDescriptor &TID,
                                       unsigned DestReg,
                                       unsigned OrigReg,
                                       unsigned immediate){
-
-  if (immediate == 0){
-    BuildMI(BB, I, TID, DestReg).addReg(OrigReg).addImm(0)
-       .addImm(0).addImm(ARMShift::LSL);
-    return;
-  }
-
-  int start_pos = findLargestZeroSequence(immediate);
-  unsigned immediate_tmp = rotateR(immediate, start_pos);
-
-  int pos = 0;
-  while (pos < 32){
-    while(((immediate_tmp&0x3) == 0)&&(pos<32)){
-      immediate_tmp = rotateR(immediate_tmp,2);
-      pos+=2;
-    }
-    if (pos < 32){
-      BuildMI(BB, I, TID, DestReg).addReg(OrigReg)
-       .addImm(rotateL(immediate_tmp&0xFF, (start_pos + pos) % 32 ))
-       .addImm(0).addImm(ARMShift::LSL);
-      immediate_tmp = rotateR(immediate_tmp,8);
-      pos+=8;
-    }
+  std::vector<unsigned> immediatePieces = splitImmediate(immediate);
+  std::vector<unsigned>::iterator it;
+  for (it=immediatePieces.begin(); it != immediatePieces.end(); ++it){
+    BuildMI(BB, I, TID, DestReg).addReg(OrigReg)
+       .addImm(*it).addImm(0).addImm(ARMShift::LSL);
   }
-
 }
 
 ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii)
index 560a4c8429cf6f00e49f01a1c44f98b59bd062cb..c499a08209d3b7c76219947a47f130a96fbc1952 100644 (file)
@@ -2,7 +2,8 @@
 ; RUN: grep "mov r0, #0" %t.s     | wc -l | grep 1 &&
 ; RUN: grep "mov r0, #255" %t.s   | wc -l | grep 1 &&
 ; RUN: grep "mov r0, #256" %t.s   | wc -l | grep 1 &&
-; RUN: grep ".word.*257" %t.s     | wc -l | grep 1 &&
+; RUN: grep "mov r0, #1" %t.s     | wc -l | grep 2 &&
+; RUN: grep "orr r0, r0, #256" %t.s     | wc -l | grep 1 &&
 ; RUN: grep "mov r0, #-1073741761" %t.s | wc -l | grep 1 &&
 ; RUN: grep "mov r0, #1008" %t.s  | wc -l | grep 1 &&
 ; RUN: grep "cmp r0, #65536" %t.s | wc -l | grep 1 &&
index 127d9a1a217273a8c52311355c19795c6154c88b..ef6fde6a1c373a3ebecf68f171793d9900c1bc41 100644 (file)
@@ -7,7 +7,7 @@
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep flds &&
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep fstd &&
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep fsts &&
-; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep ".word.*1065353216"
+; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "mov r0, #1065353216"
 
 
 double %h(double* %v) {
@@ -16,6 +16,12 @@ entry:
        ret double %tmp
 }
 
+float %h(float* %v) {
+entry:
+       %tmp = load float* %v           ; <double> [#uses=1]
+       ret float %tmp
+}
+
 float %h() {
 entry:
         ret float 1.000000e+00
index 7704f2b9a7a32a40f8dba35ab3373c3b4d1e5cc6..4f942e836542eca7b9d902ad4d4cef5b369a9f97 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm &&
-; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep flds | wc -l | grep 2 &&
+; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "mov r0, #0" | wc -l | grep 1 &&
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "flds.*\[" | wc -l | grep 1 &&
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "fsts.*\[" | wc -l | grep 1