ARMSelectionDAGInfo.cpp revision 4bfcd4acbc7d12aa55f8de9af84a38422f0f6d83
153c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===// 253c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// 353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// The LLVM Compiler Infrastructure 453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// 553c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// This file is distributed under the University of Illinois Open Source 653c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// License. See LICENSE.TXT for details. 753c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// 853c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===----------------------------------------------------------------------===// 953c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// 1053c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// This file implements the ARMSelectionDAGInfo class. 1153c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// 1253c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===----------------------------------------------------------------------===// 1353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman 1453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman#define DEBUG_TYPE "arm-selectiondag-info" 15ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman#include "ARMTargetMachine.h" 161ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin#include "llvm/DerivedTypes.h" 171ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin#include "llvm/CodeGen/SelectionDAG.h" 1853c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohmanusing namespace llvm; 1953c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman 20ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM) 21ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman : TargetSelectionDAGInfo(TM), 22ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 2353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman} 2453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman 2553c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan GohmanARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 2653c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman} 27ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 28ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanSDValue 29ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, 30ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SDValue Chain, 31ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SDValue Dst, SDValue Src, 32ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SDValue Size, unsigned Align, 33ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman bool isVolatile, bool AlwaysInline, 34e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner MachinePointerInfo DstPtrInfo, 35e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner MachinePointerInfo SrcPtrInfo) const { 36ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // Do repeated 4-byte loads and stores. To be improved. 37ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // This requires 4-byte alignment. 38ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman if ((Align & 3) != 0) 39ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman return SDValue(); 407a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner // This requires the copy size to be a constant, preferably 41ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // within a subtarget-specific limit. 42ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 43ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman if (!ConstantSize) 44ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman return SDValue(); 45ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman uint64_t SizeVal = ConstantSize->getZExtValue(); 46ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold()) 47ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman return SDValue(); 48ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 49ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman unsigned BytesLeft = SizeVal & 3; 50ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman unsigned NumMemOps = SizeVal >> 2; 51ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman unsigned EmittedNumMemOps = 0; 52ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman EVT VT = MVT::i32; 53ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman unsigned VTSize = 4; 54ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman unsigned i = 0; 55ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman const unsigned MAX_LOADS_IN_LDM = 6; 56ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SDValue TFOps[MAX_LOADS_IN_LDM]; 57ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SDValue Loads[MAX_LOADS_IN_LDM]; 58ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman uint64_t SrcOff = 0, DstOff = 0; 59ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 60ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the 61ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // same number of stores. The loads and stores will get combined into 62ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // ldm/stm later on. 63ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman while (EmittedNumMemOps < NumMemOps) { 64ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman for (i = 0; 65ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 66ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman Loads[i] = DAG.getLoad(VT, dl, Chain, 67ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 68ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getConstant(SrcOff, MVT::i32)), 69e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner SrcPtrInfo.getWithOffset(SrcOff), isVolatile, 70d752e0f7e64585839cb3a458ef52456eaebbea3cPete Cooper false, false, 0); 71ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman TFOps[i] = Loads[i].getValue(1); 72ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SrcOff += VTSize; 73ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 74ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 75ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 76ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman for (i = 0; 77ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 78ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 79ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 80ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getConstant(DstOff, MVT::i32)), 81e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner DstPtrInfo.getWithOffset(DstOff), 82e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner isVolatile, false, 0); 83ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DstOff += VTSize; 84ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 85ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 86ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 87ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman EmittedNumMemOps += i; 88ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 89ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 90ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman if (BytesLeft == 0) 91ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman return Chain; 92ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 93ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman // Issue loads / stores for the trailing (1 - 3) bytes. 94ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman unsigned BytesLeftSave = BytesLeft; 95ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman i = 0; 96ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman while (BytesLeft) { 97ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman if (BytesLeft >= 2) { 98ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VT = MVT::i16; 99ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VTSize = 2; 100ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } else { 101ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VT = MVT::i8; 102ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VTSize = 1; 103ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 104ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 105ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman Loads[i] = DAG.getLoad(VT, dl, Chain, 106ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 107ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getConstant(SrcOff, MVT::i32)), 108d752e0f7e64585839cb3a458ef52456eaebbea3cPete Cooper SrcPtrInfo.getWithOffset(SrcOff), 109d752e0f7e64585839cb3a458ef52456eaebbea3cPete Cooper false, false, false, 0); 110ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman TFOps[i] = Loads[i].getValue(1); 111ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman ++i; 112ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman SrcOff += VTSize; 113ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman BytesLeft -= VTSize; 114ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 115ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 116ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 117ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman i = 0; 118ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman BytesLeft = BytesLeftSave; 119ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman while (BytesLeft) { 120ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman if (BytesLeft >= 2) { 121ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VT = MVT::i16; 122ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VTSize = 2; 123ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } else { 124ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VT = MVT::i8; 125ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman VTSize = 1; 126ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 127ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman 128ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 129ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 130ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DAG.getConstant(DstOff, MVT::i32)), 131e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner DstPtrInfo.getWithOffset(DstOff), false, false, 0); 132ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman ++i; 133ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman DstOff += VTSize; 134ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman BytesLeft -= VTSize; 135ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman } 136ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 137ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman} 1381ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1391ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin// Adjust parameters for memset, EABI uses format (ptr, size, value), 1401ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin// GNU library uses (ptr, value, size) 1411ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin// See RTABI section 4.3.4 142b04546ff5b1a7a03eec1076900c945223bf494ccJim GrosbachSDValue ARMSelectionDAGInfo:: 143b04546ff5b1a7a03eec1076900c945223bf494ccJim GrosbachEmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, 144b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach SDValue Chain, SDValue Dst, 145b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach SDValue Src, SDValue Size, 146b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach unsigned Align, bool isVolatile, 147b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach MachinePointerInfo DstPtrInfo) const { 14807043279f60622243d16d8a3f60805960482083cEvan Cheng // Use default for non AAPCS (or Darwin) subtargets 14907043279f60622243d16d8a3f60805960482083cEvan Cheng if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetDarwin()) 1501ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin return SDValue(); 1511ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1521ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin const ARMTargetLowering &TLI = 1531ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin *static_cast<const ARMTargetLowering*>(DAG.getTarget().getTargetLowering()); 1541ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin TargetLowering::ArgListTy Args; 1551ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin TargetLowering::ArgListEntry Entry; 1561ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1571ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin // First argument: data pointer 158db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*DAG.getContext()); 1591ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.Node = Dst; 1601ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.Ty = IntPtrTy; 1611ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Args.push_back(Entry); 1621ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1631ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin // Second argument: buffer size 1641ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.Node = Size; 1651ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.Ty = IntPtrTy; 1661ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.isSExt = false; 1671ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Args.push_back(Entry); 1681ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1691ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin // Extend or truncate the argument to be an i32 value for the call. 1701ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin if (Src.getValueType().bitsGT(MVT::i32)) 1711ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src); 1721ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin else 1731ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); 1741ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1751ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin // Third argument: value to fill 1761ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.Node = Src; 1771ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.Ty = Type::getInt32Ty(*DAG.getContext()); 1781ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Entry.isSExt = true; 1791ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Args.push_back(Entry); 1801ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1811ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin // Emit __eabi_memset call 1821ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin std::pair<SDValue,SDValue> CallResult = 1831ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin TLI.LowerCallTo(Chain, 1841ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Type::getVoidTy(*DAG.getContext()), // return type 1851ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin false, // return sign ext 1861ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin false, // return zero ext 1871ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin false, // is var arg 1881ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin false, // is in regs 1891ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 0, // number of fixed arguments 1901ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin TLI.getLibcallCallingConv(RTLIB::MEMSET), // call conv 1911ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin false, // is tail call 1924bfcd4acbc7d12aa55f8de9af84a38422f0f6d83Evan Cheng false, // does not return 1931ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin false, // is return val used 1941ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), 1951ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin TLI.getPointerTy()), // callee 1961ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin Args, DAG, dl); // arg list, DAG and debug 1971ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin 1981ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin return CallResult.second; 1991ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin} 200