Changes in directory llvm/lib/Target/ARM:
ARMCommon.cpp added (r1.1) ARMCommon.h added (r1.1) ARMISelDAGToDAG.cpp updated: 1.97 -> 1.98 ARMRegisterInfo.cpp updated: 1.31 -> 1.32 --- Log message: Build constants using instructions mov/orr or mvn/eor. --- Diffs of the changes: (+186 -89) ARMCommon.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++ ARMCommon.h | 22 ++++++++++++ ARMISelDAGToDAG.cpp | 94 ++++++++++++++++++++++++++++++++++++++++------------ ARMRegisterInfo.cpp | 75 +++-------------------------------------- 4 files changed, 186 insertions(+), 89 deletions(-) Index: llvm/lib/Target/ARM/ARMCommon.cpp diff -c /dev/null llvm/lib/Target/ARM/ARMCommon.cpp:1.1 *** /dev/null Fri Jan 12 14:35:59 2007 --- llvm/lib/Target/ARM/ARMCommon.cpp Fri Jan 12 14:35:49 2007 *************** *** 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; + } Index: llvm/lib/Target/ARM/ARMCommon.h diff -c /dev/null llvm/lib/Target/ARM/ARMCommon.h:1.1 *** /dev/null Fri Jan 12 14:36:08 2007 --- llvm/lib/Target/ARM/ARMCommon.h Fri Jan 12 14:35:49 2007 *************** *** 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: llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp diff -u llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp:1.97 llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp:1.98 --- llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp:1.97 Thu Jan 4 08:01:38 2007 +++ llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp Fri Jan 12 14:35:49 2007 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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: llvm/lib/Target/ARM/ARMRegisterInfo.cpp diff -u llvm/lib/Target/ARM/ARMRegisterInfo.cpp:1.31 llvm/lib/Target/ARM/ARMRegisterInfo.cpp:1.32 --- llvm/lib/Target/ARM/ARMRegisterInfo.cpp:1.31 Tue Jan 2 15:31:55 2007 +++ llvm/lib/Target/ARM/ARMRegisterInfo.cpp Fri Jan 12 14:35:49 2007 @@ -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 @@ 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) _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits