1234285Sdim//===-- HexagonISelLowering.cpp - Hexagon DAG Lowering Implementation -----===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This file implements the interfaces that Hexagon uses to lower LLVM code 11234285Sdim// into a selection DAG. 12234285Sdim// 13234285Sdim//===----------------------------------------------------------------------===// 14234285Sdim 15234285Sdim#include "HexagonISelLowering.h" 16252723Sdim#include "HexagonMachineFunctionInfo.h" 17252723Sdim#include "HexagonSubtarget.h" 18234285Sdim#include "HexagonTargetMachine.h" 19234285Sdim#include "HexagonTargetObjectFile.h" 20234285Sdim#include "llvm/CodeGen/CallingConvLower.h" 21234285Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 22234285Sdim#include "llvm/CodeGen/MachineFunction.h" 23234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 24234285Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 25234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 26234285Sdim#include "llvm/CodeGen/SelectionDAGISel.h" 27234285Sdim#include "llvm/CodeGen/ValueTypes.h" 28252723Sdim#include "llvm/IR/CallingConv.h" 29252723Sdim#include "llvm/IR/DerivedTypes.h" 30252723Sdim#include "llvm/IR/Function.h" 31252723Sdim#include "llvm/IR/GlobalAlias.h" 32252723Sdim#include "llvm/IR/GlobalVariable.h" 33252723Sdim#include "llvm/IR/InlineAsm.h" 34252723Sdim#include "llvm/IR/Intrinsics.h" 35235633Sdim#include "llvm/Support/CommandLine.h" 36234285Sdim#include "llvm/Support/Debug.h" 37234285Sdim#include "llvm/Support/ErrorHandling.h" 38235633Sdim#include "llvm/Support/raw_ostream.h" 39235633Sdim 40234285Sdimusing namespace llvm; 41234285Sdim 42234285Sdimstatic cl::opt<bool> 43234285SdimEmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden, 44234285Sdim cl::desc("Control jump table emission on Hexagon target")); 45234285Sdim 46263509Sdimnamespace { 47263509Sdimclass HexagonCCState : public CCState { 48263509Sdim int NumNamedVarArgParams; 49234285Sdim 50263509Sdimpublic: 51263509Sdim HexagonCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, 52263509Sdim const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs, 53263509Sdim LLVMContext &C, int NumNamedVarArgParams) 54263509Sdim : CCState(CC, isVarArg, MF, TM, locs, C), 55263509Sdim NumNamedVarArgParams(NumNamedVarArgParams) {} 56263509Sdim 57263509Sdim int getNumNamedVarArgParams() const { return NumNamedVarArgParams; } 58263509Sdim}; 59263509Sdim} 60263509Sdim 61234285Sdim// Implement calling convention for Hexagon. 62234285Sdimstatic bool 63234285SdimCC_Hexagon(unsigned ValNo, MVT ValVT, 64234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 65234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State); 66234285Sdim 67234285Sdimstatic bool 68234285SdimCC_Hexagon32(unsigned ValNo, MVT ValVT, 69234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 70234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State); 71234285Sdim 72234285Sdimstatic bool 73234285SdimCC_Hexagon64(unsigned ValNo, MVT ValVT, 74234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 75234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State); 76234285Sdim 77234285Sdimstatic bool 78234285SdimRetCC_Hexagon(unsigned ValNo, MVT ValVT, 79234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 80234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State); 81234285Sdim 82234285Sdimstatic bool 83234285SdimRetCC_Hexagon32(unsigned ValNo, MVT ValVT, 84234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 85234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State); 86234285Sdim 87234285Sdimstatic bool 88234285SdimRetCC_Hexagon64(unsigned ValNo, MVT ValVT, 89234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 90234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State); 91234285Sdim 92234285Sdimstatic bool 93234285SdimCC_Hexagon_VarArg (unsigned ValNo, MVT ValVT, 94234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 95234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 96263509Sdim HexagonCCState &HState = static_cast<HexagonCCState &>(State); 97234285Sdim 98234285Sdim // NumNamedVarArgParams can not be zero for a VarArg function. 99263509Sdim assert((HState.getNumNamedVarArgParams() > 0) && 100263509Sdim "NumNamedVarArgParams is not bigger than zero."); 101234285Sdim 102263509Sdim if ((int)ValNo < HState.getNumNamedVarArgParams()) { 103234285Sdim // Deal with named arguments. 104234285Sdim return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State); 105234285Sdim } 106234285Sdim 107234285Sdim // Deal with un-named arguments. 108234285Sdim unsigned ofst; 109234285Sdim if (ArgFlags.isByVal()) { 110234285Sdim // If pass-by-value, the size allocated on stack is decided 111234285Sdim // by ArgFlags.getByValSize(), not by the size of LocVT. 112234285Sdim assert ((ArgFlags.getByValSize() > 8) && 113234285Sdim "ByValSize must be bigger than 8 bytes"); 114234285Sdim ofst = State.AllocateStack(ArgFlags.getByValSize(), 4); 115234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); 116234285Sdim return false; 117234285Sdim } 118252723Sdim if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) { 119252723Sdim LocVT = MVT::i32; 120252723Sdim ValVT = MVT::i32; 121252723Sdim if (ArgFlags.isSExt()) 122252723Sdim LocInfo = CCValAssign::SExt; 123252723Sdim else if (ArgFlags.isZExt()) 124252723Sdim LocInfo = CCValAssign::ZExt; 125252723Sdim else 126252723Sdim LocInfo = CCValAssign::AExt; 127252723Sdim } 128245431Sdim if (LocVT == MVT::i32 || LocVT == MVT::f32) { 129234285Sdim ofst = State.AllocateStack(4, 4); 130234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); 131234285Sdim return false; 132234285Sdim } 133245431Sdim if (LocVT == MVT::i64 || LocVT == MVT::f64) { 134234285Sdim ofst = State.AllocateStack(8, 8); 135234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); 136234285Sdim return false; 137234285Sdim } 138234285Sdim llvm_unreachable(0); 139234285Sdim} 140234285Sdim 141234285Sdim 142234285Sdimstatic bool 143234285SdimCC_Hexagon (unsigned ValNo, MVT ValVT, 144234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 145234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 146234285Sdim 147234285Sdim if (ArgFlags.isByVal()) { 148234285Sdim // Passed on stack. 149234285Sdim assert ((ArgFlags.getByValSize() > 8) && 150234285Sdim "ByValSize must be bigger than 8 bytes"); 151234285Sdim unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 4); 152234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 153234285Sdim return false; 154234285Sdim } 155234285Sdim 156234285Sdim if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) { 157234285Sdim LocVT = MVT::i32; 158234285Sdim ValVT = MVT::i32; 159234285Sdim if (ArgFlags.isSExt()) 160234285Sdim LocInfo = CCValAssign::SExt; 161234285Sdim else if (ArgFlags.isZExt()) 162234285Sdim LocInfo = CCValAssign::ZExt; 163234285Sdim else 164234285Sdim LocInfo = CCValAssign::AExt; 165234285Sdim } 166234285Sdim 167245431Sdim if (LocVT == MVT::i32 || LocVT == MVT::f32) { 168234285Sdim if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) 169234285Sdim return false; 170234285Sdim } 171234285Sdim 172245431Sdim if (LocVT == MVT::i64 || LocVT == MVT::f64) { 173234285Sdim if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) 174234285Sdim return false; 175234285Sdim } 176234285Sdim 177234285Sdim return true; // CC didn't match. 178234285Sdim} 179234285Sdim 180234285Sdim 181234285Sdimstatic bool CC_Hexagon32(unsigned ValNo, MVT ValVT, 182234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 183234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 184234285Sdim 185234285Sdim static const uint16_t RegList[] = { 186234285Sdim Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4, 187234285Sdim Hexagon::R5 188234285Sdim }; 189234285Sdim if (unsigned Reg = State.AllocateReg(RegList, 6)) { 190234285Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 191234285Sdim return false; 192234285Sdim } 193234285Sdim 194234285Sdim unsigned Offset = State.AllocateStack(4, 4); 195234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 196234285Sdim return false; 197234285Sdim} 198234285Sdim 199234285Sdimstatic bool CC_Hexagon64(unsigned ValNo, MVT ValVT, 200234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 201234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 202234285Sdim 203234285Sdim if (unsigned Reg = State.AllocateReg(Hexagon::D0)) { 204234285Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 205234285Sdim return false; 206234285Sdim } 207234285Sdim 208234285Sdim static const uint16_t RegList1[] = { 209234285Sdim Hexagon::D1, Hexagon::D2 210234285Sdim }; 211234285Sdim static const uint16_t RegList2[] = { 212234285Sdim Hexagon::R1, Hexagon::R3 213234285Sdim }; 214234285Sdim if (unsigned Reg = State.AllocateReg(RegList1, RegList2, 2)) { 215234285Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 216234285Sdim return false; 217234285Sdim } 218234285Sdim 219234285Sdim unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2); 220234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 221234285Sdim return false; 222234285Sdim} 223234285Sdim 224234285Sdimstatic bool RetCC_Hexagon(unsigned ValNo, MVT ValVT, 225234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 226234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 227234285Sdim 228234285Sdim 229234285Sdim if (LocVT == MVT::i1 || 230234285Sdim LocVT == MVT::i8 || 231234285Sdim LocVT == MVT::i16) { 232234285Sdim LocVT = MVT::i32; 233234285Sdim ValVT = MVT::i32; 234234285Sdim if (ArgFlags.isSExt()) 235234285Sdim LocInfo = CCValAssign::SExt; 236234285Sdim else if (ArgFlags.isZExt()) 237234285Sdim LocInfo = CCValAssign::ZExt; 238234285Sdim else 239234285Sdim LocInfo = CCValAssign::AExt; 240234285Sdim } 241234285Sdim 242245431Sdim if (LocVT == MVT::i32 || LocVT == MVT::f32) { 243234285Sdim if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) 244234285Sdim return false; 245234285Sdim } 246234285Sdim 247245431Sdim if (LocVT == MVT::i64 || LocVT == MVT::f64) { 248234285Sdim if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) 249234285Sdim return false; 250234285Sdim } 251234285Sdim 252234285Sdim return true; // CC didn't match. 253234285Sdim} 254234285Sdim 255234285Sdimstatic bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT, 256234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 257234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 258234285Sdim 259245431Sdim if (LocVT == MVT::i32 || LocVT == MVT::f32) { 260234285Sdim if (unsigned Reg = State.AllocateReg(Hexagon::R0)) { 261234285Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 262234285Sdim return false; 263234285Sdim } 264234285Sdim } 265234285Sdim 266234285Sdim unsigned Offset = State.AllocateStack(4, 4); 267234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 268234285Sdim return false; 269234285Sdim} 270234285Sdim 271234285Sdimstatic bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT, 272234285Sdim MVT LocVT, CCValAssign::LocInfo LocInfo, 273234285Sdim ISD::ArgFlagsTy ArgFlags, CCState &State) { 274245431Sdim if (LocVT == MVT::i64 || LocVT == MVT::f64) { 275234285Sdim if (unsigned Reg = State.AllocateReg(Hexagon::D0)) { 276234285Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 277234285Sdim return false; 278234285Sdim } 279234285Sdim } 280234285Sdim 281234285Sdim unsigned Offset = State.AllocateStack(8, 8); 282234285Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 283234285Sdim return false; 284234285Sdim} 285234285Sdim 286234285SdimSDValue 287234285SdimHexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) 288234285Sdimconst { 289234285Sdim return SDValue(); 290234285Sdim} 291234285Sdim 292234285Sdim/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified 293234285Sdim/// by "Src" to address "Dst" of size "Size". Alignment information is 294234285Sdim/// specified by the specific parameter attribute. The copy will be passed as 295234285Sdim/// a byval function parameter. Sometimes what we are copying is the end of a 296234285Sdim/// larger object, the part that does not fit in registers. 297234285Sdimstatic SDValue 298234285SdimCreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, 299234285Sdim ISD::ArgFlagsTy Flags, SelectionDAG &DAG, 300263509Sdim SDLoc dl) { 301234285Sdim 302234285Sdim SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); 303234285Sdim return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), 304234285Sdim /*isVolatile=*/false, /*AlwaysInline=*/false, 305234285Sdim MachinePointerInfo(), MachinePointerInfo()); 306234285Sdim} 307234285Sdim 308234285Sdim 309234285Sdim// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is 310234285Sdim// passed by value, the function prototype is modified to return void and 311234285Sdim// the value is stored in memory pointed by a pointer passed by caller. 312234285SdimSDValue 313234285SdimHexagonTargetLowering::LowerReturn(SDValue Chain, 314234285Sdim CallingConv::ID CallConv, bool isVarArg, 315234285Sdim const SmallVectorImpl<ISD::OutputArg> &Outs, 316234285Sdim const SmallVectorImpl<SDValue> &OutVals, 317263509Sdim SDLoc dl, SelectionDAG &DAG) const { 318234285Sdim 319234285Sdim // CCValAssign - represent the assignment of the return value to locations. 320234285Sdim SmallVector<CCValAssign, 16> RVLocs; 321234285Sdim 322234285Sdim // CCState - Info about the registers and stack slot. 323234285Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 324245431Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 325234285Sdim 326234285Sdim // Analyze return values of ISD::RET 327234285Sdim CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon); 328234285Sdim 329252723Sdim SDValue Flag; 330252723Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 331234285Sdim 332234285Sdim // Copy the result values into the output registers. 333234285Sdim for (unsigned i = 0; i != RVLocs.size(); ++i) { 334234285Sdim CCValAssign &VA = RVLocs[i]; 335234285Sdim 336234285Sdim Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); 337234285Sdim 338234285Sdim // Guarantee that all emitted copies are stuck together with flags. 339234285Sdim Flag = Chain.getValue(1); 340252723Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 341234285Sdim } 342234285Sdim 343252723Sdim RetOps[0] = Chain; // Update chain. 344252723Sdim 345252723Sdim // Add the flag if we have it. 346234285Sdim if (Flag.getNode()) 347252723Sdim RetOps.push_back(Flag); 348234285Sdim 349252723Sdim return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, 350252723Sdim &RetOps[0], RetOps.size()); 351234285Sdim} 352234285Sdim 353234285Sdim 354234285Sdim 355234285Sdim 356234285Sdim/// LowerCallResult - Lower the result values of an ISD::CALL into the 357234285Sdim/// appropriate copies out of appropriate physical registers. This assumes that 358234285Sdim/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call 359234285Sdim/// being lowered. Returns a SDNode with the same number of values as the 360234285Sdim/// ISD::CALL. 361234285SdimSDValue 362234285SdimHexagonTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, 363234285Sdim CallingConv::ID CallConv, bool isVarArg, 364234285Sdim const 365234285Sdim SmallVectorImpl<ISD::InputArg> &Ins, 366263509Sdim SDLoc dl, SelectionDAG &DAG, 367234285Sdim SmallVectorImpl<SDValue> &InVals, 368234285Sdim const SmallVectorImpl<SDValue> &OutVals, 369234285Sdim SDValue Callee) const { 370234285Sdim 371234285Sdim // Assign locations to each value returned by this call. 372234285Sdim SmallVector<CCValAssign, 16> RVLocs; 373234285Sdim 374234285Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 375245431Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 376234285Sdim 377234285Sdim CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon); 378234285Sdim 379234285Sdim // Copy all of the result registers out of their specified physreg. 380234285Sdim for (unsigned i = 0; i != RVLocs.size(); ++i) { 381234285Sdim Chain = DAG.getCopyFromReg(Chain, dl, 382234285Sdim RVLocs[i].getLocReg(), 383234285Sdim RVLocs[i].getValVT(), InFlag).getValue(1); 384234285Sdim InFlag = Chain.getValue(2); 385234285Sdim InVals.push_back(Chain.getValue(0)); 386234285Sdim } 387234285Sdim 388234285Sdim return Chain; 389234285Sdim} 390234285Sdim 391234285Sdim/// LowerCall - Functions arguments are copied from virtual regs to 392234285Sdim/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. 393234285SdimSDValue 394245431SdimHexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 395234285Sdim SmallVectorImpl<SDValue> &InVals) const { 396245431Sdim SelectionDAG &DAG = CLI.DAG; 397263509Sdim SDLoc &dl = CLI.DL; 398263509Sdim SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 399263509Sdim SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 400263509Sdim SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 401245431Sdim SDValue Chain = CLI.Chain; 402245431Sdim SDValue Callee = CLI.Callee; 403245431Sdim bool &isTailCall = CLI.IsTailCall; 404245431Sdim CallingConv::ID CallConv = CLI.CallConv; 405245431Sdim bool isVarArg = CLI.IsVarArg; 406234285Sdim 407234285Sdim bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet(); 408234285Sdim 409234285Sdim // Check for varargs. 410263509Sdim int NumNamedVarArgParams = -1; 411234285Sdim if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Callee)) 412234285Sdim { 413234285Sdim const Function* CalleeFn = NULL; 414234285Sdim Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, MVT::i32); 415234285Sdim if ((CalleeFn = dyn_cast<Function>(GA->getGlobal()))) 416234285Sdim { 417234285Sdim // If a function has zero args and is a vararg function, that's 418234285Sdim // disallowed so it must be an undeclared function. Do not assume 419234285Sdim // varargs if the callee is undefined. 420234285Sdim if (CalleeFn->isVarArg() && 421234285Sdim CalleeFn->getFunctionType()->getNumParams() != 0) { 422234285Sdim NumNamedVarArgParams = CalleeFn->getFunctionType()->getNumParams(); 423234285Sdim } 424234285Sdim } 425234285Sdim } 426234285Sdim 427263509Sdim // Analyze operands of the call, assigning locations to each operand. 428263509Sdim SmallVector<CCValAssign, 16> ArgLocs; 429263509Sdim HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 430263509Sdim getTargetMachine(), ArgLocs, *DAG.getContext(), 431263509Sdim NumNamedVarArgParams); 432263509Sdim 433234285Sdim if (NumNamedVarArgParams > 0) 434234285Sdim CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg); 435234285Sdim else 436234285Sdim CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon); 437234285Sdim 438234285Sdim 439234285Sdim if(isTailCall) { 440234285Sdim bool StructAttrFlag = 441234285Sdim DAG.getMachineFunction().getFunction()->hasStructRetAttr(); 442234285Sdim isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, 443234285Sdim isVarArg, IsStructRet, 444234285Sdim StructAttrFlag, 445234285Sdim Outs, OutVals, Ins, DAG); 446234285Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i){ 447234285Sdim CCValAssign &VA = ArgLocs[i]; 448234285Sdim if (VA.isMemLoc()) { 449234285Sdim isTailCall = false; 450234285Sdim break; 451234285Sdim } 452234285Sdim } 453234285Sdim if (isTailCall) { 454234285Sdim DEBUG(dbgs () << "Eligible for Tail Call\n"); 455234285Sdim } else { 456234285Sdim DEBUG(dbgs () << 457234285Sdim "Argument must be passed on stack. Not eligible for Tail Call\n"); 458234285Sdim } 459234285Sdim } 460234285Sdim // Get a count of how many bytes are to be pushed on the stack. 461234285Sdim unsigned NumBytes = CCInfo.getNextStackOffset(); 462234285Sdim SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass; 463234285Sdim SmallVector<SDValue, 8> MemOpChains; 464234285Sdim 465234285Sdim SDValue StackPtr = 466234285Sdim DAG.getCopyFromReg(Chain, dl, TM.getRegisterInfo()->getStackRegister(), 467234285Sdim getPointerTy()); 468234285Sdim 469234285Sdim // Walk the register/memloc assignments, inserting copies/loads. 470234285Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 471234285Sdim CCValAssign &VA = ArgLocs[i]; 472234285Sdim SDValue Arg = OutVals[i]; 473234285Sdim ISD::ArgFlagsTy Flags = Outs[i].Flags; 474234285Sdim 475234285Sdim // Promote the value if needed. 476234285Sdim switch (VA.getLocInfo()) { 477234285Sdim default: 478234285Sdim // Loc info must be one of Full, SExt, ZExt, or AExt. 479234285Sdim llvm_unreachable("Unknown loc info!"); 480234285Sdim case CCValAssign::Full: 481234285Sdim break; 482234285Sdim case CCValAssign::SExt: 483234285Sdim Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 484234285Sdim break; 485234285Sdim case CCValAssign::ZExt: 486234285Sdim Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 487234285Sdim break; 488234285Sdim case CCValAssign::AExt: 489234285Sdim Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 490234285Sdim break; 491234285Sdim } 492234285Sdim 493234285Sdim if (VA.isMemLoc()) { 494234285Sdim unsigned LocMemOffset = VA.getLocMemOffset(); 495234285Sdim SDValue PtrOff = DAG.getConstant(LocMemOffset, StackPtr.getValueType()); 496234285Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 497234285Sdim 498234285Sdim if (Flags.isByVal()) { 499234285Sdim // The argument is a struct passed by value. According to LLVM, "Arg" 500234285Sdim // is is pointer. 501234285Sdim MemOpChains.push_back(CreateCopyOfByValArgument(Arg, PtrOff, Chain, 502234285Sdim Flags, DAG, dl)); 503234285Sdim } else { 504234285Sdim // The argument is not passed by value. "Arg" is a buildin type. It is 505234285Sdim // not a pointer. 506234285Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, 507234285Sdim MachinePointerInfo(),false, false, 508234285Sdim 0)); 509234285Sdim } 510234285Sdim continue; 511234285Sdim } 512234285Sdim 513234285Sdim // Arguments that can be passed on register must be kept at RegsToPass 514234285Sdim // vector. 515234285Sdim if (VA.isRegLoc()) { 516234285Sdim RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 517234285Sdim } 518234285Sdim } 519234285Sdim 520234285Sdim // Transform all store nodes into one single node because all store 521234285Sdim // nodes are independent of each other. 522234285Sdim if (!MemOpChains.empty()) { 523234285Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], 524234285Sdim MemOpChains.size()); 525234285Sdim } 526234285Sdim 527234285Sdim if (!isTailCall) 528234285Sdim Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes, 529263509Sdim getPointerTy(), true), 530263509Sdim dl); 531234285Sdim 532234285Sdim // Build a sequence of copy-to-reg nodes chained together with token 533234285Sdim // chain and flag operands which copy the outgoing args into registers. 534245431Sdim // The InFlag in necessary since all emitted instructions must be 535234285Sdim // stuck together. 536234285Sdim SDValue InFlag; 537234285Sdim if (!isTailCall) { 538234285Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 539234285Sdim Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 540234285Sdim RegsToPass[i].second, InFlag); 541234285Sdim InFlag = Chain.getValue(1); 542234285Sdim } 543234285Sdim } 544234285Sdim 545234285Sdim // For tail calls lower the arguments to the 'real' stack slot. 546234285Sdim if (isTailCall) { 547234285Sdim // Force all the incoming stack arguments to be loaded from the stack 548234285Sdim // before any new outgoing arguments are stored to the stack, because the 549234285Sdim // outgoing stack slots may alias the incoming argument stack slots, and 550234285Sdim // the alias isn't otherwise explicit. This is slightly more conservative 551234285Sdim // than necessary, because it means that each store effectively depends 552234285Sdim // on every argument instead of just those arguments it would clobber. 553234285Sdim // 554245431Sdim // Do not flag preceding copytoreg stuff together with the following stuff. 555234285Sdim InFlag = SDValue(); 556234285Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 557234285Sdim Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 558234285Sdim RegsToPass[i].second, InFlag); 559234285Sdim InFlag = Chain.getValue(1); 560234285Sdim } 561234285Sdim InFlag =SDValue(); 562234285Sdim } 563234285Sdim 564234285Sdim // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every 565234285Sdim // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol 566234285Sdim // node so that legalize doesn't hack it. 567234285Sdim if (flag_aligned_memcpy) { 568234285Sdim const char *MemcpyName = 569234285Sdim "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes"; 570234285Sdim Callee = 571234285Sdim DAG.getTargetExternalSymbol(MemcpyName, getPointerTy()); 572234285Sdim flag_aligned_memcpy = false; 573234285Sdim } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { 574234285Sdim Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy()); 575234285Sdim } else if (ExternalSymbolSDNode *S = 576234285Sdim dyn_cast<ExternalSymbolSDNode>(Callee)) { 577234285Sdim Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); 578234285Sdim } 579234285Sdim 580234285Sdim // Returns a chain & a flag for retval copy to use. 581234285Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 582234285Sdim SmallVector<SDValue, 8> Ops; 583234285Sdim Ops.push_back(Chain); 584234285Sdim Ops.push_back(Callee); 585234285Sdim 586234285Sdim // Add argument registers to the end of the list so that they are 587234285Sdim // known live into the call. 588234285Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 589234285Sdim Ops.push_back(DAG.getRegister(RegsToPass[i].first, 590234285Sdim RegsToPass[i].second.getValueType())); 591234285Sdim } 592234285Sdim 593234285Sdim if (InFlag.getNode()) { 594234285Sdim Ops.push_back(InFlag); 595234285Sdim } 596234285Sdim 597234285Sdim if (isTailCall) 598234285Sdim return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, &Ops[0], Ops.size()); 599234285Sdim 600234285Sdim Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); 601234285Sdim InFlag = Chain.getValue(1); 602234285Sdim 603234285Sdim // Create the CALLSEQ_END node. 604234285Sdim Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), 605263509Sdim DAG.getIntPtrConstant(0, true), InFlag, dl); 606234285Sdim InFlag = Chain.getValue(1); 607234285Sdim 608234285Sdim // Handle result values, copying them out of physregs into vregs that we 609234285Sdim // return. 610234285Sdim return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG, 611234285Sdim InVals, OutVals, Callee); 612234285Sdim} 613234285Sdim 614234285Sdimstatic bool getIndexedAddressParts(SDNode *Ptr, EVT VT, 615234285Sdim bool isSEXTLoad, SDValue &Base, 616234285Sdim SDValue &Offset, bool &isInc, 617234285Sdim SelectionDAG &DAG) { 618234285Sdim if (Ptr->getOpcode() != ISD::ADD) 619234285Sdim return false; 620234285Sdim 621234285Sdim if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { 622234285Sdim isInc = (Ptr->getOpcode() == ISD::ADD); 623234285Sdim Base = Ptr->getOperand(0); 624234285Sdim Offset = Ptr->getOperand(1); 625234285Sdim // Ensure that Offset is a constant. 626234285Sdim return (isa<ConstantSDNode>(Offset)); 627234285Sdim } 628234285Sdim 629234285Sdim return false; 630234285Sdim} 631234285Sdim 632234285Sdim// TODO: Put this function along with the other isS* functions in 633234285Sdim// HexagonISelDAGToDAG.cpp into a common file. Or better still, use the 634252723Sdim// functions defined in HexagonOperands.td. 635234285Sdimstatic bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) { 636234285Sdim ConstantSDNode *N = cast<ConstantSDNode>(S); 637234285Sdim 638234285Sdim // immS4 predicate - True if the immediate fits in a 4-bit sign extended. 639234285Sdim // field. 640234285Sdim int64_t v = (int64_t)N->getSExtValue(); 641234285Sdim int64_t m = 0; 642234285Sdim if (ShiftAmount > 0) { 643234285Sdim m = v % ShiftAmount; 644234285Sdim v = v >> ShiftAmount; 645234285Sdim } 646234285Sdim return (v <= 7) && (v >= -8) && (m == 0); 647234285Sdim} 648234285Sdim 649234285Sdim/// getPostIndexedAddressParts - returns true by value, base pointer and 650234285Sdim/// offset pointer and addressing mode by reference if this node can be 651234285Sdim/// combined with a load / store to form a post-indexed load / store. 652234285Sdimbool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, 653234285Sdim SDValue &Base, 654234285Sdim SDValue &Offset, 655234285Sdim ISD::MemIndexedMode &AM, 656234285Sdim SelectionDAG &DAG) const 657234285Sdim{ 658234285Sdim EVT VT; 659234285Sdim SDValue Ptr; 660234285Sdim bool isSEXTLoad = false; 661234285Sdim 662234285Sdim if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { 663234285Sdim VT = LD->getMemoryVT(); 664234285Sdim isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; 665234285Sdim } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { 666234285Sdim VT = ST->getMemoryVT(); 667234285Sdim if (ST->getValue().getValueType() == MVT::i64 && ST->isTruncatingStore()) { 668234285Sdim return false; 669234285Sdim } 670234285Sdim } else { 671234285Sdim return false; 672234285Sdim } 673234285Sdim 674234285Sdim bool isInc = false; 675234285Sdim bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, 676234285Sdim isInc, DAG); 677234285Sdim // ShiftAmount = number of left-shifted bits in the Hexagon instruction. 678234285Sdim int ShiftAmount = VT.getSizeInBits() / 16; 679234285Sdim if (isLegal && Is_PostInc_S4_Offset(Offset.getNode(), ShiftAmount)) { 680234285Sdim AM = isInc ? ISD::POST_INC : ISD::POST_DEC; 681234285Sdim return true; 682234285Sdim } 683234285Sdim 684234285Sdim return false; 685234285Sdim} 686234285Sdim 687234285SdimSDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op, 688234285Sdim SelectionDAG &DAG) const { 689234285Sdim SDNode *Node = Op.getNode(); 690234285Sdim MachineFunction &MF = DAG.getMachineFunction(); 691234285Sdim HexagonMachineFunctionInfo *FuncInfo = 692234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 693234285Sdim switch (Node->getOpcode()) { 694234285Sdim case ISD::INLINEASM: { 695234285Sdim unsigned NumOps = Node->getNumOperands(); 696234285Sdim if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) 697234285Sdim --NumOps; // Ignore the flag operand. 698234285Sdim 699234285Sdim for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { 700234285Sdim if (FuncInfo->hasClobberLR()) 701234285Sdim break; 702234285Sdim unsigned Flags = 703234285Sdim cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue(); 704234285Sdim unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); 705234285Sdim ++i; // Skip the ID value. 706234285Sdim 707234285Sdim switch (InlineAsm::getKind(Flags)) { 708234285Sdim default: llvm_unreachable("Bad flags!"); 709234285Sdim case InlineAsm::Kind_RegDef: 710234285Sdim case InlineAsm::Kind_RegUse: 711234285Sdim case InlineAsm::Kind_Imm: 712234285Sdim case InlineAsm::Kind_Clobber: 713234285Sdim case InlineAsm::Kind_Mem: { 714234285Sdim for (; NumVals; --NumVals, ++i) {} 715234285Sdim break; 716234285Sdim } 717234285Sdim case InlineAsm::Kind_RegDefEarlyClobber: { 718234285Sdim for (; NumVals; --NumVals, ++i) { 719234285Sdim unsigned Reg = 720234285Sdim cast<RegisterSDNode>(Node->getOperand(i))->getReg(); 721234285Sdim 722234285Sdim // Check it to be lr 723234285Sdim if (Reg == TM.getRegisterInfo()->getRARegister()) { 724234285Sdim FuncInfo->setHasClobberLR(true); 725234285Sdim break; 726234285Sdim } 727234285Sdim } 728234285Sdim break; 729234285Sdim } 730234285Sdim } 731234285Sdim } 732234285Sdim } 733234285Sdim } // Node->getOpcode 734234285Sdim return Op; 735234285Sdim} 736234285Sdim 737234285Sdim 738234285Sdim// 739234285Sdim// Taken from the XCore backend. 740234285Sdim// 741234285SdimSDValue HexagonTargetLowering:: 742234285SdimLowerBR_JT(SDValue Op, SelectionDAG &DAG) const 743234285Sdim{ 744234285Sdim SDValue Chain = Op.getOperand(0); 745234285Sdim SDValue Table = Op.getOperand(1); 746234285Sdim SDValue Index = Op.getOperand(2); 747263509Sdim SDLoc dl(Op); 748234285Sdim JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); 749234285Sdim unsigned JTI = JT->getIndex(); 750234285Sdim MachineFunction &MF = DAG.getMachineFunction(); 751234285Sdim const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); 752234285Sdim SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); 753234285Sdim 754234285Sdim // Mark all jump table targets as address taken. 755234285Sdim const std::vector<MachineJumpTableEntry> &JTE = MJTI->getJumpTables(); 756234285Sdim const std::vector<MachineBasicBlock*> &JTBBs = JTE[JTI].MBBs; 757234285Sdim for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { 758234285Sdim MachineBasicBlock *MBB = JTBBs[i]; 759234285Sdim MBB->setHasAddressTaken(); 760234285Sdim // This line is needed to set the hasAddressTaken flag on the BasicBlock 761234285Sdim // object. 762234285Sdim BlockAddress::get(const_cast<BasicBlock *>(MBB->getBasicBlock())); 763234285Sdim } 764234285Sdim 765234285Sdim SDValue JumpTableBase = DAG.getNode(HexagonISD::WrapperJT, dl, 766234285Sdim getPointerTy(), TargetJT); 767234285Sdim SDValue ShiftIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, 768234285Sdim DAG.getConstant(2, MVT::i32)); 769234285Sdim SDValue JTAddress = DAG.getNode(ISD::ADD, dl, MVT::i32, JumpTableBase, 770234285Sdim ShiftIndex); 771234285Sdim SDValue LoadTarget = DAG.getLoad(MVT::i32, dl, Chain, JTAddress, 772234285Sdim MachinePointerInfo(), false, false, false, 773234285Sdim 0); 774234285Sdim return DAG.getNode(HexagonISD::BR_JT, dl, MVT::Other, Chain, LoadTarget); 775234285Sdim} 776234285Sdim 777234285Sdim 778234285SdimSDValue 779234285SdimHexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, 780234285Sdim SelectionDAG &DAG) const { 781234285Sdim SDValue Chain = Op.getOperand(0); 782234285Sdim SDValue Size = Op.getOperand(1); 783263509Sdim SDLoc dl(Op); 784234285Sdim 785234285Sdim unsigned SPReg = getStackPointerRegisterToSaveRestore(); 786234285Sdim 787234285Sdim // Get a reference to the stack pointer. 788234285Sdim SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32); 789234285Sdim 790234285Sdim // Subtract the dynamic size from the actual stack size to 791234285Sdim // obtain the new stack size. 792234285Sdim SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size); 793234285Sdim 794234285Sdim // 795234285Sdim // For Hexagon, the outgoing memory arguments area should be on top of the 796234285Sdim // alloca area on the stack i.e., the outgoing memory arguments should be 797234285Sdim // at a lower address than the alloca area. Move the alloca area down the 798234285Sdim // stack by adding back the space reserved for outgoing arguments to SP 799234285Sdim // here. 800234285Sdim // 801234285Sdim // We do not know what the size of the outgoing args is at this point. 802234285Sdim // So, we add a pseudo instruction ADJDYNALLOC that will adjust the 803234285Sdim // stack pointer. We patch this instruction with the correct, known 804234285Sdim // offset in emitPrologue(). 805234285Sdim // 806234285Sdim // Use a placeholder immediate (zero) for now. This will be patched up 807234285Sdim // by emitPrologue(). 808234285Sdim SDValue ArgAdjust = DAG.getNode(HexagonISD::ADJDYNALLOC, dl, 809234285Sdim MVT::i32, 810234285Sdim Sub, 811234285Sdim DAG.getConstant(0, MVT::i32)); 812234285Sdim 813234285Sdim // The Sub result contains the new stack start address, so it 814234285Sdim // must be placed in the stack pointer register. 815234285Sdim SDValue CopyChain = DAG.getCopyToReg(Chain, dl, 816234285Sdim TM.getRegisterInfo()->getStackRegister(), 817234285Sdim Sub); 818234285Sdim 819234285Sdim SDValue Ops[2] = { ArgAdjust, CopyChain }; 820234285Sdim return DAG.getMergeValues(Ops, 2, dl); 821234285Sdim} 822234285Sdim 823234285SdimSDValue 824234285SdimHexagonTargetLowering::LowerFormalArguments(SDValue Chain, 825234285Sdim CallingConv::ID CallConv, 826234285Sdim bool isVarArg, 827234285Sdim const 828234285Sdim SmallVectorImpl<ISD::InputArg> &Ins, 829263509Sdim SDLoc dl, SelectionDAG &DAG, 830234285Sdim SmallVectorImpl<SDValue> &InVals) 831234285Sdimconst { 832234285Sdim 833234285Sdim MachineFunction &MF = DAG.getMachineFunction(); 834234285Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 835234285Sdim MachineRegisterInfo &RegInfo = MF.getRegInfo(); 836234285Sdim HexagonMachineFunctionInfo *FuncInfo = 837234285Sdim MF.getInfo<HexagonMachineFunctionInfo>(); 838234285Sdim 839234285Sdim 840234285Sdim // Assign locations to all of the incoming arguments. 841234285Sdim SmallVector<CCValAssign, 16> ArgLocs; 842234285Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 843245431Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 844234285Sdim 845234285Sdim CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon); 846234285Sdim 847234285Sdim // For LLVM, in the case when returning a struct by value (>8byte), 848234285Sdim // the first argument is a pointer that points to the location on caller's 849234285Sdim // stack where the return value will be stored. For Hexagon, the location on 850234285Sdim // caller's stack is passed only when the struct size is smaller than (and 851234285Sdim // equal to) 8 bytes. If not, no address will be passed into callee and 852234285Sdim // callee return the result direclty through R0/R1. 853234285Sdim 854234285Sdim SmallVector<SDValue, 4> MemOps; 855234285Sdim 856234285Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 857234285Sdim CCValAssign &VA = ArgLocs[i]; 858234285Sdim ISD::ArgFlagsTy Flags = Ins[i].Flags; 859234285Sdim unsigned ObjSize; 860234285Sdim unsigned StackLocation; 861234285Sdim int FI; 862234285Sdim 863234285Sdim if ( (VA.isRegLoc() && !Flags.isByVal()) 864234285Sdim || (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) { 865234285Sdim // Arguments passed in registers 866234285Sdim // 1. int, long long, ptr args that get allocated in register. 867234285Sdim // 2. Large struct that gets an register to put its address in. 868234285Sdim EVT RegVT = VA.getLocVT(); 869245431Sdim if (RegVT == MVT::i8 || RegVT == MVT::i16 || 870245431Sdim RegVT == MVT::i32 || RegVT == MVT::f32) { 871234285Sdim unsigned VReg = 872245431Sdim RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass); 873234285Sdim RegInfo.addLiveIn(VA.getLocReg(), VReg); 874234285Sdim InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); 875234285Sdim } else if (RegVT == MVT::i64) { 876234285Sdim unsigned VReg = 877245431Sdim RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass); 878234285Sdim RegInfo.addLiveIn(VA.getLocReg(), VReg); 879234285Sdim InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); 880234285Sdim } else { 881234285Sdim assert (0); 882234285Sdim } 883234285Sdim } else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) { 884234285Sdim assert (0 && "ByValSize must be bigger than 8 bytes"); 885234285Sdim } else { 886234285Sdim // Sanity check. 887234285Sdim assert(VA.isMemLoc()); 888234285Sdim 889234285Sdim if (Flags.isByVal()) { 890234285Sdim // If it's a byval parameter, then we need to compute the 891234285Sdim // "real" size, not the size of the pointer. 892234285Sdim ObjSize = Flags.getByValSize(); 893234285Sdim } else { 894234285Sdim ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3; 895234285Sdim } 896234285Sdim 897234285Sdim StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset(); 898234285Sdim // Create the frame index object for this incoming parameter... 899234285Sdim FI = MFI->CreateFixedObject(ObjSize, StackLocation, true); 900234285Sdim 901234285Sdim // Create the SelectionDAG nodes cordl, responding to a load 902234285Sdim // from this parameter. 903234285Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 904234285Sdim 905234285Sdim if (Flags.isByVal()) { 906234285Sdim // If it's a pass-by-value aggregate, then do not dereference the stack 907234285Sdim // location. Instead, we should generate a reference to the stack 908234285Sdim // location. 909234285Sdim InVals.push_back(FIN); 910234285Sdim } else { 911234285Sdim InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 912234285Sdim MachinePointerInfo(), false, false, 913234285Sdim false, 0)); 914234285Sdim } 915234285Sdim } 916234285Sdim } 917234285Sdim 918234285Sdim if (!MemOps.empty()) 919234285Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0], 920234285Sdim MemOps.size()); 921234285Sdim 922234285Sdim if (isVarArg) { 923234285Sdim // This will point to the next argument passed via stack. 924234285Sdim int FrameIndex = MFI->CreateFixedObject(Hexagon_PointerSize, 925234285Sdim HEXAGON_LRFP_SIZE + 926234285Sdim CCInfo.getNextStackOffset(), 927234285Sdim true); 928234285Sdim FuncInfo->setVarArgsFrameIndex(FrameIndex); 929234285Sdim } 930234285Sdim 931234285Sdim return Chain; 932234285Sdim} 933234285Sdim 934234285SdimSDValue 935234285SdimHexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { 936234285Sdim // VASTART stores the address of the VarArgsFrameIndex slot into the 937234285Sdim // memory location argument. 938234285Sdim MachineFunction &MF = DAG.getMachineFunction(); 939234285Sdim HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>(); 940234285Sdim SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32); 941234285Sdim const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 942263509Sdim return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr, 943234285Sdim Op.getOperand(1), MachinePointerInfo(SV), false, 944234285Sdim false, 0); 945234285Sdim} 946234285Sdim 947234285SdimSDValue 948234285SdimHexagonTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { 949245431Sdim SDValue LHS = Op.getOperand(0); 950245431Sdim SDValue RHS = Op.getOperand(1); 951245431Sdim SDValue CC = Op.getOperand(4); 952245431Sdim SDValue TrueVal = Op.getOperand(2); 953245431Sdim SDValue FalseVal = Op.getOperand(3); 954263509Sdim SDLoc dl(Op); 955234285Sdim SDNode* OpNode = Op.getNode(); 956245431Sdim EVT SVT = OpNode->getValueType(0); 957234285Sdim 958245431Sdim SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i1, LHS, RHS, CC); 959245431Sdim return DAG.getNode(ISD::SELECT, dl, SVT, Cond, TrueVal, FalseVal); 960234285Sdim} 961234285Sdim 962234285SdimSDValue 963245431SdimHexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { 964245431Sdim EVT ValTy = Op.getValueType(); 965263509Sdim SDLoc dl(Op); 966245431Sdim ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); 967245431Sdim SDValue Res; 968245431Sdim if (CP->isMachineConstantPoolEntry()) 969245431Sdim Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), ValTy, 970245431Sdim CP->getAlignment()); 971245431Sdim else 972245431Sdim Res = DAG.getTargetConstantPool(CP->getConstVal(), ValTy, 973245431Sdim CP->getAlignment()); 974245431Sdim return DAG.getNode(HexagonISD::CONST32, dl, ValTy, Res); 975245431Sdim} 976245431Sdim 977245431SdimSDValue 978234285SdimHexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { 979234285Sdim const TargetRegisterInfo *TRI = TM.getRegisterInfo(); 980234285Sdim MachineFunction &MF = DAG.getMachineFunction(); 981234285Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 982234285Sdim MFI->setReturnAddressIsTaken(true); 983234285Sdim 984234285Sdim EVT VT = Op.getValueType(); 985263509Sdim SDLoc dl(Op); 986234285Sdim unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 987234285Sdim if (Depth) { 988234285Sdim SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); 989234285Sdim SDValue Offset = DAG.getConstant(4, MVT::i32); 990234285Sdim return DAG.getLoad(VT, dl, DAG.getEntryNode(), 991234285Sdim DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset), 992234285Sdim MachinePointerInfo(), false, false, false, 0); 993234285Sdim } 994234285Sdim 995234285Sdim // Return LR, which contains the return address. Mark it an implicit live-in. 996234285Sdim unsigned Reg = MF.addLiveIn(TRI->getRARegister(), getRegClassFor(MVT::i32)); 997234285Sdim return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); 998234285Sdim} 999234285Sdim 1000234285SdimSDValue 1001234285SdimHexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { 1002234285Sdim const HexagonRegisterInfo *TRI = TM.getRegisterInfo(); 1003234285Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 1004234285Sdim MFI->setFrameAddressIsTaken(true); 1005234285Sdim 1006234285Sdim EVT VT = Op.getValueType(); 1007263509Sdim SDLoc dl(Op); 1008234285Sdim unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 1009234285Sdim SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, 1010234285Sdim TRI->getFrameRegister(), VT); 1011234285Sdim while (Depth--) 1012234285Sdim FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, 1013234285Sdim MachinePointerInfo(), 1014234285Sdim false, false, false, 0); 1015234285Sdim return FrameAddr; 1016234285Sdim} 1017234285Sdim 1018234285SdimSDValue HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op, 1019234285Sdim SelectionDAG& DAG) const { 1020263509Sdim SDLoc dl(Op); 1021234285Sdim return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0)); 1022234285Sdim} 1023234285Sdim 1024234285Sdim 1025234285SdimSDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, 1026234285Sdim SelectionDAG &DAG) const { 1027234285Sdim SDValue Result; 1028234285Sdim const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 1029234285Sdim int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); 1030263509Sdim SDLoc dl(Op); 1031234285Sdim Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset); 1032234285Sdim 1033252723Sdim const HexagonTargetObjectFile &TLOF = 1034252723Sdim static_cast<const HexagonTargetObjectFile &>(getObjFileLowering()); 1035234285Sdim if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { 1036234285Sdim return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result); 1037234285Sdim } 1038234285Sdim 1039234285Sdim return DAG.getNode(HexagonISD::CONST32, dl, getPointerTy(), Result); 1040234285Sdim} 1041234285Sdim 1042252723SdimSDValue 1043252723SdimHexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { 1044252723Sdim const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 1045252723Sdim SDValue BA_SD = DAG.getTargetBlockAddress(BA, MVT::i32); 1046263509Sdim SDLoc dl(Op); 1047252723Sdim return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), BA_SD); 1048252723Sdim} 1049252723Sdim 1050234285Sdim//===----------------------------------------------------------------------===// 1051234285Sdim// TargetLowering Implementation 1052234285Sdim//===----------------------------------------------------------------------===// 1053234285Sdim 1054234285SdimHexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine 1055234285Sdim &targetmachine) 1056234285Sdim : TargetLowering(targetmachine, new HexagonTargetObjectFile()), 1057234285Sdim TM(targetmachine) { 1058234285Sdim 1059245431Sdim const HexagonRegisterInfo* QRI = TM.getRegisterInfo(); 1060245431Sdim 1061234285Sdim // Set up the register classes. 1062245431Sdim addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass); 1063245431Sdim addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass); 1064234285Sdim 1065245431Sdim if (QRI->Subtarget.hasV5TOps()) { 1066245431Sdim addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass); 1067245431Sdim addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass); 1068245431Sdim } 1069234285Sdim 1070245431Sdim addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass); 1071245431Sdim 1072234285Sdim computeRegisterProperties(); 1073234285Sdim 1074234285Sdim // Align loop entry 1075234285Sdim setPrefLoopAlignment(4); 1076234285Sdim 1077234285Sdim // Limits for inline expansion of memcpy/memmove 1078252723Sdim MaxStoresPerMemcpy = 6; 1079252723Sdim MaxStoresPerMemmove = 6; 1080234285Sdim 1081234285Sdim // 1082234285Sdim // Library calls for unsupported operations 1083234285Sdim // 1084234285Sdim 1085234285Sdim setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf"); 1086234285Sdim setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf"); 1087234285Sdim 1088234285Sdim setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti"); 1089234285Sdim setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti"); 1090234285Sdim 1091234285Sdim setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti"); 1092234285Sdim setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti"); 1093234285Sdim 1094234285Sdim setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3"); 1095234285Sdim setOperationAction(ISD::SDIV, MVT::i32, Expand); 1096234285Sdim setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3"); 1097234285Sdim setOperationAction(ISD::SREM, MVT::i32, Expand); 1098234285Sdim 1099234285Sdim setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3"); 1100234285Sdim setOperationAction(ISD::SDIV, MVT::i64, Expand); 1101234285Sdim setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3"); 1102234285Sdim setOperationAction(ISD::SREM, MVT::i64, Expand); 1103234285Sdim 1104234285Sdim setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3"); 1105234285Sdim setOperationAction(ISD::UDIV, MVT::i32, Expand); 1106234285Sdim 1107234285Sdim setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3"); 1108234285Sdim setOperationAction(ISD::UDIV, MVT::i64, Expand); 1109234285Sdim 1110234285Sdim setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3"); 1111234285Sdim setOperationAction(ISD::UREM, MVT::i32, Expand); 1112234285Sdim 1113234285Sdim setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3"); 1114234285Sdim setOperationAction(ISD::UREM, MVT::i64, Expand); 1115234285Sdim 1116234285Sdim setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3"); 1117234285Sdim setOperationAction(ISD::FDIV, MVT::f32, Expand); 1118234285Sdim 1119234285Sdim setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3"); 1120234285Sdim setOperationAction(ISD::FDIV, MVT::f64, Expand); 1121234285Sdim 1122245431Sdim setOperationAction(ISD::FSQRT, MVT::f32, Expand); 1123245431Sdim setOperationAction(ISD::FSQRT, MVT::f64, Expand); 1124245431Sdim setOperationAction(ISD::FSIN, MVT::f32, Expand); 1125245431Sdim setOperationAction(ISD::FSIN, MVT::f64, Expand); 1126234285Sdim 1127245431Sdim if (QRI->Subtarget.hasV5TOps()) { 1128245431Sdim // Hexagon V5 Support. 1129245431Sdim setOperationAction(ISD::FADD, MVT::f32, Legal); 1130245431Sdim setOperationAction(ISD::FADD, MVT::f64, Legal); 1131245431Sdim setOperationAction(ISD::FP_EXTEND, MVT::f32, Legal); 1132245431Sdim setCondCodeAction(ISD::SETOEQ, MVT::f32, Legal); 1133245431Sdim setCondCodeAction(ISD::SETOEQ, MVT::f64, Legal); 1134245431Sdim setCondCodeAction(ISD::SETUEQ, MVT::f32, Legal); 1135245431Sdim setCondCodeAction(ISD::SETUEQ, MVT::f64, Legal); 1136234285Sdim 1137245431Sdim setCondCodeAction(ISD::SETOGE, MVT::f32, Legal); 1138245431Sdim setCondCodeAction(ISD::SETOGE, MVT::f64, Legal); 1139245431Sdim setCondCodeAction(ISD::SETUGE, MVT::f32, Legal); 1140245431Sdim setCondCodeAction(ISD::SETUGE, MVT::f64, Legal); 1141234285Sdim 1142245431Sdim setCondCodeAction(ISD::SETOGT, MVT::f32, Legal); 1143245431Sdim setCondCodeAction(ISD::SETOGT, MVT::f64, Legal); 1144245431Sdim setCondCodeAction(ISD::SETUGT, MVT::f32, Legal); 1145245431Sdim setCondCodeAction(ISD::SETUGT, MVT::f64, Legal); 1146234285Sdim 1147245431Sdim setCondCodeAction(ISD::SETOLE, MVT::f32, Legal); 1148245431Sdim setCondCodeAction(ISD::SETOLE, MVT::f64, Legal); 1149245431Sdim setCondCodeAction(ISD::SETOLT, MVT::f32, Legal); 1150245431Sdim setCondCodeAction(ISD::SETOLT, MVT::f64, Legal); 1151234285Sdim 1152245431Sdim setOperationAction(ISD::ConstantFP, MVT::f32, Legal); 1153245431Sdim setOperationAction(ISD::ConstantFP, MVT::f64, Legal); 1154234285Sdim 1155245431Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i1, Promote); 1156245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i1, Promote); 1157245431Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i1, Promote); 1158245431Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i1, Promote); 1159234285Sdim 1160245431Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote); 1161245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote); 1162245431Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote); 1163245431Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote); 1164234285Sdim 1165245431Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote); 1166245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote); 1167245431Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote); 1168245431Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote); 1169234285Sdim 1170245431Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal); 1171245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal); 1172245431Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal); 1173245431Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal); 1174234285Sdim 1175245431Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i64, Legal); 1176245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i64, Legal); 1177245431Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i64, Legal); 1178245431Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i64, Legal); 1179234285Sdim 1180245431Sdim setOperationAction(ISD::FABS, MVT::f32, Legal); 1181245431Sdim setOperationAction(ISD::FABS, MVT::f64, Expand); 1182234285Sdim 1183245431Sdim setOperationAction(ISD::FNEG, MVT::f32, Legal); 1184245431Sdim setOperationAction(ISD::FNEG, MVT::f64, Expand); 1185245431Sdim } else { 1186234285Sdim 1187245431Sdim // Expand fp<->uint. 1188245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand); 1189245431Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); 1190234285Sdim 1191245431Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); 1192245431Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); 1193234285Sdim 1194245431Sdim setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf"); 1195245431Sdim setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf"); 1196234285Sdim 1197245431Sdim setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf"); 1198245431Sdim setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf"); 1199234285Sdim 1200245431Sdim setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf"); 1201245431Sdim setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf"); 1202234285Sdim 1203245431Sdim setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf"); 1204245431Sdim setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf"); 1205234285Sdim 1206245431Sdim setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi"); 1207245431Sdim setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi"); 1208234285Sdim 1209245431Sdim setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi"); 1210245431Sdim setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi"); 1211234285Sdim 1212245431Sdim setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi"); 1213245431Sdim setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi"); 1214234285Sdim 1215245431Sdim setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3"); 1216245431Sdim setOperationAction(ISD::FADD, MVT::f64, Expand); 1217234285Sdim 1218245431Sdim setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3"); 1219245431Sdim setOperationAction(ISD::FADD, MVT::f32, Expand); 1220234285Sdim 1221245431Sdim setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2"); 1222245431Sdim setOperationAction(ISD::FP_EXTEND, MVT::f32, Expand); 1223234285Sdim 1224245431Sdim setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2"); 1225245431Sdim setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand); 1226234285Sdim 1227245431Sdim setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2"); 1228245431Sdim setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand); 1229234285Sdim 1230245431Sdim setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2"); 1231245431Sdim setCondCodeAction(ISD::SETOGE, MVT::f32, Expand); 1232234285Sdim 1233245431Sdim setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2"); 1234245431Sdim setCondCodeAction(ISD::SETOGE, MVT::f64, Expand); 1235234285Sdim 1236245431Sdim setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2"); 1237245431Sdim setCondCodeAction(ISD::SETOGT, MVT::f32, Expand); 1238234285Sdim 1239245431Sdim setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2"); 1240245431Sdim setCondCodeAction(ISD::SETOGT, MVT::f64, Expand); 1241245431Sdim 1242245431Sdim setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi"); 1243245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand); 1244245431Sdim 1245245431Sdim setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi"); 1246245431Sdim setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand); 1247245431Sdim 1248245431Sdim setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2"); 1249245431Sdim setCondCodeAction(ISD::SETOLE, MVT::f64, Expand); 1250245431Sdim 1251245431Sdim setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2"); 1252245431Sdim setCondCodeAction(ISD::SETOLE, MVT::f32, Expand); 1253245431Sdim 1254245431Sdim setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2"); 1255245431Sdim setCondCodeAction(ISD::SETOLT, MVT::f64, Expand); 1256245431Sdim 1257245431Sdim setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2"); 1258245431Sdim setCondCodeAction(ISD::SETOLT, MVT::f32, Expand); 1259245431Sdim 1260245431Sdim setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3"); 1261245431Sdim setOperationAction(ISD::FMUL, MVT::f64, Expand); 1262245431Sdim 1263245431Sdim setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3"); 1264245431Sdim setOperationAction(ISD::MUL, MVT::f32, Expand); 1265245431Sdim 1266245431Sdim setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2"); 1267245431Sdim setCondCodeAction(ISD::SETUNE, MVT::f64, Expand); 1268245431Sdim 1269245431Sdim setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2"); 1270245431Sdim 1271245431Sdim setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3"); 1272245431Sdim setOperationAction(ISD::SUB, MVT::f64, Expand); 1273245431Sdim 1274245431Sdim setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3"); 1275245431Sdim setOperationAction(ISD::SUB, MVT::f32, Expand); 1276245431Sdim 1277245431Sdim setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2"); 1278245431Sdim setOperationAction(ISD::FP_ROUND, MVT::f64, Expand); 1279245431Sdim 1280245431Sdim setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2"); 1281245431Sdim setCondCodeAction(ISD::SETUO, MVT::f64, Expand); 1282245431Sdim 1283245431Sdim setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2"); 1284245431Sdim setCondCodeAction(ISD::SETO, MVT::f64, Expand); 1285245431Sdim 1286245431Sdim setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2"); 1287245431Sdim setCondCodeAction(ISD::SETO, MVT::f32, Expand); 1288245431Sdim 1289245431Sdim setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2"); 1290245431Sdim setCondCodeAction(ISD::SETUO, MVT::f32, Expand); 1291245431Sdim 1292245431Sdim setOperationAction(ISD::FABS, MVT::f32, Expand); 1293245431Sdim setOperationAction(ISD::FABS, MVT::f64, Expand); 1294245431Sdim setOperationAction(ISD::FNEG, MVT::f32, Expand); 1295245431Sdim setOperationAction(ISD::FNEG, MVT::f64, Expand); 1296245431Sdim } 1297245431Sdim 1298245431Sdim setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3"); 1299245431Sdim setOperationAction(ISD::SREM, MVT::i32, Expand); 1300245431Sdim 1301234285Sdim setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); 1302234285Sdim setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); 1303234285Sdim setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal); 1304234285Sdim setIndexedLoadAction(ISD::POST_INC, MVT::i64, Legal); 1305234285Sdim 1306234285Sdim setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal); 1307234285Sdim setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal); 1308234285Sdim setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal); 1309234285Sdim setIndexedStoreAction(ISD::POST_INC, MVT::i64, Legal); 1310234285Sdim 1311234285Sdim setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); 1312234285Sdim 1313234285Sdim // Turn FP extload into load/fextend. 1314234285Sdim setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); 1315234285Sdim // Hexagon has a i1 sign extending load. 1316234285Sdim setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Expand); 1317234285Sdim // Turn FP truncstore into trunc + store. 1318234285Sdim setTruncStoreAction(MVT::f64, MVT::f32, Expand); 1319234285Sdim 1320234285Sdim // Custom legalize GlobalAddress nodes into CONST32. 1321234285Sdim setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 1322234285Sdim setOperationAction(ISD::GlobalAddress, MVT::i8, Custom); 1323252723Sdim setOperationAction(ISD::BlockAddress, MVT::i32, Custom); 1324234285Sdim // Truncate action? 1325234285Sdim setOperationAction(ISD::TRUNCATE, MVT::i64, Expand); 1326234285Sdim 1327234285Sdim // Hexagon doesn't have sext_inreg, replace them with shl/sra. 1328234285Sdim setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); 1329234285Sdim 1330234285Sdim // Hexagon has no REM or DIVREM operations. 1331234285Sdim setOperationAction(ISD::UREM, MVT::i32, Expand); 1332234285Sdim setOperationAction(ISD::SREM, MVT::i32, Expand); 1333234285Sdim setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 1334234285Sdim setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 1335234285Sdim setOperationAction(ISD::SREM, MVT::i64, Expand); 1336234285Sdim setOperationAction(ISD::SDIVREM, MVT::i64, Expand); 1337234285Sdim setOperationAction(ISD::UDIVREM, MVT::i64, Expand); 1338234285Sdim 1339234285Sdim setOperationAction(ISD::BSWAP, MVT::i64, Expand); 1340234285Sdim 1341234285Sdim // Lower SELECT_CC to SETCC and SELECT. 1342234285Sdim setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 1343234285Sdim setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); 1344234285Sdim 1345245431Sdim if (QRI->Subtarget.hasV5TOps()) { 1346245431Sdim 1347245431Sdim // We need to make the operation type of SELECT node to be Custom, 1348245431Sdim // such that we don't go into the infinite loop of 1349245431Sdim // select -> setcc -> select_cc -> select loop. 1350245431Sdim setOperationAction(ISD::SELECT, MVT::f32, Custom); 1351245431Sdim setOperationAction(ISD::SELECT, MVT::f64, Custom); 1352245431Sdim 1353245431Sdim setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); 1354245431Sdim setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); 1355245431Sdim setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); 1356245431Sdim 1357245431Sdim } else { 1358245431Sdim 1359245431Sdim // Hexagon has no select or setcc: expand to SELECT_CC. 1360245431Sdim setOperationAction(ISD::SELECT, MVT::f32, Expand); 1361245431Sdim setOperationAction(ISD::SELECT, MVT::f64, Expand); 1362245431Sdim 1363245431Sdim // This is a workaround documented in DAGCombiner.cpp:2892 We don't 1364245431Sdim // support SELECT_CC on every type. 1365245431Sdim setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); 1366245431Sdim 1367245431Sdim } 1368245431Sdim 1369234285Sdim if (EmitJumpTables) { 1370234285Sdim setOperationAction(ISD::BR_JT, MVT::Other, Custom); 1371234285Sdim } else { 1372234285Sdim setOperationAction(ISD::BR_JT, MVT::Other, Expand); 1373234285Sdim } 1374245431Sdim // Increase jump tables cutover to 5, was 4. 1375245431Sdim setMinimumJumpTableEntries(5); 1376234285Sdim 1377252723Sdim setOperationAction(ISD::BR_CC, MVT::f32, Expand); 1378252723Sdim setOperationAction(ISD::BR_CC, MVT::f64, Expand); 1379252723Sdim setOperationAction(ISD::BR_CC, MVT::i1, Expand); 1380234285Sdim setOperationAction(ISD::BR_CC, MVT::i32, Expand); 1381252723Sdim setOperationAction(ISD::BR_CC, MVT::i64, Expand); 1382234285Sdim 1383234285Sdim setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); 1384234285Sdim 1385234285Sdim setOperationAction(ISD::FSIN , MVT::f64, Expand); 1386234285Sdim setOperationAction(ISD::FCOS , MVT::f64, Expand); 1387234285Sdim setOperationAction(ISD::FREM , MVT::f64, Expand); 1388234285Sdim setOperationAction(ISD::FSIN , MVT::f32, Expand); 1389234285Sdim setOperationAction(ISD::FCOS , MVT::f32, Expand); 1390234285Sdim setOperationAction(ISD::FREM , MVT::f32, Expand); 1391252723Sdim setOperationAction(ISD::FSINCOS, MVT::f64, Expand); 1392252723Sdim setOperationAction(ISD::FSINCOS, MVT::f32, Expand); 1393252723Sdim 1394252723Sdim // In V4, we have double word add/sub with carry. The problem with 1395252723Sdim // modelling this instruction is that it produces 2 results - Rdd and Px. 1396252723Sdim // To model update of Px, we will have to use Defs[p0..p3] which will 1397252723Sdim // cause any predicate live range to spill. So, we pretend we dont't 1398252723Sdim // have these instructions. 1399252723Sdim setOperationAction(ISD::ADDE, MVT::i8, Expand); 1400252723Sdim setOperationAction(ISD::ADDE, MVT::i16, Expand); 1401252723Sdim setOperationAction(ISD::ADDE, MVT::i32, Expand); 1402252723Sdim setOperationAction(ISD::ADDE, MVT::i64, Expand); 1403252723Sdim setOperationAction(ISD::SUBE, MVT::i8, Expand); 1404252723Sdim setOperationAction(ISD::SUBE, MVT::i16, Expand); 1405252723Sdim setOperationAction(ISD::SUBE, MVT::i32, Expand); 1406252723Sdim setOperationAction(ISD::SUBE, MVT::i64, Expand); 1407252723Sdim setOperationAction(ISD::ADDC, MVT::i8, Expand); 1408252723Sdim setOperationAction(ISD::ADDC, MVT::i16, Expand); 1409252723Sdim setOperationAction(ISD::ADDC, MVT::i32, Expand); 1410252723Sdim setOperationAction(ISD::ADDC, MVT::i64, Expand); 1411252723Sdim setOperationAction(ISD::SUBC, MVT::i8, Expand); 1412252723Sdim setOperationAction(ISD::SUBC, MVT::i16, Expand); 1413252723Sdim setOperationAction(ISD::SUBC, MVT::i32, Expand); 1414252723Sdim setOperationAction(ISD::SUBC, MVT::i64, Expand); 1415252723Sdim 1416234285Sdim setOperationAction(ISD::CTPOP, MVT::i32, Expand); 1417252723Sdim setOperationAction(ISD::CTPOP, MVT::i64, Expand); 1418234285Sdim setOperationAction(ISD::CTTZ , MVT::i32, Expand); 1419252723Sdim setOperationAction(ISD::CTTZ , MVT::i64, Expand); 1420234285Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); 1421252723Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); 1422234285Sdim setOperationAction(ISD::CTLZ , MVT::i32, Expand); 1423252723Sdim setOperationAction(ISD::CTLZ , MVT::i64, Expand); 1424234285Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); 1425252723Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); 1426234285Sdim setOperationAction(ISD::ROTL , MVT::i32, Expand); 1427234285Sdim setOperationAction(ISD::ROTR , MVT::i32, Expand); 1428234285Sdim setOperationAction(ISD::BSWAP, MVT::i32, Expand); 1429234285Sdim setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); 1430234285Sdim setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); 1431234285Sdim setOperationAction(ISD::FPOW , MVT::f64, Expand); 1432234285Sdim setOperationAction(ISD::FPOW , MVT::f32, Expand); 1433234285Sdim 1434234285Sdim setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 1435234285Sdim setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 1436234285Sdim setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 1437234285Sdim 1438234285Sdim setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 1439234285Sdim setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 1440234285Sdim 1441234285Sdim setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); 1442234285Sdim setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); 1443234285Sdim 1444252723Sdim setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); 1445234285Sdim 1446234285Sdim if (TM.getSubtargetImpl()->isSubtargetV2()) { 1447234285Sdim setExceptionPointerRegister(Hexagon::R20); 1448234285Sdim setExceptionSelectorRegister(Hexagon::R21); 1449234285Sdim } else { 1450234285Sdim setExceptionPointerRegister(Hexagon::R0); 1451234285Sdim setExceptionSelectorRegister(Hexagon::R1); 1452234285Sdim } 1453234285Sdim 1454234285Sdim // VASTART needs to be custom lowered to use the VarArgsFrameIndex. 1455234285Sdim setOperationAction(ISD::VASTART , MVT::Other, Custom); 1456234285Sdim 1457234285Sdim // Use the default implementation. 1458234285Sdim setOperationAction(ISD::VAARG , MVT::Other, Expand); 1459234285Sdim setOperationAction(ISD::VACOPY , MVT::Other, Expand); 1460234285Sdim setOperationAction(ISD::VAEND , MVT::Other, Expand); 1461234285Sdim setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); 1462234285Sdim setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); 1463234285Sdim 1464234285Sdim 1465234285Sdim setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); 1466234285Sdim setOperationAction(ISD::INLINEASM , MVT::Other, Custom); 1467234285Sdim 1468234285Sdim setMinFunctionAlignment(2); 1469234285Sdim 1470234285Sdim // Needed for DYNAMIC_STACKALLOC expansion. 1471234285Sdim unsigned StackRegister = TM.getRegisterInfo()->getStackRegister(); 1472234285Sdim setStackPointerRegisterToSaveRestore(StackRegister); 1473234285Sdim setSchedulingPreference(Sched::VLIW); 1474234285Sdim} 1475234285Sdim 1476234285Sdim 1477234285Sdimconst char* 1478234285SdimHexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { 1479234285Sdim switch (Opcode) { 1480234285Sdim default: return 0; 1481245431Sdim case HexagonISD::CONST32: return "HexagonISD::CONST32"; 1482252723Sdim case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP"; 1483252723Sdim case HexagonISD::CONST32_Int_Real: return "HexagonISD::CONST32_Int_Real"; 1484234285Sdim case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC"; 1485245431Sdim case HexagonISD::CMPICC: return "HexagonISD::CMPICC"; 1486245431Sdim case HexagonISD::CMPFCC: return "HexagonISD::CMPFCC"; 1487245431Sdim case HexagonISD::BRICC: return "HexagonISD::BRICC"; 1488245431Sdim case HexagonISD::BRFCC: return "HexagonISD::BRFCC"; 1489245431Sdim case HexagonISD::SELECT_ICC: return "HexagonISD::SELECT_ICC"; 1490245431Sdim case HexagonISD::SELECT_FCC: return "HexagonISD::SELECT_FCC"; 1491245431Sdim case HexagonISD::Hi: return "HexagonISD::Hi"; 1492245431Sdim case HexagonISD::Lo: return "HexagonISD::Lo"; 1493245431Sdim case HexagonISD::FTOI: return "HexagonISD::FTOI"; 1494245431Sdim case HexagonISD::ITOF: return "HexagonISD::ITOF"; 1495245431Sdim case HexagonISD::CALL: return "HexagonISD::CALL"; 1496245431Sdim case HexagonISD::RET_FLAG: return "HexagonISD::RET_FLAG"; 1497245431Sdim case HexagonISD::BR_JT: return "HexagonISD::BR_JT"; 1498245431Sdim case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN"; 1499252723Sdim case HexagonISD::EH_RETURN: return "HexagonISD::EH_RETURN"; 1500234285Sdim } 1501234285Sdim} 1502234285Sdim 1503234285Sdimbool 1504234285SdimHexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const { 1505234285Sdim EVT MTy1 = EVT::getEVT(Ty1); 1506234285Sdim EVT MTy2 = EVT::getEVT(Ty2); 1507234285Sdim if (!MTy1.isSimple() || !MTy2.isSimple()) { 1508234285Sdim return false; 1509234285Sdim } 1510234285Sdim return ((MTy1.getSimpleVT() == MVT::i64) && (MTy2.getSimpleVT() == MVT::i32)); 1511234285Sdim} 1512234285Sdim 1513234285Sdimbool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { 1514234285Sdim if (!VT1.isSimple() || !VT2.isSimple()) { 1515234285Sdim return false; 1516234285Sdim } 1517234285Sdim return ((VT1.getSimpleVT() == MVT::i64) && (VT2.getSimpleVT() == MVT::i32)); 1518234285Sdim} 1519234285Sdim 1520263509Sdimbool 1521263509SdimHexagonTargetLowering::allowTruncateForTailCall(Type *Ty1, Type *Ty2) const { 1522263509Sdim // Assuming the caller does not have either a signext or zeroext modifier, and 1523263509Sdim // only one value is accepted, any reasonable truncation is allowed. 1524263509Sdim if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy()) 1525263509Sdim return false; 1526263509Sdim 1527263509Sdim // FIXME: in principle up to 64-bit could be made safe, but it would be very 1528263509Sdim // fragile at the moment: any support for multiple value returns would be 1529263509Sdim // liable to disallow tail calls involving i64 -> iN truncation in many cases. 1530263509Sdim return Ty1->getPrimitiveSizeInBits() <= 32; 1531263509Sdim} 1532263509Sdim 1533234285SdimSDValue 1534252723SdimHexagonTargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { 1535252723Sdim SDValue Chain = Op.getOperand(0); 1536252723Sdim SDValue Offset = Op.getOperand(1); 1537252723Sdim SDValue Handler = Op.getOperand(2); 1538263509Sdim SDLoc dl(Op); 1539252723Sdim 1540252723Sdim // Mark function as containing a call to EH_RETURN. 1541252723Sdim HexagonMachineFunctionInfo *FuncInfo = 1542252723Sdim DAG.getMachineFunction().getInfo<HexagonMachineFunctionInfo>(); 1543252723Sdim FuncInfo->setHasEHReturn(); 1544252723Sdim 1545252723Sdim unsigned OffsetReg = Hexagon::R28; 1546252723Sdim 1547252723Sdim SDValue StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(), 1548252723Sdim DAG.getRegister(Hexagon::R30, getPointerTy()), 1549252723Sdim DAG.getIntPtrConstant(4)); 1550252723Sdim Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo(), 1551252723Sdim false, false, 0); 1552252723Sdim Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset); 1553252723Sdim 1554252723Sdim // Not needed we already use it as explict input to EH_RETURN. 1555252723Sdim // MF.getRegInfo().addLiveOut(OffsetReg); 1556252723Sdim 1557252723Sdim return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain); 1558252723Sdim} 1559252723Sdim 1560252723SdimSDValue 1561234285SdimHexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { 1562234285Sdim switch (Op.getOpcode()) { 1563234285Sdim default: llvm_unreachable("Should not custom lower this!"); 1564245431Sdim case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 1565252723Sdim case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); 1566234285Sdim // Frame & Return address. Currently unimplemented. 1567245431Sdim case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); 1568245431Sdim case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 1569234285Sdim case ISD::GlobalTLSAddress: 1570234285Sdim llvm_unreachable("TLS not implemented for Hexagon."); 1571234285Sdim case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); 1572234285Sdim case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG); 1573252723Sdim case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 1574234285Sdim case ISD::VASTART: return LowerVASTART(Op, DAG); 1575234285Sdim case ISD::BR_JT: return LowerBR_JT(Op, DAG); 1576234285Sdim 1577234285Sdim case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); 1578245431Sdim case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 1579245431Sdim case ISD::SELECT: return Op; 1580234285Sdim case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); 1581245431Sdim case ISD::INLINEASM: return LowerINLINEASM(Op, DAG); 1582234285Sdim 1583234285Sdim } 1584234285Sdim} 1585234285Sdim 1586234285Sdim 1587234285Sdim 1588234285Sdim//===----------------------------------------------------------------------===// 1589234285Sdim// Hexagon Scheduler Hooks 1590234285Sdim//===----------------------------------------------------------------------===// 1591234285SdimMachineBasicBlock * 1592234285SdimHexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 1593234285Sdim MachineBasicBlock *BB) 1594234285Sdimconst { 1595234285Sdim switch (MI->getOpcode()) { 1596234285Sdim case Hexagon::ADJDYNALLOC: { 1597234285Sdim MachineFunction *MF = BB->getParent(); 1598234285Sdim HexagonMachineFunctionInfo *FuncInfo = 1599234285Sdim MF->getInfo<HexagonMachineFunctionInfo>(); 1600234285Sdim FuncInfo->addAllocaAdjustInst(MI); 1601234285Sdim return BB; 1602234285Sdim } 1603234285Sdim default: llvm_unreachable("Unexpected instr type to insert"); 1604234285Sdim } // switch 1605234285Sdim} 1606234285Sdim 1607234285Sdim//===----------------------------------------------------------------------===// 1608234285Sdim// Inline Assembly Support 1609234285Sdim//===----------------------------------------------------------------------===// 1610234285Sdim 1611234285Sdimstd::pair<unsigned, const TargetRegisterClass*> 1612234285SdimHexagonTargetLowering::getRegForInlineAsmConstraint(const 1613234285Sdim std::string &Constraint, 1614263509Sdim MVT VT) const { 1615234285Sdim if (Constraint.size() == 1) { 1616234285Sdim switch (Constraint[0]) { 1617234285Sdim case 'r': // R0-R31 1618263509Sdim switch (VT.SimpleTy) { 1619234285Sdim default: 1620234285Sdim llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type"); 1621234285Sdim case MVT::i32: 1622234285Sdim case MVT::i16: 1623234285Sdim case MVT::i8: 1624245431Sdim case MVT::f32: 1625245431Sdim return std::make_pair(0U, &Hexagon::IntRegsRegClass); 1626234285Sdim case MVT::i64: 1627245431Sdim case MVT::f64: 1628245431Sdim return std::make_pair(0U, &Hexagon::DoubleRegsRegClass); 1629234285Sdim } 1630234285Sdim default: 1631234285Sdim llvm_unreachable("Unknown asm register class"); 1632234285Sdim } 1633234285Sdim } 1634234285Sdim 1635234285Sdim return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 1636234285Sdim} 1637234285Sdim 1638245431Sdim/// isFPImmLegal - Returns true if the target can instruction select the 1639245431Sdim/// specified FP immediate natively. If false, the legalizer will 1640245431Sdim/// materialize the FP immediate as a load from a constant pool. 1641245431Sdimbool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { 1642245431Sdim const HexagonRegisterInfo* QRI = TM.getRegisterInfo(); 1643245431Sdim return QRI->Subtarget.hasV5TOps(); 1644245431Sdim} 1645245431Sdim 1646234285Sdim/// isLegalAddressingMode - Return true if the addressing mode represented by 1647234285Sdim/// AM is legal for this target, for a load/store of the specified type. 1648234285Sdimbool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM, 1649234285Sdim Type *Ty) const { 1650234285Sdim // Allows a signed-extended 11-bit immediate field. 1651234285Sdim if (AM.BaseOffs <= -(1LL << 13) || AM.BaseOffs >= (1LL << 13)-1) { 1652234285Sdim return false; 1653234285Sdim } 1654234285Sdim 1655234285Sdim // No global is ever allowed as a base. 1656234285Sdim if (AM.BaseGV) { 1657234285Sdim return false; 1658234285Sdim } 1659234285Sdim 1660234285Sdim int Scale = AM.Scale; 1661234285Sdim if (Scale < 0) Scale = -Scale; 1662234285Sdim switch (Scale) { 1663234285Sdim case 0: // No scale reg, "r+i", "r", or just "i". 1664234285Sdim break; 1665234285Sdim default: // No scaled addressing mode. 1666234285Sdim return false; 1667234285Sdim } 1668234285Sdim return true; 1669234285Sdim} 1670234285Sdim 1671234285Sdim/// isLegalICmpImmediate - Return true if the specified immediate is legal 1672234285Sdim/// icmp immediate, that is the target has icmp instructions which can compare 1673234285Sdim/// a register against the immediate without having to materialize the 1674234285Sdim/// immediate into a register. 1675234285Sdimbool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const { 1676234285Sdim return Imm >= -512 && Imm <= 511; 1677234285Sdim} 1678234285Sdim 1679234285Sdim/// IsEligibleForTailCallOptimization - Check whether the call is eligible 1680234285Sdim/// for tail call optimization. Targets which want to do tail call 1681234285Sdim/// optimization should implement this function. 1682234285Sdimbool HexagonTargetLowering::IsEligibleForTailCallOptimization( 1683234285Sdim SDValue Callee, 1684234285Sdim CallingConv::ID CalleeCC, 1685234285Sdim bool isVarArg, 1686234285Sdim bool isCalleeStructRet, 1687234285Sdim bool isCallerStructRet, 1688234285Sdim const SmallVectorImpl<ISD::OutputArg> &Outs, 1689234285Sdim const SmallVectorImpl<SDValue> &OutVals, 1690234285Sdim const SmallVectorImpl<ISD::InputArg> &Ins, 1691234285Sdim SelectionDAG& DAG) const { 1692234285Sdim const Function *CallerF = DAG.getMachineFunction().getFunction(); 1693234285Sdim CallingConv::ID CallerCC = CallerF->getCallingConv(); 1694234285Sdim bool CCMatch = CallerCC == CalleeCC; 1695234285Sdim 1696234285Sdim // *************************************************************************** 1697234285Sdim // Look for obvious safe cases to perform tail call optimization that do not 1698234285Sdim // require ABI changes. 1699234285Sdim // *************************************************************************** 1700234285Sdim 1701234285Sdim // If this is a tail call via a function pointer, then don't do it! 1702234285Sdim if (!(dyn_cast<GlobalAddressSDNode>(Callee)) 1703234285Sdim && !(dyn_cast<ExternalSymbolSDNode>(Callee))) { 1704234285Sdim return false; 1705234285Sdim } 1706234285Sdim 1707234285Sdim // Do not optimize if the calling conventions do not match. 1708234285Sdim if (!CCMatch) 1709234285Sdim return false; 1710234285Sdim 1711234285Sdim // Do not tail call optimize vararg calls. 1712234285Sdim if (isVarArg) 1713234285Sdim return false; 1714234285Sdim 1715234285Sdim // Also avoid tail call optimization if either caller or callee uses struct 1716234285Sdim // return semantics. 1717234285Sdim if (isCalleeStructRet || isCallerStructRet) 1718234285Sdim return false; 1719234285Sdim 1720234285Sdim // In addition to the cases above, we also disable Tail Call Optimization if 1721234285Sdim // the calling convention code that at least one outgoing argument needs to 1722234285Sdim // go on the stack. We cannot check that here because at this point that 1723234285Sdim // information is not available. 1724234285Sdim return true; 1725234285Sdim} 1726