Esempio n. 1
0
/// AddOperand - Add the specified operand to the specified machine instr.  II
/// specifies the instruction information for the node, and IIOpNum is the
/// operand number (in the II) that we are adding. IIOpNum and II are used for
/// assertions only.
void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op,
                              unsigned IIOpNum,
                              const MCInstrDesc *II,
                              DenseMap<SDValue, unsigned> &VRBaseMap,
                              bool IsDebug, bool IsClone, bool IsCloned) {
    if (Op.isMachineOpcode()) {
        AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap,
                           IsDebug, IsClone, IsCloned);
    } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateImm(C->getSExtValue()));
    } else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
        const ConstantFP *CFP = F->getConstantFPValue();
        MI->addOperand(MachineOperand::CreateFPImm(CFP));
    } else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateReg(R->getReg(), false));
    } else if (RegisterMaskSDNode *RM = dyn_cast<RegisterMaskSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateRegMask(RM->getRegMask()));
    } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(), TGA->getOffset(),
                                                TGA->getTargetFlags()));
    } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock()));
    } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
    } else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateJTI(JT->getIndex(),
                       JT->getTargetFlags()));
    } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) {
        int Offset = CP->getOffset();
        unsigned Align = CP->getAlignment();
        Type *Type = CP->getType();
        // MachineConstantPool wants an explicit alignment.
        if (Align == 0) {
            Align = TM->getTargetData()->getPrefTypeAlignment(Type);
            if (Align == 0) {
                // Alignment of vector types.  FIXME!
                Align = TM->getTargetData()->getTypeAllocSize(Type);
            }
        }

        unsigned Idx;
        MachineConstantPool *MCP = MF->getConstantPool();
        if (CP->isMachineConstantPoolEntry())
            Idx = MCP->getConstantPoolIndex(CP->getMachineCPVal(), Align);
        else
            Idx = MCP->getConstantPoolIndex(CP->getConstVal(), Align);
        MI->addOperand(MachineOperand::CreateCPI(Idx, Offset,
                       CP->getTargetFlags()));
    } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateES(ES->getSymbol(),
                                                ES->getTargetFlags()));
    } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
        MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress(),
                                                BA->getTargetFlags()));
    } else {
        assert(Op.getValueType() != MVT::Other &&
               Op.getValueType() != MVT::Glue &&
               "Chain and glue operands should occur at end of operand list!");
        AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap,
                           IsDebug, IsClone, IsCloned);
    }
}
Esempio n. 2
0
SDValue
AlphaTargetLowering::LowerReturn(SDValue Chain,
                                 CallingConv::ID CallConv, bool isVarArg,
                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
                                 DebugLoc dl, SelectionDAG &DAG) {

  SDValue Copy = DAG.getCopyToReg(Chain, dl, Alpha::R26,
                                  DAG.getNode(AlphaISD::GlobalRetAddr,
                                              DebugLoc::getUnknownLoc(),
                                              MVT::i64),
                                  SDValue());
  switch (Outs.size()) {
  default:
    llvm_unreachable("Do not know how to return this many arguments!");
  case 0:
    break;
    //return SDValue(); // ret void is legal
  case 1: {
    EVT ArgVT = Outs[0].Val.getValueType();
    unsigned ArgReg;
    if (ArgVT.isInteger())
      ArgReg = Alpha::R0;
    else {
      assert(ArgVT.isFloatingPoint());
      ArgReg = Alpha::F0;
    }
    Copy = DAG.getCopyToReg(Copy, dl, ArgReg,
                            Outs[0].Val, Copy.getValue(1));
    if (DAG.getMachineFunction().getRegInfo().liveout_empty())
      DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg);
    break;
  }
  case 2: {
    EVT ArgVT = Outs[0].Val.getValueType();
    unsigned ArgReg1, ArgReg2;
    if (ArgVT.isInteger()) {
      ArgReg1 = Alpha::R0;
      ArgReg2 = Alpha::R1;
    } else {
      assert(ArgVT.isFloatingPoint());
      ArgReg1 = Alpha::F0;
      ArgReg2 = Alpha::F1;
    }
    Copy = DAG.getCopyToReg(Copy, dl, ArgReg1,
                            Outs[0].Val, Copy.getValue(1));
    if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(),
                  DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg1)
        == DAG.getMachineFunction().getRegInfo().liveout_end())
      DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg1);
    Copy = DAG.getCopyToReg(Copy, dl, ArgReg2,
                            Outs[1].Val, Copy.getValue(1));
    if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(),
                   DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg2)
        == DAG.getMachineFunction().getRegInfo().liveout_end())
      DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg2);
    break;
  }
  }
  return DAG.getNode(AlphaISD::RET_FLAG, dl,
                     MVT::Other, Copy, Copy.getValue(1));
}
Esempio n. 3
0
/// ComplexPattern used on MipsInstrInfo
/// Used on Mips Load/Store instructions
bool MipsDAGToDAGISel::
SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) {
  EVT ValTy = Addr.getValueType();

  // if Address is FI, get the TargetFrameIndex.
  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
    Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
    Offset = CurDAG->getTargetConstant(0, ValTy);
    return true;
  }

  // on PIC code Load GA
  if (Addr.getOpcode() == MipsISD::Wrapper) {
    Base   = Addr.getOperand(0);
    Offset = Addr.getOperand(1);
    return true;
  }

  if (TM.getRelocationModel() != Reloc::PIC_) {
    if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
        Addr.getOpcode() == ISD::TargetGlobalAddress))
      return false;
  }

  // Addresses of the form FI+const or FI|const
  if (CurDAG->isBaseWithConstantOffset(Addr)) {
    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
    if (isInt<16>(CN->getSExtValue())) {

      // If the first operand is a FI, get the TargetFI Node
      if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
                                  (Addr.getOperand(0)))
        Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
      else
        Base = Addr.getOperand(0);

      Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy);
      return true;
    }
  }

  // Operand is a result from an ADD.
  if (Addr.getOpcode() == ISD::ADD) {
    // When loading from constant pools, load the lower address part in
    // the instruction itself. Example, instead of:
    //  lui $2, %hi($CPI1_0)
    //  addiu $2, $2, %lo($CPI1_0)
    //  lwc1 $f0, 0($2)
    // Generate:
    //  lui $2, %hi($CPI1_0)
    //  lwc1 $f0, %lo($CPI1_0)($2)
    if (Addr.getOperand(1).getOpcode() == MipsISD::Lo) {
      SDValue LoVal = Addr.getOperand(1), Opnd0 = LoVal.getOperand(0);
      if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
          isa<JumpTableSDNode>(Opnd0)) {
        Base = Addr.getOperand(0);
        Offset = Opnd0;
        return true;
      }
    }

    // If an indexed floating point load/store can be emitted, return false.
    const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent);

    if (LS &&
        (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) &&
        Subtarget.hasMips32r2Or64())
      return false;
  }

  Base   = Addr;
  Offset = CurDAG->getTargetConstant(0, ValTy);
  return true;
}
Esempio n. 4
0
/// LowerCCCCallTo - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: sret.
SDValue
NvfcTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
                                     CallingConv::ID CallConv, bool isVarArg,
                                     bool isTailCall,
                                     const SmallVectorImpl<ISD::OutputArg>
                                       &Outs,
                                     const SmallVectorImpl<SDValue> &OutVals,
                                     const SmallVectorImpl<ISD::InputArg> &Ins,
                                     DebugLoc dl, SelectionDAG &DAG,
                                     SmallVectorImpl<SDValue> &InVals) const {
  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 ArgLocs, *DAG.getContext());

  CCInfo.AnalyzeCallOperands(Outs, CC_NVFUC);

  // Get a count of how many bytes are to be pushed on the stack.
  unsigned NumBytes = CCInfo.getNextStackOffset();

  Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes,
                                                      getPointerTy(), true));

  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
  SmallVector<SDValue, 12> MemOpChains;
  SDValue StackPtr;

  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    SDValue Arg = OutVals[i];

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
      default: llvm_unreachable("Unknown loc info!");
      case CCValAssign::Full: break;
    }

    // Arguments that can be passed on register must be kept at RegsToPass
    // vector
    if (VA.isRegLoc()) {
      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
    } else {
      assert(VA.isMemLoc());

      // BUG: Special registers cannot be accessed...
      if (StackPtr.getNode() == 0)
        StackPtr = DAG.getCopyFromReg(Chain, dl, Nvfc::SP, getPointerTy());

      SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
                                   StackPtr,
                                   DAG.getIntPtrConstant(VA.getLocMemOffset()));


      MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
                                         PseudoSourceValue::getStack(),
                                         VA.getLocMemOffset(), false, false, 0));
    }
  }

  // Transform all store nodes into one single node because all store nodes are
  // independent of each other.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                        &MemOpChains[0], MemOpChains.size());

  // Build a sequence of copy-to-reg nodes chained together with token chain and
  // flag operands which copy the outgoing args into registers.  The InFlag in
  // necessary since all emited instructions must be stuck together.
  SDValue InFlag;
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
                             RegsToPass[i].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);

  // Returns a chain & a flag for retval copy to use.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
  SmallVector<SDValue, 8> Ops;  
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
                                  RegsToPass[i].second.getValueType()));

  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(NvfcISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
  InFlag = Chain.getValue(1);

  // Create the CALLSEQ_END node.
  Chain = DAG.getCALLSEQ_END(Chain,
                             DAG.getConstant(NumBytes, getPointerTy(), true),
                             DAG.getConstant(0, getPointerTy(), true),
                             InFlag);
  InFlag = Chain.getValue(1);

  // Handle result values, copying them out of physregs into vregs that we
  // return.
  return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
                         DAG, InVals);
}
Esempio n. 5
0
SDValue NvfcTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
  SDValue LHS   = Op.getOperand(0);
  SDValue RHS   = Op.getOperand(1);
  DebugLoc dl   = Op.getDebugLoc();

  // If we are doing an AND and testing against zero, then the CMP
  // will not be generated.  The AND (or OR) will generate the condition codes,
  // but they are different from CMP.
  // FIXME: since we're doing a post-processing, use a pseudoinstr here, so
  // lowering & isel wouldn't diverge.
  bool andCC = false;
  if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
    if (RHSC->isNullValue() && LHS.hasOneUse() &&
        (LHS.getOpcode() == ISD::AND ||
         (LHS.getOpcode() == ISD::TRUNCATE &&
          LHS.getOperand(0).getOpcode() == ISD::AND))) {
      andCC = true;
    }
  }
  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
  SDValue TargetCC;
  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);

  // Get the condition codes directly from the status register, if its easy.
  // Otherwise a branch will be generated.  Note that the AND and OR
  // instructions generate different flags than CMP, the carry bit can be used
  // for NE/EQ.
  bool Invert = false;
  bool Convert = true;
  int Shamt = 0; 
  switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) {
   default:
    Convert = false;
    break;
   case NvfcCC::COND_HS:
     // Res = (FLG >> 8) & 1
     Shamt = 8;
     break;
   case NvfcCC::COND_LO:
     // Res = ~((FLG >> 8) & 1)
     Shamt = 8;    
     Invert = true;
     break;
   case NvfcCC::COND_NE:
     if (andCC) {
       // C = ~Z, thus Res = (FLG >> 8) & 1
       Shamt = 8;
     } else {
       // Res = ~((FLG >> 0xb) & 1)
       Shamt = 0xb;
       Invert = true;
     }
     break;
   case NvfcCC::COND_E:
     // Res = (FLG >> 0xb) & 1
     Shamt = 0xb;
     break;
  }
  EVT VT = Op.getValueType();
  SDValue One  = DAG.getConstant(1, VT);
  if (Convert) {
    SDValue Shift = DAG.getConstant(Shamt, VT);
    SDValue FLG = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Nvfc::FLG,
    				     MVT::i32, Flag);
    FLG = DAG.getNode(NvfcISD::XBIT, dl, MVT::i32, FLG, Shift, Flag);
    if (Invert) {
	FLG = DAG.getNode(ISD::XOR, dl, MVT::i32, FLG, One);
	//FLG = DAG.getNode(ISD::NOT, dl, MVT::i32, FLG);
    }
    
    return FLG;
  } else {
    SDValue Zero = DAG.getConstant(0, VT);
    SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
    SmallVector<SDValue, 4> Ops;
    Ops.push_back(One);
    Ops.push_back(Zero);
    Ops.push_back(TargetCC);
    Ops.push_back(Flag);
    return DAG.getNode(NvfcISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
  }
}
Esempio n. 6
0
bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,
                                     SDValue &Base, SDValue &Offset) {
  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(),
                                       getTargetLowering()->getPointerTy());
    Offset = CurDAG->getTargetConstant(0, MVT::i32);
    return true;
  }
  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
      Addr.getOpcode() == ISD::TargetGlobalAddress ||
      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
    return false;  // direct calls.

  if (Addr.getOpcode() == ISD::ADD) {
    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
      if (isInt<13>(CN->getSExtValue())) {
        if (FrameIndexSDNode *FIN =
                dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
          // Constant offset from frame ref.
          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(),
                                           getTargetLowering()->getPointerTy());
        } else {
          Base = Addr.getOperand(0);
        }
        Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
        return true;
      }
    }
    if (Addr.getOperand(0).getOpcode() == SPISD::Lo) {
      Base = Addr.getOperand(1);
      Offset = Addr.getOperand(0).getOperand(0);
      return true;
    }
    if (Addr.getOperand(1).getOpcode() == SPISD::Lo) {
      Base = Addr.getOperand(0);
      Offset = Addr.getOperand(1).getOperand(0);
      return true;
    }
  }
  Base = Addr;
  Offset = CurDAG->getTargetConstant(0, MVT::i32);
  return true;
}
void Mips16TargetLowering::
getOpndList(SmallVectorImpl<SDValue> &Ops,
            std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
            bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
            CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const {
  SelectionDAG &DAG = CLI.DAG;
  MachineFunction &MF = DAG.getMachineFunction();
  MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
  const char* Mips16HelperFunction = nullptr;
  bool NeedMips16Helper = false;

  if (Subtarget.inMips16HardFloat()) {
    //
    // currently we don't have symbols tagged with the mips16 or mips32
    // qualifier so we will assume that we don't know what kind it is.
    // and generate the helper
    //
    bool LookupHelper = true;
    if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
      Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };

      if (std::binary_search(std::begin(HardFloatLibCalls),
                             std::end(HardFloatLibCalls), Find))
        LookupHelper = false;
      else {
        const char *Symbol = S->getSymbol();
        Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };
        const Mips16HardFloatInfo::FuncSignature *Signature =
            Mips16HardFloatInfo::findFuncSignature(Symbol);
        if (!IsPICCall && (Signature && (FuncInfo->StubsNeeded.find(Symbol) ==
                                         FuncInfo->StubsNeeded.end()))) {
          FuncInfo->StubsNeeded[Symbol] = Signature;
          //
          // S2 is normally saved if the stub is for a function which
          // returns a float or double value and is not otherwise. This is
          // because more work is required after the function the stub
          // is calling completes, and so the stub cannot directly return
          // and the stub has no stack space to store the return address so
          // S2 is used for that purpose.
          // In order to take advantage of not saving S2, we need to also
          // optimize the call in the stub and this requires some further
          // functionality in MipsAsmPrinter which we don't have yet.
          // So for now we always save S2. The optimization will be done
          // in a follow-on patch.
          //
          if (1 || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))
            FuncInfo->setSaveS2();
        }
        // one more look at list of intrinsics
        const Mips16IntrinsicHelperType *Helper =
            std::lower_bound(std::begin(Mips16IntrinsicHelper),
                             std::end(Mips16IntrinsicHelper), IntrinsicFind);
        if (Helper != std::end(Mips16IntrinsicHelper) &&
            *Helper == IntrinsicFind) {
          Mips16HelperFunction = Helper->Helper;
          NeedMips16Helper = true;
          LookupHelper = false;
        }

      }
    } else if (GlobalAddressSDNode *G =
                   dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
      Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,
                             G->getGlobal()->getName().data() };

      if (std::binary_search(std::begin(HardFloatLibCalls),
                             std::end(HardFloatLibCalls), Find))
        LookupHelper = false;
    }
    if (LookupHelper)
      Mips16HelperFunction =
        getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
  }

  SDValue JumpTarget = Callee;

  // T9 should contain the address of the callee function if
  // -reloction-model=pic or it is an indirect call.
  if (IsPICCall || !GlobalOrExternal) {
    unsigned V0Reg = Mips::V0;
    if (NeedMips16Helper) {
      RegsToPass.push_front(std::make_pair(V0Reg, Callee));
      JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, getPointerTy());
      ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);
      JumpTarget = getAddrGlobal(S, JumpTarget.getValueType(), DAG,
                                 MipsII::MO_GOT, Chain,
                                 FuncInfo->callPtrInfo(S->getSymbol()));
    } else
      RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));
  }

  Ops.push_back(JumpTarget);

  MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
                                  InternalLinkage, CLI, Callee, Chain);
}
Esempio n. 8
0
SDValue X86SelectionDAGInfo::EmitTargetCodeForMemcpy(
    SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src,
    SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline,
    MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
  // This requires the copy size to be a constant, preferably
  // within a subtarget-specific limit.
  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
  const X86Subtarget &Subtarget =
      DAG.getMachineFunction().getSubtarget<X86Subtarget>();
  if (!ConstantSize)
    return SDValue();
  uint64_t SizeVal = ConstantSize->getZExtValue();
  if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold())
    return SDValue();

  /// If not DWORD aligned, it is more efficient to call the library.  However
  /// if calling the library is not allowed (AlwaysInline), then soldier on as
  /// the code generated here is better than the long load-store sequence we
  /// would otherwise get.
  if (!AlwaysInline && (Align & 3) != 0)
    return SDValue();

  // If to a segment-relative address space, use the default lowering.
  if (DstPtrInfo.getAddrSpace() >= 256 ||
      SrcPtrInfo.getAddrSpace() >= 256)
    return SDValue();

  // If the base register might conflict with our physical registers, bail out.
  const unsigned ClobberSet[] = {X86::RCX, X86::RSI, X86::RDI,
                                 X86::ECX, X86::ESI, X86::EDI};
  if (isBaseRegConflictPossible(DAG, ClobberSet))
    return SDValue();

  MVT AVT;
  if (Align & 1)
    AVT = MVT::i8;
  else if (Align & 2)
    AVT = MVT::i16;
  else if (Align & 4)
    // DWORD aligned
    AVT = MVT::i32;
  else
    // QWORD aligned
    AVT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32;

  unsigned UBytes = AVT.getSizeInBits() / 8;
  unsigned CountVal = SizeVal / UBytes;
  SDValue Count = DAG.getIntPtrConstant(CountVal, dl);
  unsigned BytesLeft = SizeVal % UBytes;

  SDValue InFlag;
  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : X86::ECX,
                           Count, InFlag);
  InFlag = Chain.getValue(1);
  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : X86::EDI,
                           Dst, InFlag);
  InFlag = Chain.getValue(1);
  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RSI : X86::ESI,
                           Src, InFlag);
  InFlag = Chain.getValue(1);

  SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
  SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops);

  SmallVector<SDValue, 4> Results;
  Results.push_back(RepMovs);
  if (BytesLeft) {
    // Handle the last 1 - 7 bytes.
    unsigned Offset = SizeVal - BytesLeft;
    EVT DstVT = Dst.getValueType();
    EVT SrcVT = Src.getValueType();
    EVT SizeVT = Size.getValueType();
    Results.push_back(DAG.getMemcpy(Chain, dl,
                                    DAG.getNode(ISD::ADD, dl, DstVT, Dst,
                                                DAG.getConstant(Offset, dl,
                                                                DstVT)),
                                    DAG.getNode(ISD::ADD, dl, SrcVT, Src,
                                                DAG.getConstant(Offset, dl,
                                                                SrcVT)),
                                    DAG.getConstant(BytesLeft, dl, SizeVT),
                                    Align, isVolatile, AlwaysInline, false,
                                    DstPtrInfo.getWithOffset(Offset),
                                    SrcPtrInfo.getWithOffset(Offset)));
  }

  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Results);
}
Esempio n. 9
0
SDValue X86SelectionDAGInfo::EmitTargetCodeForMemset(
    SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src,
    SDValue Size, unsigned Align, bool isVolatile,
    MachinePointerInfo DstPtrInfo) const {
  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
  const X86Subtarget &Subtarget =
      DAG.getMachineFunction().getSubtarget<X86Subtarget>();

#ifndef NDEBUG
  // If the base register might conflict with our physical registers, bail out.
  const unsigned ClobberSet[] = {X86::RCX, X86::RAX, X86::RDI,
                                 X86::ECX, X86::EAX, X86::EDI};
  assert(!isBaseRegConflictPossible(DAG, ClobberSet));
#endif

  // If to a segment-relative address space, use the default lowering.
  if (DstPtrInfo.getAddrSpace() >= 256)
    return SDValue();

  // If not DWORD aligned or size is more than the threshold, call the library.
  // The libc version is likely to be faster for these cases. It can use the
  // address value and run time information about the CPU.
  if ((Align & 3) != 0 || !ConstantSize ||
      ConstantSize->getZExtValue() > Subtarget.getMaxInlineSizeThreshold()) {
    // Check to see if there is a specialized entry-point for memory zeroing.
    ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src);

    if (const char *bzeroEntry = V &&
        V->isNullValue() ? Subtarget.getBZeroEntry() : nullptr) {
      const TargetLowering &TLI = DAG.getTargetLoweringInfo();
      EVT IntPtr = TLI.getPointerTy(DAG.getDataLayout());
      Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
      TargetLowering::ArgListTy Args;
      TargetLowering::ArgListEntry Entry;
      Entry.Node = Dst;
      Entry.Ty = IntPtrTy;
      Args.push_back(Entry);
      Entry.Node = Size;
      Args.push_back(Entry);

      TargetLowering::CallLoweringInfo CLI(DAG);
      CLI.setDebugLoc(dl).setChain(Chain)
        .setCallee(CallingConv::C, Type::getVoidTy(*DAG.getContext()),
                   DAG.getExternalSymbol(bzeroEntry, IntPtr), std::move(Args),
                   0)
        .setDiscardResult();

      std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI);
      return CallResult.second;
    }

    // Otherwise have the target-independent code call memset.
    return SDValue();
  }

  uint64_t SizeVal = ConstantSize->getZExtValue();
  SDValue InFlag;
  EVT AVT;
  SDValue Count;
  ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
  unsigned BytesLeft = 0;
  bool TwoRepStos = false;
  if (ValC) {
    unsigned ValReg;
    uint64_t Val = ValC->getZExtValue() & 255;

    // If the value is a constant, then we can potentially use larger sets.
    switch (Align & 3) {
    case 2:   // WORD aligned
      AVT = MVT::i16;
      ValReg = X86::AX;
      Val = (Val << 8) | Val;
      break;
    case 0:  // DWORD aligned
      AVT = MVT::i32;
      ValReg = X86::EAX;
      Val = (Val << 8)  | Val;
      Val = (Val << 16) | Val;
      if (Subtarget.is64Bit() && ((Align & 0x7) == 0)) {  // QWORD aligned
        AVT = MVT::i64;
        ValReg = X86::RAX;
        Val = (Val << 32) | Val;
      }
      break;
    default:  // Byte aligned
      AVT = MVT::i8;
      ValReg = X86::AL;
      Count = DAG.getIntPtrConstant(SizeVal, dl);
      break;
    }

    if (AVT.bitsGT(MVT::i8)) {
      unsigned UBytes = AVT.getSizeInBits() / 8;
      Count = DAG.getIntPtrConstant(SizeVal / UBytes, dl);
      BytesLeft = SizeVal % UBytes;
    }

    Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, dl, AVT),
                             InFlag);
    InFlag = Chain.getValue(1);
  } else {
    AVT = MVT::i8;
    Count  = DAG.getIntPtrConstant(SizeVal, dl);
    Chain  = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
    InFlag = Chain.getValue(1);
  }

  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : X86::ECX,
                           Count, InFlag);
  InFlag = Chain.getValue(1);
  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : X86::EDI,
                           Dst, InFlag);
  InFlag = Chain.getValue(1);

  SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
  Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);

  if (TwoRepStos) {
    InFlag = Chain.getValue(1);
    Count  = Size;
    EVT CVT = Count.getValueType();
    SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
                               DAG.getConstant((AVT == MVT::i64) ? 7 : 3, dl,
                                               CVT));
    Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX : X86::ECX,
                             Left, InFlag);
    InFlag = Chain.getValue(1);
    Tys = DAG.getVTList(MVT::Other, MVT::Glue);
    SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
    Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);
  } else if (BytesLeft) {
    // Handle the last 1 - 7 bytes.
    unsigned Offset = SizeVal - BytesLeft;
    EVT AddrVT = Dst.getValueType();
    EVT SizeVT = Size.getValueType();

    Chain = DAG.getMemset(Chain, dl,
                          DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
                                      DAG.getConstant(Offset, dl, AddrVT)),
                          Src,
                          DAG.getConstant(BytesLeft, dl, SizeVT),
                          Align, isVolatile, false,
                          DstPtrInfo.getWithOffset(Offset));
  }

  // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
  return Chain;
}
Esempio n. 10
0
// Emit, if possible, a specialized version of the given Libcall. Typically this
// means selecting the appropriately aligned version, but we also convert memset
// of 0 into memclr.
SDValue ARMSelectionDAGInfo::EmitSpecializedLibcall(
    SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
    SDValue Size, unsigned Align, RTLIB::Libcall LC) const {
  const ARMSubtarget &Subtarget =
      DAG.getMachineFunction().getSubtarget<ARMSubtarget>();
  const ARMTargetLowering *TLI = Subtarget.getTargetLowering();

  // Only use a specialized AEABI function if the default version of this
  // Libcall is an AEABI function.
  if (std::strncmp(TLI->getLibcallName(LC), "__aeabi", 7) != 0)
    return SDValue();

  // Translate RTLIB::Libcall to AEABILibcall. We only do this in order to be
  // able to translate memset to memclr and use the value to index the function
  // name array.
  enum {
    AEABI_MEMCPY = 0,
    AEABI_MEMMOVE,
    AEABI_MEMSET,
    AEABI_MEMCLR
  } AEABILibcall;
  switch (LC) {
  case RTLIB::MEMCPY:
    AEABILibcall = AEABI_MEMCPY;
    break;
  case RTLIB::MEMMOVE:
    AEABILibcall = AEABI_MEMMOVE;
    break;
  case RTLIB::MEMSET: 
    AEABILibcall = AEABI_MEMSET;
    if (ConstantSDNode *ConstantSrc = dyn_cast<ConstantSDNode>(Src))
      if (ConstantSrc->getZExtValue() == 0)
        AEABILibcall = AEABI_MEMCLR;
    break;
  default:
    return SDValue();
  }

  // Choose the most-aligned libcall variant that we can
  enum {
    ALIGN1 = 0,
    ALIGN4,
    ALIGN8
  } AlignVariant;
  if ((Align & 7) == 0)
    AlignVariant = ALIGN8;
  else if ((Align & 3) == 0)
    AlignVariant = ALIGN4;
  else
    AlignVariant = ALIGN1;

  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
  Entry.Node = Dst;
  Args.push_back(Entry);
  if (AEABILibcall == AEABI_MEMCLR) {
    Entry.Node = Size;
    Args.push_back(Entry);
  } else if (AEABILibcall == AEABI_MEMSET) {
    // Adjust parameters for memset, EABI uses format (ptr, size, value),
    // GNU library uses (ptr, value, size)
    // See RTABI section 4.3.4
    Entry.Node = Size;
    Args.push_back(Entry);

    // Extend or truncate the argument to be an i32 value for the call.
    if (Src.getValueType().bitsGT(MVT::i32))
      Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src);
    else if (Src.getValueType().bitsLT(MVT::i32))
      Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);

    Entry.Node = Src; 
    Entry.Ty = Type::getInt32Ty(*DAG.getContext());
    Entry.isSExt = false;
    Args.push_back(Entry);
  } else {
    Entry.Node = Src;
    Args.push_back(Entry);
    
    Entry.Node = Size;
    Args.push_back(Entry);
  }

  char const *FunctionNames[4][3] = {
    { "__aeabi_memcpy",  "__aeabi_memcpy4",  "__aeabi_memcpy8"  },
    { "__aeabi_memmove", "__aeabi_memmove4", "__aeabi_memmove8" },
    { "__aeabi_memset",  "__aeabi_memset4",  "__aeabi_memset8"  },
    { "__aeabi_memclr",  "__aeabi_memclr4",  "__aeabi_memclr8"  }
  };
  TargetLowering::CallLoweringInfo CLI(DAG);
  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setCallee(
           TLI->getLibcallCallingConv(LC), Type::getVoidTy(*DAG.getContext()),
           DAG.getExternalSymbol(FunctionNames[AEABILibcall][AlignVariant],
                                 TLI->getPointerTy(DAG.getDataLayout())),
           std::move(Args))
      .setDiscardResult();
  std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
  
  return CallResult.second;
}
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) {
  unsigned Opcode = Node->getOpcode();
  DebugLoc dl = Node->getDebugLoc();

  // If we have a custom node, we already have selected!
  if (Node->isMachineOpcode())
    return NULL;

  ///
  // Instruction Selection not handled by the auto-generated
  // tablegen selection should be handled here.
  ///
  switch (Opcode) {
    default: break;

    // Get target GOT address.
    case ISD::GLOBAL_OFFSET_TABLE:
      return getGlobalBaseReg();

    case ISD::FrameIndex: {
        SDValue imm = CurDAG->getTargetConstant(0, MVT::i32);
        int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
        EVT VT = Node->getValueType(0);
        SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
        unsigned Opc = MBlaze::ADDIK;
        if (Node->hasOneUse())
          return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm);
        return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm);
    }


    /// Handle direct and indirect calls when using PIC. On PIC, when
    /// GOT is smaller than about 64k (small code) the GA target is
    /// loaded with only one instruction. Otherwise GA's target must
    /// be loaded with 3 instructions.
    case MBlazeISD::JmpLink: {
      if (TM.getRelocationModel() == Reloc::PIC_) {
        SDValue Chain  = Node->getOperand(0);
        SDValue Callee = Node->getOperand(1);
        SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32);
        SDValue InFlag(0, 0);

        if ((isa<GlobalAddressSDNode>(Callee)) ||
            (isa<ExternalSymbolSDNode>(Callee)))
        {
          /// Direct call for global addresses and external symbols
          SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32);

          // Use load to get GOT target
          SDValue Ops[] = { Callee, GPReg, Chain };
          SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl,
                                 MVT::i32, MVT::Other, Ops), 0);
          Chain = Load.getValue(1);

          // Call target must be on T9
          Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag);
        } else
          /// Indirect call
          Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag);

        // Emit Jump and Link Register
        SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other,
                                                 MVT::Glue, R20Reg, Chain);
        Chain  = SDValue(ResNode, 0);
        InFlag = SDValue(ResNode, 1);
        ReplaceUses(SDValue(Node, 0), Chain);
        ReplaceUses(SDValue(Node, 1), InFlag);
        return ResNode;
      }
    }
  }

  // Select the default instruction
  SDNode *ResNode = SelectCode(Node);

  DEBUG(errs() << "=> ");
  if (ResNode == NULL || ResNode == Node)
    DEBUG(Node->dump(CurDAG));
  else
    DEBUG(ResNode->dump(CurDAG));
  DEBUG(errs() << "\n");
  return ResNode;
}
Esempio n. 12
0
SDValue ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(
    SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
    SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline,
    MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
  const ARMSubtarget &Subtarget =
      DAG.getMachineFunction().getSubtarget<ARMSubtarget>();
  // Do repeated 4-byte loads and stores. To be improved.
  // This requires 4-byte alignment.
  if ((Align & 3) != 0)
    return SDValue();
  // This requires the copy size to be a constant, preferably
  // within a subtarget-specific limit.
  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
  if (!ConstantSize)
    return EmitSpecializedLibcall(DAG, dl, Chain, Dst, Src, Size, Align,
                                  RTLIB::MEMCPY);
  uint64_t SizeVal = ConstantSize->getZExtValue();
  if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold())
    return EmitSpecializedLibcall(DAG, dl, Chain, Dst, Src, Size, Align,
                                  RTLIB::MEMCPY);

  unsigned BytesLeft = SizeVal & 3;
  unsigned NumMemOps = SizeVal >> 2;
  unsigned EmittedNumMemOps = 0;
  EVT VT = MVT::i32;
  unsigned VTSize = 4;
  unsigned i = 0;
  // Emit a maximum of 4 loads in Thumb1 since we have fewer registers
  const unsigned MaxLoadsInLDM = Subtarget.isThumb1Only() ? 4 : 6;
  SDValue TFOps[6];
  SDValue Loads[6];
  uint64_t SrcOff = 0, DstOff = 0;

  // FIXME: We should invent a VMEMCPY pseudo-instruction that lowers to
  // VLDM/VSTM and make this code emit it when appropriate. This would reduce
  // pressure on the general purpose registers. However this seems harder to map
  // onto the register allocator's view of the world.

  // The number of MEMCPY pseudo-instructions to emit. We use up to
  // MaxLoadsInLDM registers per mcopy, which will get lowered into ldm/stm
  // later on. This is a lower bound on the number of MEMCPY operations we must
  // emit.
  unsigned NumMEMCPYs = (NumMemOps + MaxLoadsInLDM - 1) / MaxLoadsInLDM;

  // Code size optimisation: do not inline memcpy if expansion results in
  // more instructions than the libary call.
  if (NumMEMCPYs > 1 && DAG.getMachineFunction().getFunction()->optForMinSize()) {
    return SDValue();
  }

  SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other, MVT::Glue);

  for (unsigned I = 0; I != NumMEMCPYs; ++I) {
    // Evenly distribute registers among MEMCPY operations to reduce register
    // pressure.
    unsigned NextEmittedNumMemOps = NumMemOps * (I + 1) / NumMEMCPYs;
    unsigned NumRegs = NextEmittedNumMemOps - EmittedNumMemOps;

    Dst = DAG.getNode(ARMISD::MEMCPY, dl, VTs, Chain, Dst, Src,
                      DAG.getConstant(NumRegs, dl, MVT::i32));
    Src = Dst.getValue(1);
    Chain = Dst.getValue(2);

    DstPtrInfo = DstPtrInfo.getWithOffset(NumRegs * VTSize);
    SrcPtrInfo = SrcPtrInfo.getWithOffset(NumRegs * VTSize);

    EmittedNumMemOps = NextEmittedNumMemOps;
  }

  if (BytesLeft == 0)
    return Chain;

  // Issue loads / stores for the trailing (1 - 3) bytes.
  unsigned BytesLeftSave = BytesLeft;
  i = 0;
  while (BytesLeft) {
    if (BytesLeft >= 2) {
      VT = MVT::i16;
      VTSize = 2;
    } else {
      VT = MVT::i8;
      VTSize = 1;
    }

    Loads[i] = DAG.getLoad(VT, dl, Chain,
                           DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
                                       DAG.getConstant(SrcOff, dl, MVT::i32)),
                           SrcPtrInfo.getWithOffset(SrcOff));
    TFOps[i] = Loads[i].getValue(1);
    ++i;
    SrcOff += VTSize;
    BytesLeft -= VTSize;
  }
  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                      makeArrayRef(TFOps, i));

  i = 0;
  BytesLeft = BytesLeftSave;
  while (BytesLeft) {
    if (BytesLeft >= 2) {
      VT = MVT::i16;
      VTSize = 2;
    } else {
      VT = MVT::i8;
      VTSize = 1;
    }

    TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
                            DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
                                        DAG.getConstant(DstOff, dl, MVT::i32)),
                            DstPtrInfo.getWithOffset(DstOff));
    ++i;
    DstOff += VTSize;
    BytesLeft -= VTSize;
  }
  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                     makeArrayRef(TFOps, i));
}
Esempio n. 13
0
/// PerformExpensiveChecks - Do extensive, expensive, sanity checking.
void DAGTypeLegalizer::PerformExpensiveChecks() {
  // If a node is not processed, then none of its values should be mapped by any
  // of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues.

  // If a node is processed, then each value with an illegal type must be mapped
  // by exactly one of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues.
  // Values with a legal type may be mapped by ReplacedValues, but not by any of
  // the other maps.

  // Note that these invariants may not hold momentarily when processing a node:
  // the node being processed may be put in a map before being marked Processed.

  // Note that it is possible to have nodes marked NewNode in the DAG.  This can
  // occur in two ways.  Firstly, a node may be created during legalization but
  // never passed to the legalization core.  This is usually due to the implicit
  // folding that occurs when using the DAG.getNode operators.  Secondly, a new
  // node may be passed to the legalization core, but when analyzed may morph
  // into a different node, leaving the original node as a NewNode in the DAG.
  // A node may morph if one of its operands changes during analysis.  Whether
  // it actually morphs or not depends on whether, after updating its operands,
  // it is equivalent to an existing node: if so, it morphs into that existing
  // node (CSE).  An operand can change during analysis if the operand is a new
  // node that morphs, or it is a processed value that was mapped to some other
  // value (as recorded in ReplacedValues) in which case the operand is turned
  // into that other value.  If a node morphs then the node it morphed into will
  // be used instead of it for legalization, however the original node continues
  // to live on in the DAG.
  // The conclusion is that though there may be nodes marked NewNode in the DAG,
  // all uses of such nodes are also marked NewNode: the result is a fungus of
  // NewNodes growing on top of the useful nodes, and perhaps using them, but
  // not used by them.

  // If a value is mapped by ReplacedValues, then it must have no uses, except
  // by nodes marked NewNode (see above).

  // The final node obtained by mapping by ReplacedValues is not marked NewNode.
  // Note that ReplacedValues should be applied iteratively.

  // Note that the ReplacedValues map may also map deleted nodes (by iterating
  // over the DAG we never dereference deleted nodes).  This means that it may
  // also map nodes marked NewNode if the deallocated memory was reallocated as
  // another node, and that new node was not seen by the LegalizeTypes machinery
  // (for example because it was created but not used).  In general, we cannot
  // distinguish between new nodes and deleted nodes.
  SmallVector<SDNode*, 16> NewNodes;
  for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
       E = DAG.allnodes_end(); I != E; ++I) {
    // Remember nodes marked NewNode - they are subject to extra checking below.
    if (I->getNodeId() == NewNode)
      NewNodes.push_back(I);

    for (unsigned i = 0, e = I->getNumValues(); i != e; ++i) {
      SDValue Res(I, i);
      bool Failed = false;

      unsigned Mapped = 0;
      if (ReplacedValues.find(Res) != ReplacedValues.end()) {
        Mapped |= 1;
        // Check that remapped values are only used by nodes marked NewNode.
        for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end();
             UI != UE; ++UI)
          if (UI.getUse().getResNo() == i)
            assert(UI->getNodeId() == NewNode &&
                   "Remapped value has non-trivial use!");

        // Check that the final result of applying ReplacedValues is not
        // marked NewNode.
        SDValue NewVal = ReplacedValues[Res];
        DenseMap<SDValue, SDValue>::iterator I = ReplacedValues.find(NewVal);
        while (I != ReplacedValues.end()) {
          NewVal = I->second;
          I = ReplacedValues.find(NewVal);
        }
        assert(NewVal.getNode()->getNodeId() != NewNode &&
               "ReplacedValues maps to a new node!");
      }
      if (PromotedIntegers.find(Res) != PromotedIntegers.end())
        Mapped |= 2;
      if (SoftenedFloats.find(Res) != SoftenedFloats.end())
        Mapped |= 4;
      if (ScalarizedVectors.find(Res) != ScalarizedVectors.end())
        Mapped |= 8;
      if (ExpandedIntegers.find(Res) != ExpandedIntegers.end())
        Mapped |= 16;
      if (ExpandedFloats.find(Res) != ExpandedFloats.end())
        Mapped |= 32;
      if (SplitVectors.find(Res) != SplitVectors.end())
        Mapped |= 64;
      if (WidenedVectors.find(Res) != WidenedVectors.end())
        Mapped |= 128;

      if (I->getNodeId() != Processed) {
        // Since we allow ReplacedValues to map deleted nodes, it may map nodes
        // marked NewNode too, since a deleted node may have been reallocated as
        // another node that has not been seen by the LegalizeTypes machinery.
        if ((I->getNodeId() == NewNode && Mapped > 1) ||
            (I->getNodeId() != NewNode && Mapped != 0)) {
          dbgs() << "Unprocessed value in a map!";
          Failed = true;
        }
      } else if (isTypeLegal(Res.getValueType()) || IgnoreNodeResults(I)) {
        if (Mapped > 1) {
          dbgs() << "Value with legal type was transformed!";
          Failed = true;
        }
      } else {
        if (Mapped == 0) {
          dbgs() << "Processed value not in any map!";
          Failed = true;
        } else if (Mapped & (Mapped - 1)) {
          dbgs() << "Value in multiple maps!";
          Failed = true;
        }
      }

      if (Failed) {
        if (Mapped & 1)
          dbgs() << " ReplacedValues";
        if (Mapped & 2)
          dbgs() << " PromotedIntegers";
        if (Mapped & 4)
          dbgs() << " SoftenedFloats";
        if (Mapped & 8)
          dbgs() << " ScalarizedVectors";
        if (Mapped & 16)
          dbgs() << " ExpandedIntegers";
        if (Mapped & 32)
          dbgs() << " ExpandedFloats";
        if (Mapped & 64)
          dbgs() << " SplitVectors";
        if (Mapped & 128)
          dbgs() << " WidenedVectors";
        dbgs() << "\n";
        llvm_unreachable(0);
      }
    }
  }

  // Checked that NewNodes are only used by other NewNodes.
  for (unsigned i = 0, e = NewNodes.size(); i != e; ++i) {
    SDNode *N = NewNodes[i];
    for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
         UI != UE; ++UI)
      assert(UI->getNodeId() == NewNode && "NewNode used by non-NewNode!");
  }
}
Esempio n. 14
0
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void InstrEmitter::
EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned,
                unsigned SrcReg, DenseMap<SDValue, unsigned> &VRBaseMap) {
    unsigned VRBase = 0;
    if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
        // Just use the input register directly!
        SDValue Op(Node, ResNo);
        if (IsClone)
            VRBaseMap.erase(Op);
        bool isNew = VRBaseMap.insert(std::make_pair(Op, SrcReg)).second;
        (void)isNew; // Silence compiler warning.
        assert(isNew && "Node emitted out of order - early");
        return;
    }

    // If the node is only used by a CopyToReg and the dest reg is a vreg, use
    // the CopyToReg'd destination register instead of creating a new vreg.
    bool MatchReg = true;
    const TargetRegisterClass *UseRC = NULL;
    EVT VT = Node->getValueType(ResNo);

    // Stick to the preferred register classes for legal types.
    if (TLI->isTypeLegal(VT))
        UseRC = TLI->getRegClassFor(VT);

    if (!IsClone && !IsCloned)
        for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
                UI != E; ++UI) {
            SDNode *User = *UI;
            bool Match = true;
            if (User->getOpcode() == ISD::CopyToReg &&
                    User->getOperand(2).getNode() == Node &&
                    User->getOperand(2).getResNo() == ResNo) {
                unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
                if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
                    VRBase = DestReg;
                    Match = false;
                } else if (DestReg != SrcReg)
                    Match = false;
            } else {
                for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
                    SDValue Op = User->getOperand(i);
                    if (Op.getNode() != Node || Op.getResNo() != ResNo)
                        continue;
                    EVT VT = Node->getValueType(Op.getResNo());
                    if (VT == MVT::Other || VT == MVT::Glue)
                        continue;
                    Match = false;
                    if (User->isMachineOpcode()) {
                        const MCInstrDesc &II = TII->get(User->getMachineOpcode());
                        const TargetRegisterClass *RC = 0;
                        if (i+II.getNumDefs() < II.getNumOperands())
                            RC = TII->getRegClass(II, i+II.getNumDefs(), TRI);
                        if (!UseRC)
                            UseRC = RC;
                        else if (RC) {
                            const TargetRegisterClass *ComRC =
                                TRI->getCommonSubClass(UseRC, RC);
                            // If multiple uses expect disjoint register classes, we emit
                            // copies in AddRegisterOperand.
                            if (ComRC)
                                UseRC = ComRC;
                        }
                    }
                }
            }
            MatchReg &= Match;
            if (VRBase)
                break;
        }

    const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
    SrcRC = TRI->getMinimalPhysRegClass(SrcReg, VT);

    // Figure out the register class to create for the destreg.
    if (VRBase) {
        DstRC = MRI->getRegClass(VRBase);
    } else if (UseRC) {
        assert(UseRC->hasType(VT) && "Incompatible phys register def and uses!");
        DstRC = UseRC;
    } else {
        DstRC = TLI->getRegClassFor(VT);
    }

    // If all uses are reading from the src physical register and copying the
    // register is either impossible or very expensive, then don't create a copy.
    if (MatchReg && SrcRC->getCopyCost() < 0) {
        VRBase = SrcReg;
    } else {
        // Create the reg, emit the copy.
        VRBase = MRI->createVirtualRegister(DstRC);
        BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY),
                VRBase).addReg(SrcReg);
    }

    SDValue Op(Node, ResNo);
    if (IsClone)
        VRBaseMap.erase(Op);
    bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
    (void)isNew; // Silence compiler warning.
    assert(isNew && "Node emitted out of order - early");
}
Esempio n. 15
0
SDValue LanaiTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
  EVT VT = Op->getValueType(0);
  if (VT != MVT::i32)
    return SDValue();

  ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op->getOperand(1));
  if (!C)
    return SDValue();

  int64_t MulAmt = C->getSExtValue();
  int32_t HighestOne = -1;
  uint32_t NonzeroEntries = 0;
  int SignedDigit[32] = {0};

  // Convert to non-adjacent form (NAF) signed-digit representation.
  // NAF is a signed-digit form where no adjacent digits are non-zero. It is the
  // minimal Hamming weight representation of a number (on average 1/3 of the
  // digits will be non-zero vs 1/2 for regular binary representation). And as
  // the non-zero digits will be the only digits contributing to the instruction
  // count, this is desirable. The next loop converts it to NAF (following the
  // approach in 'Guide to Elliptic Curve Cryptography' [ISBN: 038795273X]) by
  // choosing the non-zero coefficients such that the resulting quotient is
  // divisible by 2 which will cause the next coefficient to be zero.
  int64_t E = std::abs(MulAmt);
  int S = (MulAmt < 0 ? -1 : 1);
  int I = 0;
  while (E > 0) {
    int ZI = 0;
    if (E % 2 == 1) {
      ZI = 2 - (E % 4);
      if (ZI != 0)
        ++NonzeroEntries;
    }
    SignedDigit[I] = S * ZI;
    if (SignedDigit[I] == 1)
      HighestOne = I;
    E = (E - ZI) / 2;
    ++I;
  }

  // Compute number of instructions required. Due to differences in lowering
  // between the different processors this count is not exact.
  // Start by assuming a shift and a add/sub for every non-zero entry (hence
  // every non-zero entry requires 1 shift and 1 add/sub except for the first
  // entry).
  int32_t InstrRequired = 2 * NonzeroEntries - 1;
  // Correct possible over-adding due to shift by 0 (which is not emitted).
  if (std::abs(MulAmt) % 2 == 1)
    --InstrRequired;
  // Return if the form generated would exceed the instruction threshold.
  if (InstrRequired > LanaiLowerConstantMulThreshold)
    return SDValue();

  SDValue Res;
  SDLoc DL(Op);
  SDValue V = Op->getOperand(0);

  // Initialize the running sum. Set the running sum to the maximal shifted
  // positive value (i.e., largest i such that zi == 1 and MulAmt has V<<i as a
  // term NAF).
  if (HighestOne == -1)
    Res = DAG.getConstant(0, DL, MVT::i32);
  else {
    Res = DAG.getNode(ISD::SHL, DL, VT, V,
                      DAG.getConstant(HighestOne, DL, MVT::i32));
    SignedDigit[HighestOne] = 0;
  }

  // Assemble multiplication from shift, add, sub using NAF form and running
  // sum.
  for (unsigned int I = 0; I < sizeof(SignedDigit) / sizeof(SignedDigit[0]);
       ++I) {
    if (SignedDigit[I] == 0)
      continue;

    // Shifted multiplicand (v<<i).
    SDValue Op =
        DAG.getNode(ISD::SHL, DL, VT, V, DAG.getConstant(I, DL, MVT::i32));
    if (SignedDigit[I] == 1)
      Res = DAG.getNode(ISD::ADD, DL, VT, Res, Op);
    else if (SignedDigit[I] == -1)
      Res = DAG.getNode(ISD::SUB, DL, VT, Res, Op);
  }
  return Res;
}
Esempio n. 16
0
bool XCoreDAGToDAGISel::tryBRIND(SDNode *N) {
  SDLoc dl(N);
  // (brind (int_xcore_checkevent (addr)))
  SDValue Chain = N->getOperand(0);
  SDValue Addr = N->getOperand(1);
  if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
    return false;
  unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue();
  if (IntNo != Intrinsic::xcore_checkevent)
    return false;
  SDValue nextAddr = Addr->getOperand(2);
  SDValue CheckEventChainOut(Addr.getNode(), 1);
  if (!CheckEventChainOut.use_empty()) {
    // If the chain out of the checkevent intrinsic is an operand of the
    // indirect branch or used in a TokenFactor which is the operand of the
    // indirect branch then build a new chain which uses the chain coming into
    // the checkevent intrinsic instead.
    SDValue CheckEventChainIn = Addr->getOperand(0);
    SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
                                      CheckEventChainIn);
    if (!NewChain.getNode())
      return false;
    Chain = NewChain;
  }
  // Enable events on the thread using setsr 1 and then disable them immediately
  // after with clrsr 1. If any resources owned by the thread are ready an event
  // will be taken. If no resource is ready we branch to the address which was
  // the operand to the checkevent intrinsic.
  SDValue constOne = getI32Imm(1, dl);
  SDValue Glue =
    SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
                                   constOne, Chain), 0);
  Glue =
    SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
                                   constOne, Glue), 0);
  if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
      nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
    CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
                         nextAddr->getOperand(0), Glue);
    return true;
  }
  CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
  return true;
}
void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo,
                                             SDValue &Hi) {
  EVT OutVT = N->getValueType(0);
  EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT);
  SDValue InOp = N->getOperand(0);
  EVT InVT = InOp.getValueType();
  DebugLoc dl = N->getDebugLoc();

  // Handle some special cases efficiently.
  switch (getTypeAction(InVT)) {
    default:
      assert(false && "Unknown type action!");
    case Legal:
    case PromoteInteger:
      break;
    case SoftenFloat:
      // Convert the integer operand instead.
      SplitInteger(GetSoftenedFloat(InOp), Lo, Hi);
      Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo);
      Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi);
      return;
    case ExpandInteger:
    case ExpandFloat:
      // Convert the expanded pieces of the input.
      GetExpandedOp(InOp, Lo, Hi);
      Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo);
      Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi);
      return;
    case SplitVector:
      GetSplitVector(InOp, Lo, Hi);
      if (TLI.isBigEndian())
        std::swap(Lo, Hi);
      Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo);
      Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi);
      return;
    case ScalarizeVector:
      // Convert the element instead.
      SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi);
      Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo);
      Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi);
      return;
    case WidenVector: {
      assert(!(InVT.getVectorNumElements() & 1) && "Unsupported BIT_CONVERT");
      InOp = GetWidenedVector(InOp);
      EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(),
                                   InVT.getVectorNumElements()/2);
      Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp,
                       DAG.getIntPtrConstant(0));
      Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp,
                       DAG.getIntPtrConstant(InNVT.getVectorNumElements()));
      if (TLI.isBigEndian())
        std::swap(Lo, Hi);
      Lo = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Lo);
      Hi = DAG.getNode(ISD::BIT_CONVERT, dl, NOutVT, Hi);
      return;
    }
  }

  if (InVT.isVector() && OutVT.isInteger()) {
    // Handle cases like i64 = BIT_CONVERT v1i64 on x86, where the operand
    // is legal but the result is not.
    EVT NVT = EVT::getVectorVT(*DAG.getContext(), NOutVT, 2);

    if (isTypeLegal(NVT)) {
      SDValue CastInOp = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, InOp);
      Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp,
                       DAG.getIntPtrConstant(0));
      Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp,
                       DAG.getIntPtrConstant(1));

      if (TLI.isBigEndian())
        std::swap(Lo, Hi);

      return;
    }
  }

  // Lower the bit-convert to a store/load from the stack.
  assert(NOutVT.isByteSized() && "Expanded type not byte sized!");

  // Create the stack frame object.  Make sure it is aligned for both
  // the source and expanded destination types.
  unsigned Alignment =
    TLI.getTargetData()->getPrefTypeAlignment(NOutVT.getTypeForEVT(*DAG.getContext()));
  SDValue StackPtr = DAG.CreateStackTemporary(InVT, Alignment);
  int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
  const Value *SV = PseudoSourceValue::getFixedStack(SPFI);

  // Emit a store to the stack slot.
  SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, SV, 0);

  // Load the first half from the stack slot.
  Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, 0);

  // Increment the pointer to the other half.
  unsigned IncrementSize = NOutVT.getSizeInBits() / 8;
  StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
                         DAG.getIntPtrConstant(IncrementSize));

  // Load the second half from the stack slot.
  Hi = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, IncrementSize, false,
                   MinAlign(Alignment, IncrementSize));

  // Handle endianness of the load.
  if (TLI.isBigEndian())
    std::swap(Lo, Hi);
}
Esempio n. 18
0
bool
SPUDAGToDAGISel::DFormAddressPredicate(SDNode *Op, SDValue N, SDValue &Base,
                                      SDValue &Index, int minOffset,
                                      int maxOffset) {
  unsigned Opc = N.getOpcode();
  EVT PtrTy = SPUtli.getPointerTy();

  if (Opc == ISD::FrameIndex) {
    // Stack frame index must be less than 512 (divided by 16):
    FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(N);
    int FI = int(FIN->getIndex());
    DEBUG(errs() << "SelectDFormAddr: ISD::FrameIndex = "
               << FI << "\n");
    if (SPUFrameLowering::FItoStackOffset(FI) < maxOffset) {
      Base = CurDAG->getTargetConstant(0, PtrTy);
      Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
      return true;
    }
  } else if (Opc == ISD::ADD) {
    // Generated by getelementptr
    const SDValue Op0 = N.getOperand(0);
    const SDValue Op1 = N.getOperand(1);

    if ((Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo)
        || (Op1.getOpcode() == SPUISD::Hi && Op0.getOpcode() == SPUISD::Lo)) {
      Base = CurDAG->getTargetConstant(0, PtrTy);
      Index = N;
      return true;
    } else if (Op1.getOpcode() == ISD::Constant
               || Op1.getOpcode() == ISD::TargetConstant) {
      ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
      int32_t offset = int32_t(CN->getSExtValue());

      if (Op0.getOpcode() == ISD::FrameIndex) {
        FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(Op0);
        int FI = int(FIN->getIndex());
        DEBUG(errs() << "SelectDFormAddr: ISD::ADD offset = " << offset
                   << " frame index = " << FI << "\n");

        if (SPUFrameLowering::FItoStackOffset(FI) < maxOffset) {
          Base = CurDAG->getTargetConstant(offset, PtrTy);
          Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
          return true;
        }
      } else if (offset > minOffset && offset < maxOffset) {
        Base = CurDAG->getTargetConstant(offset, PtrTy);
        Index = Op0;
        return true;
      }
    } else if (Op0.getOpcode() == ISD::Constant
               || Op0.getOpcode() == ISD::TargetConstant) {
      ConstantSDNode *CN = cast<ConstantSDNode>(Op0);
      int32_t offset = int32_t(CN->getSExtValue());

      if (Op1.getOpcode() == ISD::FrameIndex) {
        FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(Op1);
        int FI = int(FIN->getIndex());
        DEBUG(errs() << "SelectDFormAddr: ISD::ADD offset = " << offset
                   << " frame index = " << FI << "\n");

        if (SPUFrameLowering::FItoStackOffset(FI) < maxOffset) {
          Base = CurDAG->getTargetConstant(offset, PtrTy);
          Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
          return true;
        }
      } else if (offset > minOffset && offset < maxOffset) {
        Base = CurDAG->getTargetConstant(offset, PtrTy);
        Index = Op1;
        return true;
      }
    }
  } else if (Opc == SPUISD::IndirectAddr) {
    // Indirect with constant offset -> D-Form address
    const SDValue Op0 = N.getOperand(0);
    const SDValue Op1 = N.getOperand(1);

    if (Op0.getOpcode() == SPUISD::Hi
        && Op1.getOpcode() == SPUISD::Lo) {
      // (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0))
      Base = CurDAG->getTargetConstant(0, PtrTy);
      Index = N;
      return true;
    } else if (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1)) {
      int32_t offset = 0;
      SDValue idxOp;

      if (isa<ConstantSDNode>(Op1)) {
        ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
        offset = int32_t(CN->getSExtValue());
        idxOp = Op0;
      } else if (isa<ConstantSDNode>(Op0)) {
        ConstantSDNode *CN = cast<ConstantSDNode>(Op0);
        offset = int32_t(CN->getSExtValue());
        idxOp = Op1;
      }

      if (offset >= minOffset && offset <= maxOffset) {
        Base = CurDAG->getTargetConstant(offset, PtrTy);
        Index = idxOp;
        return true;
      }
    }
  } else if (Opc == SPUISD::AFormAddr) {
    Base = CurDAG->getTargetConstant(0, N.getValueType());
    Index = N;
    return true;
  } else if (Opc == SPUISD::LDRESULT) {
    Base = CurDAG->getTargetConstant(0, N.getValueType());
    Index = N;
    return true;
  } else if (Opc == ISD::Register
           ||Opc == ISD::CopyFromReg
           ||Opc == ISD::UNDEF
           ||Opc == ISD::Constant) {
    unsigned OpOpc = Op->getOpcode();

    if (OpOpc == ISD::STORE || OpOpc == ISD::LOAD) {
      // Direct load/store without getelementptr
      SDValue Offs;

      Offs = ((OpOpc == ISD::STORE) ? Op->getOperand(3) : Op->getOperand(2));

      if (Offs.getOpcode() == ISD::Constant || Offs.getOpcode() == ISD::UNDEF) {
        if (Offs.getOpcode() == ISD::UNDEF)
          Offs = CurDAG->getTargetConstant(0, Offs.getValueType());

        Base = Offs;
        Index = N;
        return true;
      }
    } else {
      /* If otherwise unadorned, default to D-form address with 0 offset: */
      if (Opc == ISD::CopyFromReg) {
        Index = N.getOperand(1);
      } else {
        Index = N;
      }

      Base = CurDAG->getTargetConstant(0, Index.getValueType());
      return true;
    }
  }

  return false;
}
Esempio n. 19
0
SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
                                     SmallVectorImpl<SDValue> &InVals) const {
  SelectionDAG &DAG = CLI.DAG;
  auto &Outs = CLI.Outs;
  auto &OutVals = CLI.OutVals;
  auto &Ins = CLI.Ins;
  SDValue Chain = CLI.Chain;
  SDValue Callee = CLI.Callee;
  bool &IsTailCall = CLI.IsTailCall;
  CallingConv::ID CallConv = CLI.CallConv;
  bool IsVarArg = CLI.IsVarArg;
  MachineFunction &MF = DAG.getMachineFunction();

  // BPF target does not support tail call optimization.
  IsTailCall = false;

  switch (CallConv) {
  default:
    report_fatal_error("Unsupported calling convention");
  case CallingConv::Fast:
  case CallingConv::C:
    break;
  }

  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());

  CCInfo.AnalyzeCallOperands(Outs, CC_BPF64);

  unsigned NumBytes = CCInfo.getNextStackOffset();

  if (Outs.size() >= 6) {
    DiagnosticInfoUnsupported Err(CLI.DL, *MF.getFunction(),
                                  "too many args to ", Callee);
    DAG.getContext()->diagnose(Err);
  }

  for (auto &Arg : Outs) {
    ISD::ArgFlagsTy Flags = Arg.Flags;
    if (!Flags.isByVal())
      continue;

    DiagnosticInfoUnsupported Err(CLI.DL, *MF.getFunction(),
                                  "pass by value not supported ", Callee);
    DAG.getContext()->diagnose(Err);
  }

  Chain = DAG.getCALLSEQ_START(
      Chain, DAG.getConstant(NumBytes, CLI.DL, getPointerTy(), true), CLI.DL);

  SmallVector<std::pair<unsigned, SDValue>, 5> RegsToPass;

  // Walk arg assignments
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    SDValue Arg = OutVals[i];

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
    default:
      llvm_unreachable("Unknown loc info");
    case CCValAssign::Full:
      break;
    case CCValAssign::SExt:
      Arg = DAG.getNode(ISD::SIGN_EXTEND, CLI.DL, VA.getLocVT(), Arg);
      break;
    case CCValAssign::ZExt:
      Arg = DAG.getNode(ISD::ZERO_EXTEND, CLI.DL, VA.getLocVT(), Arg);
      break;
    case CCValAssign::AExt:
      Arg = DAG.getNode(ISD::ANY_EXTEND, CLI.DL, VA.getLocVT(), Arg);
      break;
    }

    // Push arguments into RegsToPass vector
    if (VA.isRegLoc())
      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
    else
      llvm_unreachable("call arg pass bug");
  }

  SDValue InFlag;

  // Build a sequence of copy-to-reg nodes chained together with token chain and
  // flag operands which copy the outgoing args into registers.  The InFlag in
  // necessary since all emitted instructions must be stuck together.
  for (auto &Reg : RegsToPass) {
    Chain = DAG.getCopyToReg(Chain, CLI.DL, Reg.first, Reg.second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, getPointerTy(),
                                        G->getOffset(), 0);
  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), 0);

  // Returns a chain & a flag for retval copy to use.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (auto &Reg : RegsToPass)
    Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));

  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(BPFISD::CALL, CLI.DL, NodeTys, Ops);
  InFlag = Chain.getValue(1);

  // Create the CALLSEQ_END node.
  Chain = DAG.getCALLSEQ_END(
      Chain, DAG.getConstant(NumBytes, CLI.DL, getPointerTy(), true),
      DAG.getConstant(0, CLI.DL, getPointerTy(), true), InFlag, CLI.DL);
  InFlag = Chain.getValue(1);

  // Handle result values, copying them out of physregs into vregs that we
  // return.
  return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, CLI.DL, DAG,
                         InVals);
}
Esempio n. 20
0
/*!
 */
SDNode *
SPUDAGToDAGISel::Select(SDNode *N) {
  unsigned Opc = N->getOpcode();
  int n_ops = -1;
  unsigned NewOpc = 0;
  EVT OpVT = N->getValueType(0);
  SDValue Ops[8];
  DebugLoc dl = N->getDebugLoc();

  if (N->isMachineOpcode())
    return NULL;   // Already selected.

  if (Opc == ISD::FrameIndex) {
    int FI = cast<FrameIndexSDNode>(N)->getIndex();
    SDValue TFI = CurDAG->getTargetFrameIndex(FI, N->getValueType(0));
    SDValue Imm0 = CurDAG->getTargetConstant(0, N->getValueType(0));

    if (FI < 128) {
      NewOpc = SPU::AIr32;
      Ops[0] = TFI;
      Ops[1] = Imm0;
      n_ops = 2;
    } else {
      NewOpc = SPU::Ar32;
      Ops[0] = CurDAG->getRegister(SPU::R1, N->getValueType(0));
      Ops[1] = SDValue(CurDAG->getMachineNode(SPU::ILAr32, dl,
                                              N->getValueType(0), TFI),
                       0);
      n_ops = 2;
    }
  } else if (Opc == ISD::Constant && OpVT == MVT::i64) {
    // Catch the i64 constants that end up here. Note: The backend doesn't
    // attempt to legalize the constant (it's useless because DAGCombiner
    // will insert 64-bit constants and we can't stop it).
    return SelectI64Constant(N, OpVT, N->getDebugLoc());
  } else if ((Opc == ISD::ZERO_EXTEND || Opc == ISD::ANY_EXTEND)
             && OpVT == MVT::i64) {
    SDValue Op0 = N->getOperand(0);
    EVT Op0VT = Op0.getValueType();
    EVT Op0VecVT = EVT::getVectorVT(*CurDAG->getContext(),
                                    Op0VT, (128 / Op0VT.getSizeInBits()));
    EVT OpVecVT = EVT::getVectorVT(*CurDAG->getContext(),
                                   OpVT, (128 / OpVT.getSizeInBits()));
    SDValue shufMask;

    switch (Op0VT.getSimpleVT().SimpleTy) {
    default:
      report_fatal_error("CellSPU Select: Unhandled zero/any extend EVT");
      /*NOTREACHED*/
    case MVT::i32:
      shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
                                 CurDAG->getConstant(0x80808080, MVT::i32),
                                 CurDAG->getConstant(0x00010203, MVT::i32),
                                 CurDAG->getConstant(0x80808080, MVT::i32),
                                 CurDAG->getConstant(0x08090a0b, MVT::i32));
      break;

    case MVT::i16:
      shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
                                 CurDAG->getConstant(0x80808080, MVT::i32),
                                 CurDAG->getConstant(0x80800203, MVT::i32),
                                 CurDAG->getConstant(0x80808080, MVT::i32),
                                 CurDAG->getConstant(0x80800a0b, MVT::i32));
      break;

    case MVT::i8:
      shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
                                 CurDAG->getConstant(0x80808080, MVT::i32),
                                 CurDAG->getConstant(0x80808003, MVT::i32),
                                 CurDAG->getConstant(0x80808080, MVT::i32),
                                 CurDAG->getConstant(0x8080800b, MVT::i32));
      break;
    }

    SDNode *shufMaskLoad = emitBuildVector(shufMask.getNode());

    HandleSDNode PromoteScalar(CurDAG->getNode(SPUISD::PREFSLOT2VEC, dl,
                                               Op0VecVT, Op0));

    SDValue PromScalar;
    if (SDNode *N = SelectCode(PromoteScalar.getValue().getNode()))
      PromScalar = SDValue(N, 0);
    else
      PromScalar = PromoteScalar.getValue();

    SDValue zextShuffle =
            CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT,
                            PromScalar, PromScalar,
                            SDValue(shufMaskLoad, 0));

    HandleSDNode Dummy2(zextShuffle);
    if (SDNode *N = SelectCode(Dummy2.getValue().getNode()))
      zextShuffle = SDValue(N, 0);
    else
      zextShuffle = Dummy2.getValue();
    HandleSDNode Dummy(CurDAG->getNode(SPUISD::VEC2PREFSLOT, dl, OpVT,
                                       zextShuffle));

    CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode());
    SelectCode(Dummy.getValue().getNode());
    return Dummy.getValue().getNode();
  } else if (Opc == ISD::ADD && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
    SDNode *CGLoad =
            emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl).getNode());

    HandleSDNode Dummy(CurDAG->getNode(SPUISD::ADD64_MARKER, dl, OpVT,
                                       N->getOperand(0), N->getOperand(1),
                                       SDValue(CGLoad, 0)));

    CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode());
    if (SDNode *N = SelectCode(Dummy.getValue().getNode()))
      return N;
    return Dummy.getValue().getNode();
  } else if (Opc == ISD::SUB && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
    SDNode *CGLoad =
            emitBuildVector(getBorrowGenerateShufMask(*CurDAG, dl).getNode());

    HandleSDNode Dummy(CurDAG->getNode(SPUISD::SUB64_MARKER, dl, OpVT,
                                       N->getOperand(0), N->getOperand(1),
                                       SDValue(CGLoad, 0)));

    CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode());
    if (SDNode *N = SelectCode(Dummy.getValue().getNode()))
      return N;
    return Dummy.getValue().getNode();
  } else if (Opc == ISD::MUL && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
    SDNode *CGLoad =
            emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl).getNode());

    HandleSDNode Dummy(CurDAG->getNode(SPUISD::MUL64_MARKER, dl, OpVT,
                                       N->getOperand(0), N->getOperand(1),
                                       SDValue(CGLoad, 0)));
    CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode());
    if (SDNode *N = SelectCode(Dummy.getValue().getNode()))
      return N;
    return Dummy.getValue().getNode();
  } else if (Opc == ISD::TRUNCATE) {
    SDValue Op0 = N->getOperand(0);
    if ((Op0.getOpcode() == ISD::SRA || Op0.getOpcode() == ISD::SRL)
        && OpVT == MVT::i32
        && Op0.getValueType() == MVT::i64) {
      // Catch (truncate:i32 ([sra|srl]:i64 arg, c), where c >= 32
      //
      // Take advantage of the fact that the upper 32 bits are in the
      // i32 preferred slot and avoid shuffle gymnastics:
      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0.getOperand(1));
      if (CN != 0) {
        unsigned shift_amt = unsigned(CN->getZExtValue());

        if (shift_amt >= 32) {
          SDNode *hi32 =
                  CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, dl, OpVT,
                                         Op0.getOperand(0), getRC(MVT::i32));

          shift_amt -= 32;
          if (shift_amt > 0) {
            // Take care of the additional shift, if present:
            SDValue shift = CurDAG->getTargetConstant(shift_amt, MVT::i32);
            unsigned Opc = SPU::ROTMAIr32_i32;

            if (Op0.getOpcode() == ISD::SRL)
              Opc = SPU::ROTMr32;

            hi32 = CurDAG->getMachineNode(Opc, dl, OpVT, SDValue(hi32, 0),
                                          shift);
          }

          return hi32;
        }
      }
    }
  } else if (Opc == ISD::SHL) {
    if (OpVT == MVT::i64)
      return SelectSHLi64(N, OpVT);
  } else if (Opc == ISD::SRL) {
    if (OpVT == MVT::i64)
      return SelectSRLi64(N, OpVT);
  } else if (Opc == ISD::SRA) {
    if (OpVT == MVT::i64)
      return SelectSRAi64(N, OpVT);
  } else if (Opc == ISD::FNEG
             && (OpVT == MVT::f64 || OpVT == MVT::v2f64)) {
    DebugLoc dl = N->getDebugLoc();
    // Check if the pattern is a special form of DFNMS:
    // (fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC))
    SDValue Op0 = N->getOperand(0);
    if (Op0.getOpcode() == ISD::FSUB) {
      SDValue Op00 = Op0.getOperand(0);
      if (Op00.getOpcode() == ISD::FMUL) {
        unsigned Opc = SPU::DFNMSf64;
        if (OpVT == MVT::v2f64)
          Opc = SPU::DFNMSv2f64;

        return CurDAG->getMachineNode(Opc, dl, OpVT,
                                      Op00.getOperand(0),
                                      Op00.getOperand(1),
                                      Op0.getOperand(1));
      }
    }

    SDValue negConst = CurDAG->getConstant(0x8000000000000000ULL, MVT::i64);
    SDNode *signMask = 0;
    unsigned Opc = SPU::XORfneg64;

    if (OpVT == MVT::f64) {
      signMask = SelectI64Constant(negConst.getNode(), MVT::i64, dl);
    } else if (OpVT == MVT::v2f64) {
      Opc = SPU::XORfnegvec;
      signMask = emitBuildVector(CurDAG->getNode(ISD::BUILD_VECTOR, dl,
                                                 MVT::v2i64,
                                                 negConst, negConst).getNode());
    }

    return CurDAG->getMachineNode(Opc, dl, OpVT,
                                  N->getOperand(0), SDValue(signMask, 0));
  } else if (Opc == ISD::FABS) {
    if (OpVT == MVT::f64) {
      SDNode *signMask = SelectI64Constant(0x7fffffffffffffffULL, MVT::i64, dl);
      return CurDAG->getMachineNode(SPU::ANDfabs64, dl, OpVT,
                                    N->getOperand(0), SDValue(signMask, 0));
    } else if (OpVT == MVT::v2f64) {
      SDValue absConst = CurDAG->getConstant(0x7fffffffffffffffULL, MVT::i64);
      SDValue absVec = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64,
                                       absConst, absConst);
      SDNode *signMask = emitBuildVector(absVec.getNode());
      return CurDAG->getMachineNode(SPU::ANDfabsvec, dl, OpVT,
                                    N->getOperand(0), SDValue(signMask, 0));
    }
  } else if (Opc == SPUISD::LDRESULT) {
    // Custom select instructions for LDRESULT
    EVT VT = N->getValueType(0);
    SDValue Arg = N->getOperand(0);
    SDValue Chain = N->getOperand(1);
    SDNode *Result;

    Result = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, dl, VT,
                                    MVT::Other, Arg,
                                    getRC( VT.getSimpleVT()), Chain);
    return Result;

  } else if (Opc == SPUISD::IndirectAddr) {
    // Look at the operands: SelectCode() will catch the cases that aren't
    // specifically handled here.
    //
    // SPUInstrInfo catches the following patterns:
    // (SPUindirect (SPUhi ...), (SPUlo ...))
    // (SPUindirect $sp, imm)
    EVT VT = N->getValueType(0);
    SDValue Op0 = N->getOperand(0);
    SDValue Op1 = N->getOperand(1);
    RegisterSDNode *RN;

    if ((Op0.getOpcode() != SPUISD::Hi && Op1.getOpcode() != SPUISD::Lo)
        || (Op0.getOpcode() == ISD::Register
            && ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0
                && RN->getReg() != SPU::R1))) {
      NewOpc = SPU::Ar32;
      Ops[1] = Op1;
      if (Op1.getOpcode() == ISD::Constant) {
        ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
        Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT);
        if (isInt<10>(CN->getSExtValue())) {
          NewOpc = SPU::AIr32;
          Ops[1] = Op1;
        } else {
          Ops[1] = SDValue(CurDAG->getMachineNode(SPU::ILr32, dl,
                                                  N->getValueType(0),
                                                  Op1),
                           0);
        }
      }
      Ops[0] = Op0;
      n_ops = 2;
    }
  }

  if (n_ops > 0) {
    if (N->hasOneUse())
      return CurDAG->SelectNodeTo(N, NewOpc, OpVT, Ops, n_ops);
    else
      return CurDAG->getMachineNode(NewOpc, dl, OpVT, Ops, n_ops);
  } else
    return SelectCode(N);
}
Esempio n. 21
0
SDValue
NvfcTargetLowering::LowerReturn(SDValue Chain,
                                  CallingConv::ID CallConv, bool isVarArg,
                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  DebugLoc dl, SelectionDAG &DAG) const {

  // CCValAssign - represent the assignment of the return value to a location
  SmallVector<CCValAssign, 16> RVLocs;

#if 0
  // ISRs cannot return any value.
  if (CallConv == CallingConv::MSP430_INTR && !Outs.empty()) {
    report_fatal_error("ISRs cannot return any value");
    return SDValue();
  }
#endif
  
  // CCState - Info about the registers and stack slot.
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 RVLocs, *DAG.getContext());

  // Analize return values.
  CCInfo.AnalyzeReturn(Outs, RetCC_NVFUC);

  // If this is the first return lowered for this function, add the regs to the
  // liveout set for the function.
  if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
    for (unsigned i = 0; i != RVLocs.size(); ++i)
      if (RVLocs[i].isRegLoc())
        DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
  }

  SDValue Flag;

  // Copy the result values into the output registers.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    CCValAssign &VA = RVLocs[i];
    assert(VA.isRegLoc() && "Can only return in registers!");

    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
                             OutVals[i], Flag);

    // Guarantee that all emitted copies are stuck together,
    // avoiding something bad.
    Flag = Chain.getValue(1);
  }

#if 0
    unsigned Opc = (CallConv == CallingConv::MSP430_INTR ?
                  NvfcISD::RETI_FLAG : NvfcISD::RET_FLAG);
#else    
    unsigned Opc = NvfcISD::RET_FLAG;
#endif

  if (Flag.getNode())
    return DAG.getNode(Opc, dl, MVT::Other, Chain, Flag);

  // Return Void
  return DAG.getNode(Opc, dl, MVT::Other, Chain);
}
SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
  SDValue LHS   = Op.getOperand(0);
  SDValue RHS   = Op.getOperand(1);
  DebugLoc dl   = Op.getDebugLoc();

  // If we are doing an AND and testing against zero, then the CMP
  // will not be generated.  The AND (or BIT) will generate the condition codes,
  // but they are different from CMP.
  // FIXME: since we're doing a post-processing, use a pseudoinstr here, so
  // lowering & isel wouldn't diverge.
  bool andCC = false;
  if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
    if (RHSC->isNullValue() && LHS.hasOneUse() &&
        (LHS.getOpcode() == ISD::AND ||
         (LHS.getOpcode() == ISD::TRUNCATE &&
          LHS.getOperand(0).getOpcode() == ISD::AND))) {
      andCC = true;
    }
  }
  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
  SDValue TargetCC;
  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);

  // Get the condition codes directly from the status register, if its easy.
  // Otherwise a branch will be generated.  Note that the AND and BIT
  // instructions generate different flags than CMP, the carry bit can be used
  // for NE/EQ.
  bool Invert = false;
  bool Shift = false;
  bool Convert = true;
  switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) {
   default:
    Convert = false;
    break;
   case MSP430CC::COND_HS:
     // Res = SRW & 1, no processing is required
     break;
   case MSP430CC::COND_LO:
     // Res = ~(SRW & 1)
     Invert = true;
     break;
   case MSP430CC::COND_NE:
     if (andCC) {
       // C = ~Z, thus Res = SRW & 1, no processing is required
     } else {
       // Res = ~((SRW >> 1) & 1)
       Shift = true;
       Invert = true;
     }
     break;
   case MSP430CC::COND_E:
     Shift = true;
     // C = ~Z for AND instruction, thus we can put Res = ~(SRW & 1), however,
     // Res = (SRW >> 1) & 1 is 1 word shorter.
     break;
  }
  EVT VT = Op.getValueType();
  SDValue One  = DAG.getConstant(1, VT);
  if (Convert) {
    SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW,
                                    MVT::i16, Flag);
    if (Shift)
      // FIXME: somewhere this is turned into a SRL, lower it MSP specific?
      SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One);
    SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One);
    if (Invert)
      SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One);
    return SR;
  } else {
    SDValue Zero = DAG.getConstant(0, VT);
    SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
    SmallVector<SDValue, 4> Ops;
    Ops.push_back(One);
    Ops.push_back(Zero);
    Ops.push_back(TargetCC);
    Ops.push_back(Flag);
    return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
  }
}
Esempio n. 23
0
static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC,
                       ISD::CondCode CC,
                       DebugLoc dl, SelectionDAG &DAG) {
  // FIXME: Handle jump negative someday
  NvfcCC::CondCodes TCC = NvfcCC::COND_INVALID;
  switch (CC) {
  default: llvm_unreachable("Invalid integer condition!");
  case ISD::SETEQ:
    TCC = NvfcCC::COND_E;     // aka COND_Z
    // Minor optimization: if LHS is a constant, swap operands, then the
    // constant can be folded into comparison.
    if (LHS.getOpcode() == ISD::Constant)
      std::swap(LHS, RHS);
    break;
  case ISD::SETNE:
    TCC = NvfcCC::COND_NE;    // aka COND_NZ
    // Minor optimization: if LHS is a constant, swap operands, then the
    // constant can be folded into comparison.
    if (LHS.getOpcode() == ISD::Constant)
      std::swap(LHS, RHS);
    break;
  case ISD::SETULE:
    std::swap(LHS, RHS);        // FALLTHROUGH
  case ISD::SETUGE:
    // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to
    // fold constant into instruction.
    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
      LHS = RHS;
      RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
      TCC = NvfcCC::COND_HS;
      break;
    }
    TCC = NvfcCC::COND_LO;
    break;
  case ISD::SETUGT:
    std::swap(LHS, RHS);        // FALLTHROUGH
  case ISD::SETULT:
    // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to
    // fold constant into instruction.
    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
      LHS = RHS;
      RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
      TCC = NvfcCC::COND_LO;
      break;
    }
    TCC = NvfcCC::COND_HS;
    break;
  case ISD::SETLE:
    std::swap(LHS, RHS);        // FALLTHROUGH
  case ISD::SETGE:
    // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to
    // fold constant into instruction.
    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
      LHS = RHS;
      RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
      TCC = NvfcCC::COND_L;
      break;
    }
    TCC = NvfcCC::COND_GE;
    break;
  case ISD::SETGT:
    std::swap(LHS, RHS);        // FALLTHROUGH
  case ISD::SETLT:
    // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to
    // fold constant into instruction.
    if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
      LHS = RHS;
      RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0));
      TCC = NvfcCC::COND_GE;
      break;
    }
    TCC = NvfcCC::COND_L;
    break;
  }

  TargetCC = DAG.getConstant(TCC, MVT::i32);
  return DAG.getNode(NvfcISD::CMP, dl, MVT::Flag, LHS, RHS);
}
Esempio n. 24
0
// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
// vector.  If it is invalid, don't add anything to Ops.
void LanaiTargetLowering::LowerAsmOperandForConstraint(
    SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops,
    SelectionDAG &DAG) const {
  SDValue Result(0, 0);

  // Only support length 1 constraints for now.
  if (Constraint.length() > 1)
    return;

  char ConstraintLetter = Constraint[0];
  switch (ConstraintLetter) {
  case 'I': // Signed 16 bit constant
    // If this fails, the parent routine will give an error
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
      if (isInt<16>(C->getSExtValue())) {
        Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(C),
                                       Op.getValueType());
        break;
      }
    }
    return;
  case 'J': // integer zero
  case 'O':
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
      if (C->getZExtValue() == 0) {
        Result = DAG.getTargetConstant(0, SDLoc(C), Op.getValueType());
        break;
      }
    }
    return;
  case 'K': // unsigned 16 bit immediate
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
      if (isUInt<16>(C->getZExtValue())) {
        Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(C),
                                       Op.getValueType());
        break;
      }
    }
    return;
  case 'L': // immediate in the range 0 to 31
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
      if (C->getZExtValue() <= 31) {
        Result = DAG.getTargetConstant(C->getZExtValue(), SDLoc(C),
                                       Op.getValueType());
        break;
      }
    }
    return;
  case 'M': // signed 32 bit immediate where lower 16 bits are 0
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
      int64_t Val = C->getSExtValue();
      if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)) {
        Result = DAG.getTargetConstant(Val, SDLoc(C), Op.getValueType());
        break;
      }
    }
    return;
  case 'N': // signed 26 bit immediate
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
      int64_t Val = C->getSExtValue();
      if ((Val >= -33554432) && (Val <= 33554431)) {
        Result = DAG.getTargetConstant(Val, SDLoc(C), Op.getValueType());
        break;
      }
    }
    return;
  default:
    break; // This will fall through to the generic implementation
  }

  if (Result.getNode()) {
    Ops.push_back(Result);
    return;
  }

  TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
}
Esempio n. 25
0
SDValue
AlphaTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
                               CallingConv::ID CallConv, bool isVarArg,
                               bool isTailCall,
                               const SmallVectorImpl<ISD::OutputArg> &Outs,
                               const SmallVectorImpl<ISD::InputArg> &Ins,
                               DebugLoc dl, SelectionDAG &DAG,
                               SmallVectorImpl<SDValue> &InVals) {

  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 ArgLocs, *DAG.getContext());

  CCInfo.AnalyzeCallOperands(Outs, CC_Alpha);

    // Get a count of how many bytes are to be pushed on the stack.
  unsigned NumBytes = CCInfo.getNextStackOffset();

  Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes,
                                                      getPointerTy(), true));

  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
  SmallVector<SDValue, 12> MemOpChains;
  SDValue StackPtr;

  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    SDValue Arg = Outs[i].Val;

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
      default: assert(0 && "Unknown loc info!");
      case CCValAssign::Full: break;
      case CCValAssign::SExt:
        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
        break;
      case CCValAssign::ZExt:
        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
        break;
      case CCValAssign::AExt:
        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
        break;
    }

    // Arguments that can be passed on register must be kept at RegsToPass
    // vector
    if (VA.isRegLoc()) {
      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
    } else {
      assert(VA.isMemLoc());

      if (StackPtr.getNode() == 0)
        StackPtr = DAG.getCopyFromReg(Chain, dl, Alpha::R30, MVT::i64);

      SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
                                   StackPtr,
                                   DAG.getIntPtrConstant(VA.getLocMemOffset()));

      MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
                                         PseudoSourceValue::getStack(), 0));
    }
  }

  // Transform all store nodes into one single node because all store nodes are
  // independent of each other.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                        &MemOpChains[0], MemOpChains.size());

  // Build a sequence of copy-to-reg nodes chained together with token chain and
  // flag operands which copy the outgoing args into registers.  The InFlag in
  // necessary since all emited instructions must be stuck together.
  SDValue InFlag;
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
                             RegsToPass[i].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // Returns a chain & a flag for retval copy to use.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
                                  RegsToPass[i].second.getValueType()));

  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(AlphaISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
  InFlag = Chain.getValue(1);

  // Create the CALLSEQ_END node.
  Chain = DAG.getCALLSEQ_END(Chain,
                             DAG.getConstant(NumBytes, getPointerTy(), true),
                             DAG.getConstant(0, getPointerTy(), true),
                             InFlag);
  InFlag = Chain.getValue(1);

  // Handle result values, copying them out of physregs into vregs that we
  // return.
  return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
                         Ins, dl, DAG, InVals);
}
Esempio n. 26
0
// LowerCCCCallTo - functions arguments are copied from virtual regs to
// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
SDValue LanaiTargetLowering::LowerCCCCallTo(
    SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool IsVarArg,
    bool IsTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
    const SmallVectorImpl<SDValue> &OutVals,
    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
    SmallVectorImpl<SDValue> &InVals) const {
  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                 *DAG.getContext());
  GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();

  NumFixedArgs = 0;
  if (IsVarArg && G) {
    const Function *CalleeFn = dyn_cast<Function>(G->getGlobal());
    if (CalleeFn)
      NumFixedArgs = CalleeFn->getFunctionType()->getNumParams();
  }
  if (NumFixedArgs)
    CCInfo.AnalyzeCallOperands(Outs, CC_Lanai32_VarArg);
  else {
    if (CallConv == CallingConv::Fast)
      CCInfo.AnalyzeCallOperands(Outs, CC_Lanai32_Fast);
    else
      CCInfo.AnalyzeCallOperands(Outs, CC_Lanai32);
  }

  // Get a count of how many bytes are to be pushed on the stack.
  unsigned NumBytes = CCInfo.getNextStackOffset();

  // Create local copies for byval args.
  SmallVector<SDValue, 8> ByValArgs;
  for (unsigned I = 0, E = Outs.size(); I != E; ++I) {
    ISD::ArgFlagsTy Flags = Outs[I].Flags;
    if (!Flags.isByVal())
      continue;

    SDValue Arg = OutVals[I];
    unsigned Size = Flags.getByValSize();
    unsigned Align = Flags.getByValAlign();

    int FI = MFI->CreateStackObject(Size, Align, false);
    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
    SDValue SizeNode = DAG.getConstant(Size, DL, MVT::i32);

    Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Align,
                          /*IsVolatile=*/false,
                          /*AlwaysInline=*/false,
                          /*IsTailCall=*/false, MachinePointerInfo(),
                          MachinePointerInfo());
    ByValArgs.push_back(FIPtr);
  }

  Chain = DAG.getCALLSEQ_START(
      Chain,
      DAG.getConstant(NumBytes, DL, getPointerTy(DAG.getDataLayout()), true),
      DL);

  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
  SmallVector<SDValue, 12> MemOpChains;
  SDValue StackPtr;

  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned I = 0, J = 0, E = ArgLocs.size(); I != E; ++I) {
    CCValAssign &VA = ArgLocs[I];
    SDValue Arg = OutVals[I];
    ISD::ArgFlagsTy Flags = Outs[I].Flags;

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
    case CCValAssign::Full:
      break;
    case CCValAssign::SExt:
      Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
      break;
    case CCValAssign::ZExt:
      Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
      break;
    case CCValAssign::AExt:
      Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
      break;
    default:
      llvm_unreachable("Unknown loc info!");
    }

    // Use local copy if it is a byval arg.
    if (Flags.isByVal())
      Arg = ByValArgs[J++];

    // Arguments that can be passed on register must be kept at RegsToPass
    // vector
    if (VA.isRegLoc()) {
      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
    } else {
      assert(VA.isMemLoc());

      if (StackPtr.getNode() == 0)
        StackPtr = DAG.getCopyFromReg(Chain, DL, Lanai::SP,
                                      getPointerTy(DAG.getDataLayout()));

      SDValue PtrOff =
          DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr,
                      DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));

      MemOpChains.push_back(DAG.getStore(
          Chain, DL, Arg, PtrOff, MachinePointerInfo(), false, false, 0));
    }
  }

  // Transform all store nodes into one single node because all store nodes are
  // independent of each other.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
                        ArrayRef<SDValue>(&MemOpChains[0], MemOpChains.size()));

  SDValue InFlag;

  // Build a sequence of copy-to-reg nodes chained together with token chain and
  // flag operands which copy the outgoing args into registers.  The InFlag in
  // necessary since all emitted instructions must be stuck together.
  for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) {
    Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[I].first,
                             RegsToPass[I].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  uint8_t OpFlag = LanaiII::MO_NO_FLAG;
  if (G) {
    Callee = DAG.getTargetGlobalAddress(
        G->getGlobal(), DL, getPointerTy(DAG.getDataLayout()), 0, OpFlag);
  } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
    Callee = DAG.getTargetExternalSymbol(
        E->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlag);
  }

  // Returns a chain & a flag for retval copy to use.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add a register mask operand representing the call-preserved registers.
  // TODO: Should return-twice functions be handled?
  const uint32_t *Mask =
      TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
  assert(Mask && "Missing call preserved mask for calling convention");
  Ops.push_back(DAG.getRegisterMask(Mask));

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I)
    Ops.push_back(DAG.getRegister(RegsToPass[I].first,
                                  RegsToPass[I].second.getValueType()));

  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(LanaiISD::CALL, DL, NodeTys,
                      ArrayRef<SDValue>(&Ops[0], Ops.size()));
  InFlag = Chain.getValue(1);

  // Create the CALLSEQ_END node.
  Chain = DAG.getCALLSEQ_END(
      Chain,
      DAG.getConstant(NumBytes, DL, getPointerTy(DAG.getDataLayout()), true),
      DAG.getConstant(0, DL, getPointerTy(DAG.getDataLayout()), true), InFlag,
      DL);
  InFlag = Chain.getValue(1);

  // Handle result values, copying them out of physregs into vregs that we
  // return.
  return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG,
                         InVals);
}
Esempio n. 27
0
/// LowerOperation - Provide custom lowering hooks for some operations.
///
SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
  DebugLoc dl = Op.getDebugLoc();
  switch (Op.getOpcode()) {
  default: llvm_unreachable("Wasn't expecting to be able to lower this!");
  case ISD::JumpTable: return LowerJumpTable(Op, DAG);

  case ISD::INTRINSIC_WO_CHAIN: {
    unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
    switch (IntNo) {
    default: break;    // Don't custom lower most intrinsics.
    case Intrinsic::alpha_umulh:
      return DAG.getNode(ISD::MULHU, dl, MVT::i64,
                         Op.getOperand(1), Op.getOperand(2));
    }
  }

  case ISD::SRL_PARTS: {
    SDValue ShOpLo = Op.getOperand(0);
    SDValue ShOpHi = Op.getOperand(1);
    SDValue ShAmt  = Op.getOperand(2);
    SDValue bm = DAG.getNode(ISD::SUB, dl, MVT::i64,
                             DAG.getConstant(64, MVT::i64), ShAmt);
    SDValue BMCC = DAG.getSetCC(dl, MVT::i64, bm,
                                DAG.getConstant(0, MVT::i64), ISD::SETLE);
    // if 64 - shAmt <= 0
    SDValue Hi_Neg = DAG.getConstant(0, MVT::i64);
    SDValue ShAmt_Neg = DAG.getNode(ISD::SUB, dl, MVT::i64,
                                    DAG.getConstant(0, MVT::i64), bm);
    SDValue Lo_Neg = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt_Neg);
    // else
    SDValue carries = DAG.getNode(ISD::SHL, dl, MVT::i64, ShOpHi, bm);
    SDValue Hi_Pos =  DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt);
    SDValue Lo_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpLo, ShAmt);
    Lo_Pos = DAG.getNode(ISD::OR, dl, MVT::i64, Lo_Pos, carries);
    // Merge
    SDValue Hi = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Hi_Neg, Hi_Pos);
    SDValue Lo = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Lo_Neg, Lo_Pos);
    SDValue Ops[2] = { Lo, Hi };
    return DAG.getMergeValues(Ops, 2, dl);
  }
    //  case ISD::SRA_PARTS:

    //  case ISD::SHL_PARTS:


  case ISD::SINT_TO_FP: {
    assert(Op.getOperand(0).getValueType() == MVT::i64 &&
           "Unhandled SINT_TO_FP type in custom expander!");
    SDValue LD;
    bool isDouble = Op.getValueType() == MVT::f64;
    LD = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, Op.getOperand(0));
    SDValue FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, dl,
                               isDouble?MVT::f64:MVT::f32, LD);
    return FP;
  }
  case ISD::FP_TO_SINT: {
    bool isDouble = Op.getOperand(0).getValueType() == MVT::f64;
    SDValue src = Op.getOperand(0);

    if (!isDouble) //Promote
      src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, src);

    src = DAG.getNode(AlphaISD::CVTTQ_, dl, MVT::f64, src);

    return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, src);
  }
  case ISD::ConstantPool: {
    ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
    Constant *C = CP->getConstVal();
    SDValue CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment());
    // FIXME there isn't really any debug info here

    SDValue Hi = DAG.getNode(AlphaISD::GPRelHi,  dl, MVT::i64, CPI,
                               DAG.getGLOBAL_OFFSET_TABLE(MVT::i64));
    SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, CPI, Hi);
    return Lo;
  }
  case ISD::GlobalTLSAddress:
    llvm_unreachable("TLS not implemented for Alpha.");
  case ISD::GlobalAddress: {
    GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
    GlobalValue *GV = GSDN->getGlobal();
    SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset());
    // FIXME there isn't really any debug info here

    //    if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) {
    if (GV->hasLocalLinkage()) {
      SDValue Hi = DAG.getNode(AlphaISD::GPRelHi,  dl, MVT::i64, GA,
                                DAG.getGLOBAL_OFFSET_TABLE(MVT::i64));
      SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, GA, Hi);
      return Lo;
    } else
      return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, GA,
                         DAG.getGLOBAL_OFFSET_TABLE(MVT::i64));
  }
  case ISD::ExternalSymbol: {
    return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64,
                       DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op)
                                                   ->getSymbol(), MVT::i64),
                       DAG.getGLOBAL_OFFSET_TABLE(MVT::i64));
  }

  case ISD::UREM:
  case ISD::SREM:
    //Expand only on constant case
    if (Op.getOperand(1).getOpcode() == ISD::Constant) {
      EVT VT = Op.getNode()->getValueType(0);
      SDValue Tmp1 = Op.getNode()->getOpcode() == ISD::UREM ?
        BuildUDIV(Op.getNode(), DAG, NULL) :
        BuildSDIV(Op.getNode(), DAG, NULL);
      Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Op.getOperand(1));
      Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Op.getOperand(0), Tmp1);
      return Tmp1;
    }
    //fall through
  case ISD::SDIV:
  case ISD::UDIV:
    if (Op.getValueType().isInteger()) {
      if (Op.getOperand(1).getOpcode() == ISD::Constant)
        return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.getNode(), DAG, NULL)
          : BuildUDIV(Op.getNode(), DAG, NULL);
      const char* opstr = 0;
      switch (Op.getOpcode()) {
      case ISD::UREM: opstr = "__remqu"; break;
      case ISD::SREM: opstr = "__remq";  break;
      case ISD::UDIV: opstr = "__divqu"; break;
      case ISD::SDIV: opstr = "__divq";  break;
      }
      SDValue Tmp1 = Op.getOperand(0),
        Tmp2 = Op.getOperand(1),
        Addr = DAG.getExternalSymbol(opstr, MVT::i64);
      return DAG.getNode(AlphaISD::DivCall, dl, MVT::i64, Addr, Tmp1, Tmp2);
    }
    break;

  case ISD::VAARG: {
    SDValue Chain, DataPtr;
    LowerVAARG(Op.getNode(), Chain, DataPtr, DAG);

    SDValue Result;
    if (Op.getValueType() == MVT::i32)
      Result = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Chain, DataPtr,
                              NULL, 0, MVT::i32);
    else
      Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, NULL, 0);
    return Result;
  }
  case ISD::VACOPY: {
    SDValue Chain = Op.getOperand(0);
    SDValue DestP = Op.getOperand(1);
    SDValue SrcP = Op.getOperand(2);
    const Value *DestS = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
    const Value *SrcS = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();

    SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, SrcS, 0);
    SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, DestS, 0);
    SDValue NP = DAG.getNode(ISD::ADD, dl, MVT::i64, SrcP,
                               DAG.getConstant(8, MVT::i64));
    Val = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Result,
                         NP, NULL,0, MVT::i32);
    SDValue NPD = DAG.getNode(ISD::ADD, dl, MVT::i64, DestP,
                                DAG.getConstant(8, MVT::i64));
    return DAG.getTruncStore(Val.getValue(1), dl, Val, NPD, NULL, 0, MVT::i32);
  }
  case ISD::VASTART: {
    SDValue Chain = Op.getOperand(0);
    SDValue VAListP = Op.getOperand(1);
    const Value *VAListS = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();

    // vastart stores the address of the VarArgsBase and VarArgsOffset
    SDValue FR  = DAG.getFrameIndex(VarArgsBase, MVT::i64);
    SDValue S1  = DAG.getStore(Chain, dl, FR, VAListP, VAListS, 0);
    SDValue SA2 = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP,
                                DAG.getConstant(8, MVT::i64));
    return DAG.getTruncStore(S1, dl, DAG.getConstant(VarArgsOffset, MVT::i64),
                             SA2, NULL, 0, MVT::i32);
  }
  case ISD::RETURNADDR:
    return DAG.getNode(AlphaISD::GlobalRetAddr, DebugLoc::getUnknownLoc(),
                       MVT::i64);
      //FIXME: implement
  case ISD::FRAMEADDR:          break;
  }

  return SDValue();
}
Esempio n. 28
0
static LPCC::CondCode IntCondCCodeToICC(ISD::CondCode SetCCOpcode, SDLoc DL,
                                        SDValue &LHS, SDValue &RHS,
                                        SelectionDAG &DAG) {
  // For integer, only the SETEQ, SETNE, SETLT, SETLE, SETGT, SETGE, SETULT,
  // SETULE, SETUGT, and SETUGE opcodes are used (see CodeGen/ISDOpcodes.h)
  // and Lanai only supports integer comparisons, so only provide definitions
  // for them.
  switch (SetCCOpcode) {
  case ISD::SETEQ:
    return LPCC::ICC_EQ;
  case ISD::SETGT:
    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS))
      if (RHSC->getZExtValue() == 0xFFFFFFFF) {
        // X > -1 -> X >= 0 -> is_plus(X)
        RHS = DAG.getConstant(0, DL, RHS.getValueType());
        return LPCC::ICC_PL;
      }
    return LPCC::ICC_GT;
  case ISD::SETUGT:
    return LPCC::ICC_UGT;
  case ISD::SETLT:
    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS))
      if (RHSC->getZExtValue() == 0)
        // X < 0 -> is_minus(X)
        return LPCC::ICC_MI;
    return LPCC::ICC_LT;
  case ISD::SETULT:
    return LPCC::ICC_ULT;
  case ISD::SETLE:
    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS))
      if (RHSC->getZExtValue() == 0xFFFFFFFF) {
        // X <= -1 -> X < 0 -> is_minus(X)
        RHS = DAG.getConstant(0, DL, RHS.getValueType());
        return LPCC::ICC_MI;
      }
    return LPCC::ICC_LE;
  case ISD::SETULE:
    return LPCC::ICC_ULE;
  case ISD::SETGE:
    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS))
      if (RHSC->getZExtValue() == 0)
        // X >= 0 -> is_plus(X)
        return LPCC::ICC_PL;
    return LPCC::ICC_GE;
  case ISD::SETUGE:
    return LPCC::ICC_UGE;
  case ISD::SETNE:
    return LPCC::ICC_NE;
  case ISD::SETONE:
  case ISD::SETUNE:
  case ISD::SETOGE:
  case ISD::SETOLE:
  case ISD::SETOLT:
  case ISD::SETOGT:
  case ISD::SETOEQ:
  case ISD::SETUEQ:
  case ISD::SETO:
  case ISD::SETUO:
    llvm_unreachable("Unsupported comparison.");
  default:
    llvm_unreachable("Unknown integer condition code!");
  }
}
Esempio n. 29
0
static bool isIntS32Immediate(SDValue Op, int32_t &Imm) {
  return isIntS32Immediate(Op.getNode(), Imm);
}
Esempio n. 30
0
/// AddRegisterOperand - Add the specified register as an operand to the
/// specified machine instr. Insert register copies if the register is
/// not in the required register class.
void
InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op,
                                 unsigned IIOpNum,
                                 const MCInstrDesc *II,
                                 DenseMap<SDValue, unsigned> &VRBaseMap,
                                 bool IsDebug, bool IsClone, bool IsCloned) {
    assert(Op.getValueType() != MVT::Other &&
           Op.getValueType() != MVT::Glue &&
           "Chain and glue operands should occur at end of operand list!");
    // Get/emit the operand.
    unsigned VReg = getVR(Op, VRBaseMap);
    assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");

    const MCInstrDesc &MCID = MI->getDesc();
    bool isOptDef = IIOpNum < MCID.getNumOperands() &&
                    MCID.OpInfo[IIOpNum].isOptionalDef();

    // If the instruction requires a register in a different class, create
    // a new virtual register and copy the value into it, but first attempt to
    // shrink VReg's register class within reason.  For example, if VReg == GR32
    // and II requires a GR32_NOSP, just constrain VReg to GR32_NOSP.
    if (II) {
        const TargetRegisterClass *DstRC = 0;
        if (IIOpNum < II->getNumOperands())
            DstRC = TII->getRegClass(*II, IIOpNum, TRI);
        assert((DstRC || (MI->isVariadic() && IIOpNum >= MCID.getNumOperands())) &&
               "Don't have operand info for this instruction!");
        if (DstRC && !MRI->constrainRegClass(VReg, DstRC, MinRCSize)) {
            unsigned NewVReg = MRI->createVirtualRegister(DstRC);
            BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(),
                    TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg);
            VReg = NewVReg;
        }
    }

    // If this value has only one use, that use is a kill. This is a
    // conservative approximation. InstrEmitter does trivial coalescing
    // with CopyFromReg nodes, so don't emit kill flags for them.
    // Avoid kill flags on Schedule cloned nodes, since there will be
    // multiple uses.
    // Tied operands are never killed, so we need to check that. And that
    // means we need to determine the index of the operand.
    bool isKill = Op.hasOneUse() &&
                  Op.getNode()->getOpcode() != ISD::CopyFromReg &&
                  !IsDebug &&
                  !(IsClone || IsCloned);
    if (isKill) {
        unsigned Idx = MI->getNumOperands();
        while (Idx > 0 &&
                MI->getOperand(Idx-1).isReg() && MI->getOperand(Idx-1).isImplicit())
            --Idx;
        bool isTied = MI->getDesc().getOperandConstraint(Idx, MCOI::TIED_TO) != -1;
        if (isTied)
            isKill = false;
    }

    MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef,
                   false/*isImp*/, isKill,
                   false/*isDead*/, false/*isUndef*/,
                   false/*isEarlyClobber*/,
                   0/*SubReg*/, IsDebug));
}