aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLauro Ramos Venancio <lauro.venancio@gmail.com>2007-01-12 20:35:49 +0000
committerLauro Ramos Venancio <lauro.venancio@gmail.com>2007-01-12 20:35:49 +0000
commita38bbf7dd3b824aab6c290aec9e03e5cfdd028f5 (patch)
tree68230fad1be0de4a3927d02e1c8726f25ec2c01f
parent609ca3e65307a955ee0eaea80ce0091e3c7967b7 (diff)
Build constants using instructions mov/orr or mvn/eor.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33141 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMCommon.cpp84
-rw-r--r--lib/Target/ARM/ARMCommon.h22
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp94
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp75
-rw-r--r--test/CodeGen/ARM/constants.ll3
-rw-r--r--test/CodeGen/ARM/fp.ll8
-rw-r--r--test/CodeGen/ARM/fpmem.ll2
7 files changed, 196 insertions, 92 deletions
diff --git a/lib/Target/ARM/ARMCommon.cpp b/lib/Target/ARM/ARMCommon.cpp
new file mode 100644
index 0000000000..fd3757303b
--- /dev/null
+++ b/lib/Target/ARM/ARMCommon.cpp
@@ -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
index 0000000000..c35150b7a4
--- /dev/null
+++ b/lib/Target/ARM/ARMCommon.h
@@ -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
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index ef28a90004..2a5f3e360c 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -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);
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp
index 404ebee0f4..4890e3094f 100644
--- a/lib/Target/ARM/ARMRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMRegisterInfo.cpp
@@ -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)
diff --git a/test/CodeGen/ARM/constants.ll b/test/CodeGen/ARM/constants.ll
index 560a4c8429..c499a08209 100644
--- a/test/CodeGen/ARM/constants.ll
+++ b/test/CodeGen/ARM/constants.ll
@@ -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 &&
diff --git a/test/CodeGen/ARM/fp.ll b/test/CodeGen/ARM/fp.ll
index 127d9a1a21..ef6fde6a1c 100644
--- a/test/CodeGen/ARM/fp.ll
+++ b/test/CodeGen/ARM/fp.ll
@@ -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
diff --git a/test/CodeGen/ARM/fpmem.ll b/test/CodeGen/ARM/fpmem.ll
index 7704f2b9a7..4f942e8365 100644
--- a/test/CodeGen/ARM/fpmem.ll
+++ b/test/CodeGen/ARM/fpmem.ll
@@ -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