mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 01:11:44 +00:00
Build constants using instructions mov/orr or mvn/eor.
llvm-svn: 33141
This commit is contained in:
parent
4eea43e6ce
commit
97e120a71c
84
lib/Target/ARM/ARMCommon.cpp
Normal file
84
lib/Target/ARM/ARMCommon.cpp
Normal 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;
|
||||
}
|
22
lib/Target/ARM/ARMCommon.h
Normal file
22
lib/Target/ARM/ARMCommon.h
Normal 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
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 &&
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user