ARMSelectionDAGInfo.cpp revision 208599
163437Ssheldonh//===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===// 263437Ssheldonh// 363437Ssheldonh// The LLVM Compiler Infrastructure 463437Ssheldonh// 563437Ssheldonh// This file is distributed under the University of Illinois Open Source 663437Ssheldonh// License. See LICENSE.TXT for details. 763437Ssheldonh// 863437Ssheldonh//===----------------------------------------------------------------------===// 963437Ssheldonh// 1063437Ssheldonh// This file implements the ARMSelectionDAGInfo class. 1163437Ssheldonh// 1263437Ssheldonh//===----------------------------------------------------------------------===// 1363437Ssheldonh 1463437Ssheldonh#define DEBUG_TYPE "arm-selectiondag-info" 1563437Ssheldonh#include "ARMTargetMachine.h" 1663437Ssheldonhusing namespace llvm; 1763437Ssheldonh 1863437SsheldonhARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM) 1963437Ssheldonh : TargetSelectionDAGInfo(TM), 2063437Ssheldonh Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 2163437Ssheldonh} 2263437Ssheldonh 2363437SsheldonhARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 2463437Ssheldonh} 2563437Ssheldonh 2663437SsheldonhSDValue 2763437SsheldonhARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, 2863437Ssheldonh SDValue Chain, 2963437Ssheldonh SDValue Dst, SDValue Src, 3063437Ssheldonh SDValue Size, unsigned Align, 3163437Ssheldonh bool isVolatile, bool AlwaysInline, 3263437Ssheldonh const Value *DstSV, 3363437Ssheldonh uint64_t DstSVOff, 3463437Ssheldonh const Value *SrcSV, 3563437Ssheldonh uint64_t SrcSVOff) const { 3663437Ssheldonh // Do repeated 4-byte loads and stores. To be improved. 3763437Ssheldonh // This requires 4-byte alignment. 3863437Ssheldonh if ((Align & 3) != 0) 3963437Ssheldonh return SDValue(); 4063437Ssheldonh // This requires the copy size to be a constant, preferrably 4163437Ssheldonh // within a subtarget-specific limit. 4263437Ssheldonh ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 4363437Ssheldonh if (!ConstantSize) 4463437Ssheldonh return SDValue(); 4563437Ssheldonh uint64_t SizeVal = ConstantSize->getZExtValue(); 4663437Ssheldonh if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold()) 4763437Ssheldonh return SDValue(); 4863437Ssheldonh 4963437Ssheldonh unsigned BytesLeft = SizeVal & 3; 5063437Ssheldonh unsigned NumMemOps = SizeVal >> 2; 5163437Ssheldonh unsigned EmittedNumMemOps = 0; 5263437Ssheldonh EVT VT = MVT::i32; 5363437Ssheldonh unsigned VTSize = 4; 5463437Ssheldonh unsigned i = 0; 5563437Ssheldonh const unsigned MAX_LOADS_IN_LDM = 6; 5663437Ssheldonh SDValue TFOps[MAX_LOADS_IN_LDM]; 5763437Ssheldonh SDValue Loads[MAX_LOADS_IN_LDM]; 5863437Ssheldonh uint64_t SrcOff = 0, DstOff = 0; 5963437Ssheldonh 6063437Ssheldonh // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the 6163437Ssheldonh // same number of stores. The loads and stores will get combined into 6263437Ssheldonh // ldm/stm later on. 6363437Ssheldonh while (EmittedNumMemOps < NumMemOps) { 6463437Ssheldonh for (i = 0; 6563437Ssheldonh i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 6663437Ssheldonh Loads[i] = DAG.getLoad(VT, dl, Chain, 6763437Ssheldonh DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 6863437Ssheldonh DAG.getConstant(SrcOff, MVT::i32)), 6963437Ssheldonh SrcSV, SrcSVOff + SrcOff, isVolatile, false, 0); 7063437Ssheldonh TFOps[i] = Loads[i].getValue(1); 7163437Ssheldonh SrcOff += VTSize; 7263437Ssheldonh } 7363437Ssheldonh Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 7463437Ssheldonh 7563437Ssheldonh for (i = 0; 7663437Ssheldonh i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 7763437Ssheldonh TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 7863437Ssheldonh DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 7963437Ssheldonh DAG.getConstant(DstOff, MVT::i32)), 8063437Ssheldonh DstSV, DstSVOff + DstOff, isVolatile, false, 0); 8163437Ssheldonh DstOff += VTSize; 8263437Ssheldonh } 8363437Ssheldonh Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 8463437Ssheldonh 8563437Ssheldonh EmittedNumMemOps += i; 8663437Ssheldonh } 8763437Ssheldonh 8863437Ssheldonh if (BytesLeft == 0) 8963437Ssheldonh return Chain; 9063437Ssheldonh 9163437Ssheldonh // Issue loads / stores for the trailing (1 - 3) bytes. 9263437Ssheldonh unsigned BytesLeftSave = BytesLeft; 9363437Ssheldonh i = 0; 9463437Ssheldonh while (BytesLeft) { 9563437Ssheldonh if (BytesLeft >= 2) { 9663437Ssheldonh VT = MVT::i16; 9763437Ssheldonh VTSize = 2; 9863437Ssheldonh } else { 9963437Ssheldonh VT = MVT::i8; 10063437Ssheldonh VTSize = 1; 10163437Ssheldonh } 10263437Ssheldonh 10363437Ssheldonh Loads[i] = DAG.getLoad(VT, dl, Chain, 10463437Ssheldonh DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 10563437Ssheldonh DAG.getConstant(SrcOff, MVT::i32)), 10663437Ssheldonh SrcSV, SrcSVOff + SrcOff, false, false, 0); 10763437Ssheldonh TFOps[i] = Loads[i].getValue(1); 10863437Ssheldonh ++i; 10963437Ssheldonh SrcOff += VTSize; 11063437Ssheldonh BytesLeft -= VTSize; 11163437Ssheldonh } 11263437Ssheldonh Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 11363437Ssheldonh 11463437Ssheldonh i = 0; 11563437Ssheldonh BytesLeft = BytesLeftSave; 11663437Ssheldonh while (BytesLeft) { 11763437Ssheldonh if (BytesLeft >= 2) { 11863437Ssheldonh VT = MVT::i16; 11963437Ssheldonh VTSize = 2; 12063437Ssheldonh } else { 12163437Ssheldonh VT = MVT::i8; 12263437Ssheldonh VTSize = 1; 12363437Ssheldonh } 12463437Ssheldonh 12563437Ssheldonh TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 12663437Ssheldonh DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 12763437Ssheldonh DAG.getConstant(DstOff, MVT::i32)), 12863437Ssheldonh DstSV, DstSVOff + DstOff, false, false, 0); 12963437Ssheldonh ++i; 13063437Ssheldonh DstOff += VTSize; 13163437Ssheldonh BytesLeft -= VTSize; 13263437Ssheldonh } 13363437Ssheldonh return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 13463437Ssheldonh} 13563437Ssheldonh