Build constants using instructions mov/orr or mvn/eor.

llvm-svn: 33141
This commit is contained in:
Lauro Ramos Venancio 2007-01-12 20:35:49 +00:00
parent 4d06a85487
commit c4235e5521
7 changed files with 196 additions and 92 deletions

View File

@ -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;
}

View File

@ -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

View 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);

View 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;
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);
}
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;
}
}
}
ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii)

View 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 &&

View 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

View 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