1249259Sdim//===-- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface --*- C++ -*-===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// Subclass of MipsTargetLowering specialized for mips32/64. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim#include "MipsSEISelLowering.h" 14249259Sdim#include "MipsRegisterInfo.h" 15249259Sdim#include "MipsTargetMachine.h" 16249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 17249259Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 18251662Sdim#include "llvm/IR/Intrinsics.h" 19249259Sdim#include "llvm/Support/CommandLine.h" 20249259Sdim#include "llvm/Target/TargetInstrInfo.h" 21249259Sdim 22249259Sdimusing namespace llvm; 23249259Sdim 24249259Sdimstatic cl::opt<bool> 25249259SdimEnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden, 26249259Sdim cl::desc("MIPS: Enable tail calls."), cl::init(false)); 27249259Sdim 28249259SdimMipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM) 29249259Sdim : MipsTargetLowering(TM) { 30249259Sdim // Set up the register classes 31251662Sdim 32251662Sdim clearRegisterClasses(); 33251662Sdim 34249259Sdim addRegisterClass(MVT::i32, &Mips::CPURegsRegClass); 35249259Sdim 36249259Sdim if (HasMips64) 37249259Sdim addRegisterClass(MVT::i64, &Mips::CPU64RegsRegClass); 38249259Sdim 39249259Sdim if (Subtarget->hasDSP()) { 40249259Sdim MVT::SimpleValueType VecTys[2] = {MVT::v2i16, MVT::v4i8}; 41249259Sdim 42249259Sdim for (unsigned i = 0; i < array_lengthof(VecTys); ++i) { 43249259Sdim addRegisterClass(VecTys[i], &Mips::DSPRegsRegClass); 44249259Sdim 45249259Sdim // Expand all builtin opcodes. 46249259Sdim for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) 47249259Sdim setOperationAction(Opc, VecTys[i], Expand); 48249259Sdim 49251662Sdim setOperationAction(ISD::ADD, VecTys[i], Legal); 50251662Sdim setOperationAction(ISD::SUB, VecTys[i], Legal); 51249259Sdim setOperationAction(ISD::LOAD, VecTys[i], Legal); 52249259Sdim setOperationAction(ISD::STORE, VecTys[i], Legal); 53249259Sdim setOperationAction(ISD::BITCAST, VecTys[i], Legal); 54249259Sdim } 55251662Sdim 56251662Sdim setTargetDAGCombine(ISD::SHL); 57251662Sdim setTargetDAGCombine(ISD::SRA); 58251662Sdim setTargetDAGCombine(ISD::SRL); 59251662Sdim setTargetDAGCombine(ISD::SETCC); 60251662Sdim setTargetDAGCombine(ISD::VSELECT); 61249259Sdim } 62249259Sdim 63251662Sdim if (Subtarget->hasDSPR2()) 64251662Sdim setOperationAction(ISD::MUL, MVT::v2i16, Legal); 65251662Sdim 66249259Sdim if (!TM.Options.UseSoftFloat) { 67249259Sdim addRegisterClass(MVT::f32, &Mips::FGR32RegClass); 68249259Sdim 69249259Sdim // When dealing with single precision only, use libcalls 70249259Sdim if (!Subtarget->isSingleFloat()) { 71249259Sdim if (HasMips64) 72249259Sdim addRegisterClass(MVT::f64, &Mips::FGR64RegClass); 73249259Sdim else 74249259Sdim addRegisterClass(MVT::f64, &Mips::AFGR64RegClass); 75249259Sdim } 76249259Sdim } 77249259Sdim 78249259Sdim setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); 79249259Sdim setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); 80249259Sdim setOperationAction(ISD::MULHS, MVT::i32, Custom); 81249259Sdim setOperationAction(ISD::MULHU, MVT::i32, Custom); 82249259Sdim 83251662Sdim if (HasMips64) { 84251662Sdim setOperationAction(ISD::MULHS, MVT::i64, Custom); 85251662Sdim setOperationAction(ISD::MULHU, MVT::i64, Custom); 86249259Sdim setOperationAction(ISD::MUL, MVT::i64, Custom); 87251662Sdim } 88249259Sdim 89251662Sdim setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); 90251662Sdim setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); 91251662Sdim 92249259Sdim setOperationAction(ISD::SDIVREM, MVT::i32, Custom); 93249259Sdim setOperationAction(ISD::UDIVREM, MVT::i32, Custom); 94249259Sdim setOperationAction(ISD::SDIVREM, MVT::i64, Custom); 95249259Sdim setOperationAction(ISD::UDIVREM, MVT::i64, Custom); 96249259Sdim setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); 97249259Sdim setOperationAction(ISD::LOAD, MVT::i32, Custom); 98249259Sdim setOperationAction(ISD::STORE, MVT::i32, Custom); 99249259Sdim 100249259Sdim setTargetDAGCombine(ISD::ADDE); 101249259Sdim setTargetDAGCombine(ISD::SUBE); 102249259Sdim 103249259Sdim computeRegisterProperties(); 104249259Sdim} 105249259Sdim 106249259Sdimconst MipsTargetLowering * 107249259Sdimllvm::createMipsSETargetLowering(MipsTargetMachine &TM) { 108249259Sdim return new MipsSETargetLowering(TM); 109249259Sdim} 110249259Sdim 111249259Sdim 112249259Sdimbool 113249259SdimMipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const { 114249259Sdim MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; 115249259Sdim 116249259Sdim switch (SVT) { 117249259Sdim case MVT::i64: 118249259Sdim case MVT::i32: 119249259Sdim if (Fast) 120249259Sdim *Fast = true; 121249259Sdim return true; 122249259Sdim default: 123249259Sdim return false; 124249259Sdim } 125249259Sdim} 126249259Sdim 127249259SdimSDValue MipsSETargetLowering::LowerOperation(SDValue Op, 128249259Sdim SelectionDAG &DAG) const { 129249259Sdim switch(Op.getOpcode()) { 130249259Sdim case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG); 131249259Sdim case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG); 132249259Sdim case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG); 133249259Sdim case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG); 134249259Sdim case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG); 135249259Sdim case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG); 136251662Sdim case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true, 137251662Sdim DAG); 138251662Sdim case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG); 139251662Sdim case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG); 140249259Sdim } 141249259Sdim 142249259Sdim return MipsTargetLowering::LowerOperation(Op, DAG); 143249259Sdim} 144249259Sdim 145249259Sdim// selectMADD - 146249259Sdim// Transforms a subgraph in CurDAG if the following pattern is found: 147249259Sdim// (addc multLo, Lo0), (adde multHi, Hi0), 148249259Sdim// where, 149249259Sdim// multHi/Lo: product of multiplication 150249259Sdim// Lo0: initial value of Lo register 151249259Sdim// Hi0: initial value of Hi register 152249259Sdim// Return true if pattern matching was successful. 153249259Sdimstatic bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) { 154249259Sdim // ADDENode's second operand must be a flag output of an ADDC node in order 155249259Sdim // for the matching to be successful. 156249259Sdim SDNode *ADDCNode = ADDENode->getOperand(2).getNode(); 157249259Sdim 158249259Sdim if (ADDCNode->getOpcode() != ISD::ADDC) 159249259Sdim return false; 160249259Sdim 161249259Sdim SDValue MultHi = ADDENode->getOperand(0); 162249259Sdim SDValue MultLo = ADDCNode->getOperand(0); 163249259Sdim SDNode *MultNode = MultHi.getNode(); 164249259Sdim unsigned MultOpc = MultHi.getOpcode(); 165249259Sdim 166249259Sdim // MultHi and MultLo must be generated by the same node, 167249259Sdim if (MultLo.getNode() != MultNode) 168249259Sdim return false; 169249259Sdim 170249259Sdim // and it must be a multiplication. 171249259Sdim if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) 172249259Sdim return false; 173249259Sdim 174249259Sdim // MultLo amd MultHi must be the first and second output of MultNode 175249259Sdim // respectively. 176249259Sdim if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) 177249259Sdim return false; 178249259Sdim 179249259Sdim // Transform this to a MADD only if ADDENode and ADDCNode are the only users 180249259Sdim // of the values of MultNode, in which case MultNode will be removed in later 181249259Sdim // phases. 182249259Sdim // If there exist users other than ADDENode or ADDCNode, this function returns 183249259Sdim // here, which will result in MultNode being mapped to a single MULT 184249259Sdim // instruction node rather than a pair of MULT and MADD instructions being 185249259Sdim // produced. 186249259Sdim if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) 187249259Sdim return false; 188249259Sdim 189249259Sdim DebugLoc DL = ADDENode->getDebugLoc(); 190249259Sdim 191249259Sdim // Initialize accumulator. 192249259Sdim SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, 193249259Sdim ADDCNode->getOperand(1), 194249259Sdim ADDENode->getOperand(1)); 195249259Sdim 196249259Sdim // create MipsMAdd(u) node 197249259Sdim MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; 198249259Sdim 199249259Sdim SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped, 200249259Sdim MultNode->getOperand(0),// Factor 0 201249259Sdim MultNode->getOperand(1),// Factor 1 202249259Sdim ACCIn); 203249259Sdim 204249259Sdim // replace uses of adde and addc here 205249259Sdim if (!SDValue(ADDCNode, 0).use_empty()) { 206249259Sdim SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32); 207249259Sdim SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd, 208249259Sdim LoIdx); 209249259Sdim CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut); 210249259Sdim } 211249259Sdim if (!SDValue(ADDENode, 0).use_empty()) { 212249259Sdim SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32); 213249259Sdim SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd, 214249259Sdim HiIdx); 215249259Sdim CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut); 216249259Sdim } 217249259Sdim 218249259Sdim return true; 219249259Sdim} 220249259Sdim 221249259Sdim// selectMSUB - 222249259Sdim// Transforms a subgraph in CurDAG if the following pattern is found: 223249259Sdim// (addc Lo0, multLo), (sube Hi0, multHi), 224249259Sdim// where, 225249259Sdim// multHi/Lo: product of multiplication 226249259Sdim// Lo0: initial value of Lo register 227249259Sdim// Hi0: initial value of Hi register 228249259Sdim// Return true if pattern matching was successful. 229249259Sdimstatic bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) { 230249259Sdim // SUBENode's second operand must be a flag output of an SUBC node in order 231249259Sdim // for the matching to be successful. 232249259Sdim SDNode *SUBCNode = SUBENode->getOperand(2).getNode(); 233249259Sdim 234249259Sdim if (SUBCNode->getOpcode() != ISD::SUBC) 235249259Sdim return false; 236249259Sdim 237249259Sdim SDValue MultHi = SUBENode->getOperand(1); 238249259Sdim SDValue MultLo = SUBCNode->getOperand(1); 239249259Sdim SDNode *MultNode = MultHi.getNode(); 240249259Sdim unsigned MultOpc = MultHi.getOpcode(); 241249259Sdim 242249259Sdim // MultHi and MultLo must be generated by the same node, 243249259Sdim if (MultLo.getNode() != MultNode) 244249259Sdim return false; 245249259Sdim 246249259Sdim // and it must be a multiplication. 247249259Sdim if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) 248249259Sdim return false; 249249259Sdim 250249259Sdim // MultLo amd MultHi must be the first and second output of MultNode 251249259Sdim // respectively. 252249259Sdim if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) 253249259Sdim return false; 254249259Sdim 255249259Sdim // Transform this to a MSUB only if SUBENode and SUBCNode are the only users 256249259Sdim // of the values of MultNode, in which case MultNode will be removed in later 257249259Sdim // phases. 258249259Sdim // If there exist users other than SUBENode or SUBCNode, this function returns 259249259Sdim // here, which will result in MultNode being mapped to a single MULT 260249259Sdim // instruction node rather than a pair of MULT and MSUB instructions being 261249259Sdim // produced. 262249259Sdim if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) 263249259Sdim return false; 264249259Sdim 265249259Sdim DebugLoc DL = SUBENode->getDebugLoc(); 266249259Sdim 267249259Sdim // Initialize accumulator. 268249259Sdim SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, 269249259Sdim SUBCNode->getOperand(0), 270249259Sdim SUBENode->getOperand(0)); 271249259Sdim 272249259Sdim // create MipsSub(u) node 273249259Sdim MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub; 274249259Sdim 275249259Sdim SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue, 276249259Sdim MultNode->getOperand(0),// Factor 0 277249259Sdim MultNode->getOperand(1),// Factor 1 278249259Sdim ACCIn); 279249259Sdim 280249259Sdim // replace uses of sube and subc here 281249259Sdim if (!SDValue(SUBCNode, 0).use_empty()) { 282249259Sdim SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32); 283249259Sdim SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub, 284249259Sdim LoIdx); 285249259Sdim CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut); 286249259Sdim } 287249259Sdim if (!SDValue(SUBENode, 0).use_empty()) { 288249259Sdim SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32); 289249259Sdim SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub, 290249259Sdim HiIdx); 291249259Sdim CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut); 292249259Sdim } 293249259Sdim 294249259Sdim return true; 295249259Sdim} 296249259Sdim 297249259Sdimstatic SDValue performADDECombine(SDNode *N, SelectionDAG &DAG, 298249259Sdim TargetLowering::DAGCombinerInfo &DCI, 299249259Sdim const MipsSubtarget *Subtarget) { 300249259Sdim if (DCI.isBeforeLegalize()) 301249259Sdim return SDValue(); 302249259Sdim 303249259Sdim if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && 304249259Sdim selectMADD(N, &DAG)) 305249259Sdim return SDValue(N, 0); 306249259Sdim 307249259Sdim return SDValue(); 308249259Sdim} 309249259Sdim 310249259Sdimstatic SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG, 311249259Sdim TargetLowering::DAGCombinerInfo &DCI, 312249259Sdim const MipsSubtarget *Subtarget) { 313249259Sdim if (DCI.isBeforeLegalize()) 314249259Sdim return SDValue(); 315249259Sdim 316249259Sdim if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && 317249259Sdim selectMSUB(N, &DAG)) 318249259Sdim return SDValue(N, 0); 319249259Sdim 320249259Sdim return SDValue(); 321249259Sdim} 322249259Sdim 323251662Sdimstatic SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty, 324251662Sdim SelectionDAG &DAG, 325251662Sdim const MipsSubtarget *Subtarget) { 326251662Sdim // See if this is a vector splat immediate node. 327251662Sdim APInt SplatValue, SplatUndef; 328251662Sdim unsigned SplatBitSize; 329251662Sdim bool HasAnyUndefs; 330251662Sdim unsigned EltSize = Ty.getVectorElementType().getSizeInBits(); 331251662Sdim BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1)); 332251662Sdim 333251662Sdim if (!BV || 334251662Sdim !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 335251662Sdim EltSize, !Subtarget->isLittle()) || 336251662Sdim (SplatBitSize != EltSize) || 337251662Sdim (SplatValue.getZExtValue() >= EltSize)) 338251662Sdim return SDValue(); 339251662Sdim 340251662Sdim return DAG.getNode(Opc, N->getDebugLoc(), Ty, N->getOperand(0), 341251662Sdim DAG.getConstant(SplatValue.getZExtValue(), MVT::i32)); 342251662Sdim} 343251662Sdim 344251662Sdimstatic SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, 345251662Sdim TargetLowering::DAGCombinerInfo &DCI, 346251662Sdim const MipsSubtarget *Subtarget) { 347251662Sdim EVT Ty = N->getValueType(0); 348251662Sdim 349251662Sdim if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) 350251662Sdim return SDValue(); 351251662Sdim 352251662Sdim return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget); 353251662Sdim} 354251662Sdim 355251662Sdimstatic SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, 356251662Sdim TargetLowering::DAGCombinerInfo &DCI, 357251662Sdim const MipsSubtarget *Subtarget) { 358251662Sdim EVT Ty = N->getValueType(0); 359251662Sdim 360251662Sdim if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget->hasDSPR2())) 361251662Sdim return SDValue(); 362251662Sdim 363251662Sdim return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget); 364251662Sdim} 365251662Sdim 366251662Sdim 367251662Sdimstatic SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, 368251662Sdim TargetLowering::DAGCombinerInfo &DCI, 369251662Sdim const MipsSubtarget *Subtarget) { 370251662Sdim EVT Ty = N->getValueType(0); 371251662Sdim 372251662Sdim if (((Ty != MVT::v2i16) || !Subtarget->hasDSPR2()) && (Ty != MVT::v4i8)) 373251662Sdim return SDValue(); 374251662Sdim 375251662Sdim return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget); 376251662Sdim} 377251662Sdim 378251662Sdimstatic bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) { 379251662Sdim bool IsV216 = (Ty == MVT::v2i16); 380251662Sdim 381251662Sdim switch (CC) { 382251662Sdim case ISD::SETEQ: 383251662Sdim case ISD::SETNE: return true; 384251662Sdim case ISD::SETLT: 385251662Sdim case ISD::SETLE: 386251662Sdim case ISD::SETGT: 387251662Sdim case ISD::SETGE: return IsV216; 388251662Sdim case ISD::SETULT: 389251662Sdim case ISD::SETULE: 390251662Sdim case ISD::SETUGT: 391251662Sdim case ISD::SETUGE: return !IsV216; 392251662Sdim default: return false; 393251662Sdim } 394251662Sdim} 395251662Sdim 396251662Sdimstatic SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) { 397251662Sdim EVT Ty = N->getValueType(0); 398251662Sdim 399251662Sdim if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) 400251662Sdim return SDValue(); 401251662Sdim 402251662Sdim if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get())) 403251662Sdim return SDValue(); 404251662Sdim 405251662Sdim return DAG.getNode(MipsISD::SETCC_DSP, N->getDebugLoc(), Ty, N->getOperand(0), 406251662Sdim N->getOperand(1), N->getOperand(2)); 407251662Sdim} 408251662Sdim 409251662Sdimstatic SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { 410251662Sdim EVT Ty = N->getValueType(0); 411251662Sdim 412251662Sdim if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) 413251662Sdim return SDValue(); 414251662Sdim 415251662Sdim SDValue SetCC = N->getOperand(0); 416251662Sdim 417251662Sdim if (SetCC.getOpcode() != MipsISD::SETCC_DSP) 418251662Sdim return SDValue(); 419251662Sdim 420251662Sdim return DAG.getNode(MipsISD::SELECT_CC_DSP, N->getDebugLoc(), Ty, 421251662Sdim SetCC.getOperand(0), SetCC.getOperand(1), N->getOperand(1), 422251662Sdim N->getOperand(2), SetCC.getOperand(2)); 423251662Sdim} 424251662Sdim 425249259SdimSDValue 426249259SdimMipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { 427249259Sdim SelectionDAG &DAG = DCI.DAG; 428251662Sdim SDValue Val; 429249259Sdim 430249259Sdim switch (N->getOpcode()) { 431249259Sdim case ISD::ADDE: 432249259Sdim return performADDECombine(N, DAG, DCI, Subtarget); 433249259Sdim case ISD::SUBE: 434249259Sdim return performSUBECombine(N, DAG, DCI, Subtarget); 435251662Sdim case ISD::SHL: 436251662Sdim return performSHLCombine(N, DAG, DCI, Subtarget); 437251662Sdim case ISD::SRA: 438251662Sdim return performSRACombine(N, DAG, DCI, Subtarget); 439251662Sdim case ISD::SRL: 440251662Sdim return performSRLCombine(N, DAG, DCI, Subtarget); 441251662Sdim case ISD::VSELECT: 442251662Sdim return performVSELECTCombine(N, DAG); 443251662Sdim case ISD::SETCC: { 444251662Sdim Val = performSETCCCombine(N, DAG); 445251662Sdim break; 446249259Sdim } 447251662Sdim } 448251662Sdim 449251662Sdim if (Val.getNode()) 450251662Sdim return Val; 451251662Sdim 452251662Sdim return MipsTargetLowering::PerformDAGCombine(N, DCI); 453249259Sdim} 454249259Sdim 455249259SdimMachineBasicBlock * 456249259SdimMipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 457249259Sdim MachineBasicBlock *BB) const { 458249259Sdim switch (MI->getOpcode()) { 459249259Sdim default: 460249259Sdim return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); 461249259Sdim case Mips::BPOSGE32_PSEUDO: 462249259Sdim return emitBPOSGE32(MI, BB); 463249259Sdim } 464249259Sdim} 465249259Sdim 466249259Sdimbool MipsSETargetLowering:: 467249259SdimisEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, 468249259Sdim unsigned NextStackOffset, 469249259Sdim const MipsFunctionInfo& FI) const { 470249259Sdim if (!EnableMipsTailCalls) 471249259Sdim return false; 472249259Sdim 473249259Sdim // Return false if either the callee or caller has a byval argument. 474249259Sdim if (MipsCCInfo.hasByValArg() || FI.hasByvalArg()) 475249259Sdim return false; 476249259Sdim 477249259Sdim // Return true if the callee's argument area is no larger than the 478249259Sdim // caller's. 479249259Sdim return NextStackOffset <= FI.getIncomingArgSize(); 480249259Sdim} 481249259Sdim 482249259Sdimvoid MipsSETargetLowering:: 483249259SdimgetOpndList(SmallVectorImpl<SDValue> &Ops, 484249259Sdim std::deque< std::pair<unsigned, SDValue> > &RegsToPass, 485249259Sdim bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, 486249259Sdim CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { 487249259Sdim // T9 should contain the address of the callee function if 488249259Sdim // -reloction-model=pic or it is an indirect call. 489249259Sdim if (IsPICCall || !GlobalOrExternal) { 490249259Sdim unsigned T9Reg = IsN64 ? Mips::T9_64 : Mips::T9; 491249259Sdim RegsToPass.push_front(std::make_pair(T9Reg, Callee)); 492249259Sdim } else 493249259Sdim Ops.push_back(Callee); 494249259Sdim 495249259Sdim MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, 496249259Sdim InternalLinkage, CLI, Callee, Chain); 497249259Sdim} 498249259Sdim 499249259SdimSDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, 500249259Sdim bool HasLo, bool HasHi, 501249259Sdim SelectionDAG &DAG) const { 502249259Sdim EVT Ty = Op.getOperand(0).getValueType(); 503249259Sdim DebugLoc DL = Op.getDebugLoc(); 504249259Sdim SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped, 505249259Sdim Op.getOperand(0), Op.getOperand(1)); 506249259Sdim SDValue Lo, Hi; 507249259Sdim 508249259Sdim if (HasLo) 509249259Sdim Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult, 510249259Sdim DAG.getConstant(Mips::sub_lo, MVT::i32)); 511249259Sdim if (HasHi) 512249259Sdim Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult, 513249259Sdim DAG.getConstant(Mips::sub_hi, MVT::i32)); 514249259Sdim 515249259Sdim if (!HasLo || !HasHi) 516249259Sdim return HasLo ? Lo : Hi; 517249259Sdim 518249259Sdim SDValue Vals[] = { Lo, Hi }; 519249259Sdim return DAG.getMergeValues(Vals, 2, DL); 520249259Sdim} 521249259Sdim 522251662Sdim 523251662Sdimstatic SDValue initAccumulator(SDValue In, DebugLoc DL, SelectionDAG &DAG) { 524251662Sdim SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, 525251662Sdim DAG.getConstant(0, MVT::i32)); 526251662Sdim SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, 527251662Sdim DAG.getConstant(1, MVT::i32)); 528251662Sdim return DAG.getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, InLo, InHi); 529251662Sdim} 530251662Sdim 531251662Sdimstatic SDValue extractLOHI(SDValue Op, DebugLoc DL, SelectionDAG &DAG) { 532251662Sdim SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, 533251662Sdim DAG.getConstant(Mips::sub_lo, MVT::i32)); 534251662Sdim SDValue Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, 535251662Sdim DAG.getConstant(Mips::sub_hi, MVT::i32)); 536251662Sdim return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); 537251662Sdim} 538251662Sdim 539251662Sdim// This function expands mips intrinsic nodes which have 64-bit input operands 540251662Sdim// or output values. 541251662Sdim// 542251662Sdim// out64 = intrinsic-node in64 543251662Sdim// => 544251662Sdim// lo = copy (extract-element (in64, 0)) 545251662Sdim// hi = copy (extract-element (in64, 1)) 546251662Sdim// mips-specific-node 547251662Sdim// v0 = copy lo 548251662Sdim// v1 = copy hi 549251662Sdim// out64 = merge-values (v0, v1) 550251662Sdim// 551251662Sdimstatic SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { 552251662Sdim DebugLoc DL = Op.getDebugLoc(); 553251662Sdim bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other; 554251662Sdim SmallVector<SDValue, 3> Ops; 555251662Sdim unsigned OpNo = 0; 556251662Sdim 557251662Sdim // See if Op has a chain input. 558251662Sdim if (HasChainIn) 559251662Sdim Ops.push_back(Op->getOperand(OpNo++)); 560251662Sdim 561251662Sdim // The next operand is the intrinsic opcode. 562251662Sdim assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant); 563251662Sdim 564251662Sdim // See if the next operand has type i64. 565251662Sdim SDValue Opnd = Op->getOperand(++OpNo), In64; 566251662Sdim 567251662Sdim if (Opnd.getValueType() == MVT::i64) 568251662Sdim In64 = initAccumulator(Opnd, DL, DAG); 569251662Sdim else 570251662Sdim Ops.push_back(Opnd); 571251662Sdim 572251662Sdim // Push the remaining operands. 573251662Sdim for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo) 574251662Sdim Ops.push_back(Op->getOperand(OpNo)); 575251662Sdim 576251662Sdim // Add In64 to the end of the list. 577251662Sdim if (In64.getNode()) 578251662Sdim Ops.push_back(In64); 579251662Sdim 580251662Sdim // Scan output. 581251662Sdim SmallVector<EVT, 2> ResTys; 582251662Sdim 583251662Sdim for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end(); 584251662Sdim I != E; ++I) 585251662Sdim ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I); 586251662Sdim 587251662Sdim // Create node. 588251662Sdim SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size()); 589251662Sdim SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val; 590251662Sdim 591251662Sdim if (!HasChainIn) 592251662Sdim return Out; 593251662Sdim 594251662Sdim assert(Val->getValueType(1) == MVT::Other); 595251662Sdim SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) }; 596251662Sdim return DAG.getMergeValues(Vals, 2, DL); 597251662Sdim} 598251662Sdim 599251662SdimSDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, 600251662Sdim SelectionDAG &DAG) const { 601251662Sdim switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) { 602251662Sdim default: 603251662Sdim return SDValue(); 604251662Sdim case Intrinsic::mips_shilo: 605251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::SHILO); 606251662Sdim case Intrinsic::mips_dpau_h_qbl: 607251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL); 608251662Sdim case Intrinsic::mips_dpau_h_qbr: 609251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR); 610251662Sdim case Intrinsic::mips_dpsu_h_qbl: 611251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL); 612251662Sdim case Intrinsic::mips_dpsu_h_qbr: 613251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR); 614251662Sdim case Intrinsic::mips_dpa_w_ph: 615251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH); 616251662Sdim case Intrinsic::mips_dps_w_ph: 617251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH); 618251662Sdim case Intrinsic::mips_dpax_w_ph: 619251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH); 620251662Sdim case Intrinsic::mips_dpsx_w_ph: 621251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH); 622251662Sdim case Intrinsic::mips_mulsa_w_ph: 623251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH); 624251662Sdim case Intrinsic::mips_mult: 625251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::Mult); 626251662Sdim case Intrinsic::mips_multu: 627251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::Multu); 628251662Sdim case Intrinsic::mips_madd: 629251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MAdd); 630251662Sdim case Intrinsic::mips_maddu: 631251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MAddu); 632251662Sdim case Intrinsic::mips_msub: 633251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MSub); 634251662Sdim case Intrinsic::mips_msubu: 635251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MSubu); 636251662Sdim } 637251662Sdim} 638251662Sdim 639251662SdimSDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, 640251662Sdim SelectionDAG &DAG) const { 641251662Sdim switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) { 642251662Sdim default: 643251662Sdim return SDValue(); 644251662Sdim case Intrinsic::mips_extp: 645251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::EXTP); 646251662Sdim case Intrinsic::mips_extpdp: 647251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP); 648251662Sdim case Intrinsic::mips_extr_w: 649251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W); 650251662Sdim case Intrinsic::mips_extr_r_w: 651251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W); 652251662Sdim case Intrinsic::mips_extr_rs_w: 653251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W); 654251662Sdim case Intrinsic::mips_extr_s_h: 655251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H); 656251662Sdim case Intrinsic::mips_mthlip: 657251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP); 658251662Sdim case Intrinsic::mips_mulsaq_s_w_ph: 659251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH); 660251662Sdim case Intrinsic::mips_maq_s_w_phl: 661251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL); 662251662Sdim case Intrinsic::mips_maq_s_w_phr: 663251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR); 664251662Sdim case Intrinsic::mips_maq_sa_w_phl: 665251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL); 666251662Sdim case Intrinsic::mips_maq_sa_w_phr: 667251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR); 668251662Sdim case Intrinsic::mips_dpaq_s_w_ph: 669251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH); 670251662Sdim case Intrinsic::mips_dpsq_s_w_ph: 671251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH); 672251662Sdim case Intrinsic::mips_dpaq_sa_l_w: 673251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W); 674251662Sdim case Intrinsic::mips_dpsq_sa_l_w: 675251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W); 676251662Sdim case Intrinsic::mips_dpaqx_s_w_ph: 677251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH); 678251662Sdim case Intrinsic::mips_dpaqx_sa_w_ph: 679251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH); 680251662Sdim case Intrinsic::mips_dpsqx_s_w_ph: 681251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH); 682251662Sdim case Intrinsic::mips_dpsqx_sa_w_ph: 683251662Sdim return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH); 684251662Sdim } 685251662Sdim} 686251662Sdim 687249259SdimMachineBasicBlock * MipsSETargetLowering:: 688249259SdimemitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ 689249259Sdim // $bb: 690249259Sdim // bposge32_pseudo $vr0 691249259Sdim // => 692249259Sdim // $bb: 693249259Sdim // bposge32 $tbb 694249259Sdim // $fbb: 695249259Sdim // li $vr2, 0 696249259Sdim // b $sink 697249259Sdim // $tbb: 698249259Sdim // li $vr1, 1 699249259Sdim // $sink: 700249259Sdim // $vr0 = phi($vr2, $fbb, $vr1, $tbb) 701249259Sdim 702249259Sdim MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); 703249259Sdim const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 704249259Sdim const TargetRegisterClass *RC = &Mips::CPURegsRegClass; 705249259Sdim DebugLoc DL = MI->getDebugLoc(); 706249259Sdim const BasicBlock *LLVM_BB = BB->getBasicBlock(); 707249259Sdim MachineFunction::iterator It = llvm::next(MachineFunction::iterator(BB)); 708249259Sdim MachineFunction *F = BB->getParent(); 709249259Sdim MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB); 710249259Sdim MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB); 711249259Sdim MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); 712249259Sdim F->insert(It, FBB); 713249259Sdim F->insert(It, TBB); 714249259Sdim F->insert(It, Sink); 715249259Sdim 716249259Sdim // Transfer the remainder of BB and its successor edges to Sink. 717249259Sdim Sink->splice(Sink->begin(), BB, llvm::next(MachineBasicBlock::iterator(MI)), 718249259Sdim BB->end()); 719249259Sdim Sink->transferSuccessorsAndUpdatePHIs(BB); 720249259Sdim 721249259Sdim // Add successors. 722249259Sdim BB->addSuccessor(FBB); 723249259Sdim BB->addSuccessor(TBB); 724249259Sdim FBB->addSuccessor(Sink); 725249259Sdim TBB->addSuccessor(Sink); 726249259Sdim 727249259Sdim // Insert the real bposge32 instruction to $BB. 728249259Sdim BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB); 729249259Sdim 730249259Sdim // Fill $FBB. 731249259Sdim unsigned VR2 = RegInfo.createVirtualRegister(RC); 732249259Sdim BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), VR2) 733249259Sdim .addReg(Mips::ZERO).addImm(0); 734249259Sdim BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink); 735249259Sdim 736249259Sdim // Fill $TBB. 737249259Sdim unsigned VR1 = RegInfo.createVirtualRegister(RC); 738249259Sdim BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), VR1) 739249259Sdim .addReg(Mips::ZERO).addImm(1); 740249259Sdim 741249259Sdim // Insert phi function to $Sink. 742249259Sdim BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI), 743249259Sdim MI->getOperand(0).getReg()) 744249259Sdim .addReg(VR2).addMBB(FBB).addReg(VR1).addMBB(TBB); 745249259Sdim 746249259Sdim MI->eraseFromParent(); // The pseudo instruction is gone now. 747249259Sdim return Sink; 748249259Sdim} 749