From 97e120a71cff1cae6afbbed59712a9fa99d6cf35 Mon Sep 17 00:00:00 2001 From: Lauro Ramos Venancio Date: Fri, 12 Jan 2007 20:35:49 +0000 Subject: [PATCH] Build constants using instructions mov/orr or mvn/eor. llvm-svn: 33141 --- lib/Target/ARM/ARMCommon.cpp | 84 +++++++++++++++++++++ lib/Target/ARM/ARMCommon.h | 22 ++++++ lib/Target/ARM/ARMISelDAGToDAG.cpp | 94 +++++++++++++++++++----- lib/Target/ARM/ARMRegisterInfo.cpp | 75 ++----------------- test/Regression/CodeGen/ARM/constants.ll | 3 +- test/Regression/CodeGen/ARM/fp.ll | 8 +- test/Regression/CodeGen/ARM/fpmem.ll | 2 +- 7 files changed, 196 insertions(+), 92 deletions(-) create mode 100644 lib/Target/ARM/ARMCommon.cpp create mode 100644 lib/Target/ARM/ARMCommon.h diff --git a/lib/Target/ARM/ARMCommon.cpp b/lib/Target/ARM/ARMCommon.cpp new file mode 100644 index 00000000000..fd3757303bc --- /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 max_zero_length){ + max_zero_length = zero_length; + max_zero_pos = zero_pos % 32; + } + + } + + return (max_zero_pos + max_zero_length) % 32; +} + +std::vector splitImmediate(unsigned immediate){ + std::vector 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 00000000000..c35150b7a44 --- /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 + +std::vector splitImmediate(unsigned immediate); + +#endif diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index ef28a90004d..2a5f3e360ca 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 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::vectorimmediatePieces = splitImmediate(immediate); + if (immediatePieces.size()>1){ + unsigned movInst = ARM::MOV; + unsigned orInst = ARM::ORR; + SDNode *node; + //try mvn + std::vectorimmediateNegPieces = 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::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(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(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(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(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 404ebee0f48..4890e3094fe 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 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 immediatePieces = splitImmediate(immediate); + std::vector::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) diff --git a/test/Regression/CodeGen/ARM/constants.ll b/test/Regression/CodeGen/ARM/constants.ll index 560a4c8429c..c499a08209d 100644 --- a/test/Regression/CodeGen/ARM/constants.ll +++ b/test/Regression/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/Regression/CodeGen/ARM/fp.ll b/test/Regression/CodeGen/ARM/fp.ll index 127d9a1a217..ef6fde6a1c3 100644 --- a/test/Regression/CodeGen/ARM/fp.ll +++ b/test/Regression/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 ; [#uses=1] + ret float %tmp +} + float %h() { entry: ret float 1.000000e+00 diff --git a/test/Regression/CodeGen/ARM/fpmem.ll b/test/Regression/CodeGen/ARM/fpmem.ll index 7704f2b9a7a..4f942e83654 100644 --- a/test/Regression/CodeGen/ARM/fpmem.ll +++ b/test/Regression/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