コード例 #1
0
ファイル: Decompiler.cpp プロジェクト: kgrizzle/fracture
BasicBlock* Decompiler::decompileBasicBlock(MachineBasicBlock *MBB,
  Function *F) {
  // Create a Selection DAG of MachineSDNodes
  DAG = createDAGFromMachineBasicBlock(MBB);

  if (ViewMCDAGs) {
    MBB->print(Infos);
    DAG->viewGraph(MBB->getName());
  }

  // Run the engine to decompile into SDNodes
  InvISel->SetDAG(DAG);
  DAG->AssignTopologicalOrder();
  // This sets the use on the first node and prevents root from being deleted.
  HandleSDNode Dummy(DAG->getRoot());
  // Start at root and go to entry token
  SelectionDAG::allnodes_iterator ISelPosition(DAG->getRoot().getNode());
  ++ISelPosition;

  // Make sure that ISelPosition gets properly updated when nodes are deleted
  // in calls made from this function.
  ISelUpdater ISU(*DAG, ISelPosition);

  while (ISelPosition != DAG->allnodes_begin()) {
    SDNode *Node = --ISelPosition;

    for (SelectionDAG::allnodes_iterator beg = DAG->allnodes_begin(),
           end = DAG->allnodes_end(); beg != end; ++beg) {
      DEBUG(errs() << "Current Node: ";);
      DEBUG(Node->dump());
      DEBUG(beg->dump());
    }

    // Skip dead nodes
    // if (Node->use_empty())
    //   continue;

    SDNode *ResNode = InvISel->Transmogrify(Node);

    if (ResNode == Node || Node->getOpcode() == ISD::DELETED_NODE)
      continue;

    if (ResNode) {
      DAG->ReplaceAllUsesWith(Node, ResNode);
    }
    if (Node->use_empty()) {
      DAG->RemoveDeadNode(Node);
    }
  }
コード例 #2
0
/// This is the main entry point for the type legalizer. This does a top-down
/// traversal of the dag, legalizing types as it goes. Returns "true" if it made
/// any changes.
bool DAGTypeLegalizer::run() {
  bool Changed = false;

  // Create a dummy node (which is not added to allnodes), that adds a reference
  // to the root node, preventing it from being deleted, and tracking any
  // changes of the root.
  HandleSDNode Dummy(DAG.getRoot());
  Dummy.setNodeId(Unanalyzed);

  // The root of the dag may dangle to deleted nodes until the type legalizer is
  // done.  Set it to null to avoid confusion.
  DAG.setRoot(SDValue());

  // Walk all nodes in the graph, assigning them a NodeId of 'ReadyToProcess'
  // (and remembering them) if they are leaves and assigning 'Unanalyzed' if
  // non-leaves.
  for (SDNode &Node : DAG.allnodes()) {
    if (Node.getNumOperands() == 0) {
      AddToWorklist(&Node);
    } else {
      Node.setNodeId(Unanalyzed);
    }
  }

  // Now that we have a set of nodes to process, handle them all.
  while (!Worklist.empty()) {
#ifndef EXPENSIVE_CHECKS
    if (EnableExpensiveChecks)
#endif
      PerformExpensiveChecks();

    SDNode *N = Worklist.back();
    Worklist.pop_back();
    assert(N->getNodeId() == ReadyToProcess &&
           "Node should be ready if on worklist!");

    if (IgnoreNodeResults(N))
      goto ScanOperands;

    // Scan the values produced by the node, checking to see if any result
    // types are illegal.
    for (unsigned i = 0, NumResults = N->getNumValues(); i < NumResults; ++i) {
      EVT ResultVT = N->getValueType(i);
      switch (getTypeAction(ResultVT)) {
      case TargetLowering::TypeLegal:
        break;
      // The following calls must take care of *all* of the node's results,
      // not just the illegal result they were passed (this includes results
      // with a legal type).  Results can be remapped using ReplaceValueWith,
      // or their promoted/expanded/etc values registered in PromotedIntegers,
      // ExpandedIntegers etc.
      case TargetLowering::TypePromoteInteger:
        PromoteIntegerResult(N, i);
        Changed = true;
        goto NodeDone;
      case TargetLowering::TypeExpandInteger:
        ExpandIntegerResult(N, i);
        Changed = true;
        goto NodeDone;
      case TargetLowering::TypeSoftenFloat:
        Changed = SoftenFloatResult(N, i);
        if (Changed)
          goto NodeDone;
        // If not changed, the result type should be legally in register.
        assert(isLegalInHWReg(ResultVT) &&
               "Unchanged SoftenFloatResult should be legal in register!");
        goto ScanOperands;
      case TargetLowering::TypeExpandFloat:
        ExpandFloatResult(N, i);
        Changed = true;
        goto NodeDone;
      case TargetLowering::TypeScalarizeVector:
        ScalarizeVectorResult(N, i);
        Changed = true;
        goto NodeDone;
      case TargetLowering::TypeSplitVector:
        SplitVectorResult(N, i);
        Changed = true;
        goto NodeDone;
      case TargetLowering::TypeWidenVector:
        WidenVectorResult(N, i);
        Changed = true;
        goto NodeDone;
      case TargetLowering::TypePromoteFloat:
        PromoteFloatResult(N, i);
        Changed = true;
        goto NodeDone;
      }
    }

ScanOperands:
    // Scan the operand list for the node, handling any nodes with operands that
    // are illegal.
    {
    unsigned NumOperands = N->getNumOperands();
    bool NeedsReanalyzing = false;
    unsigned i;
    for (i = 0; i != NumOperands; ++i) {
      if (IgnoreNodeResults(N->getOperand(i).getNode()))
        continue;

      EVT OpVT = N->getOperand(i).getValueType();
      switch (getTypeAction(OpVT)) {
      case TargetLowering::TypeLegal:
        continue;
      // The following calls must either replace all of the node's results
      // using ReplaceValueWith, and return "false"; or update the node's
      // operands in place, and return "true".
      case TargetLowering::TypePromoteInteger:
        NeedsReanalyzing = PromoteIntegerOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypeExpandInteger:
        NeedsReanalyzing = ExpandIntegerOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypeSoftenFloat:
        NeedsReanalyzing = SoftenFloatOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypeExpandFloat:
        NeedsReanalyzing = ExpandFloatOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypeScalarizeVector:
        NeedsReanalyzing = ScalarizeVectorOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypeSplitVector:
        NeedsReanalyzing = SplitVectorOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypeWidenVector:
        NeedsReanalyzing = WidenVectorOperand(N, i);
        Changed = true;
        break;
      case TargetLowering::TypePromoteFloat:
        NeedsReanalyzing = PromoteFloatOperand(N, i);
        Changed = true;
        break;
      }
      break;
    }

    // The sub-method updated N in place.  Check to see if any operands are new,
    // and if so, mark them.  If the node needs revisiting, don't add all users
    // to the worklist etc.
    if (NeedsReanalyzing) {
      assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?");

      N->setNodeId(NewNode);
      // Recompute the NodeId and correct processed operands, adding the node to
      // the worklist if ready.
      SDNode *M = AnalyzeNewNode(N);
      if (M == N)
        // The node didn't morph - nothing special to do, it will be revisited.
        continue;

      // The node morphed - this is equivalent to legalizing by replacing every
      // value of N with the corresponding value of M.  So do that now.
      assert(N->getNumValues() == M->getNumValues() &&
             "Node morphing changed the number of results!");
      for (unsigned i = 0, e = N->getNumValues(); i != e; ++i)
        // Replacing the value takes care of remapping the new value.
        ReplaceValueWith(SDValue(N, i), SDValue(M, i));
      assert(N->getNodeId() == NewNode && "Unexpected node state!");
      // The node continues to live on as part of the NewNode fungus that
      // grows on top of the useful nodes.  Nothing more needs to be done
      // with it - move on to the next node.
      continue;
    }

    if (i == NumOperands) {
      DEBUG(dbgs() << "Legally typed node: "; N->dump(&DAG); dbgs() << "\n");
    }
    }
NodeDone:

    // If we reach here, the node was processed, potentially creating new nodes.
    // Mark it as processed and add its users to the worklist as appropriate.
    assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?");
    N->setNodeId(Processed);

    for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
         UI != E; ++UI) {
      SDNode *User = *UI;
      int NodeId = User->getNodeId();

      // This node has two options: it can either be a new node or its Node ID
      // may be a count of the number of operands it has that are not ready.
      if (NodeId > 0) {
        User->setNodeId(NodeId-1);

        // If this was the last use it was waiting on, add it to the ready list.
        if (NodeId-1 == ReadyToProcess)
          Worklist.push_back(User);
        continue;
      }

      // If this is an unreachable new node, then ignore it.  If it ever becomes
      // reachable by being used by a newly created node then it will be handled
      // by AnalyzeNewNode.
      if (NodeId == NewNode)
        continue;

      // Otherwise, this node is new: this is the first operand of it that
      // became ready.  Its new NodeId is the number of operands it has minus 1
      // (as this node is now processed).
      assert(NodeId == Unanalyzed && "Unknown node ID!");
      User->setNodeId(User->getNumOperands() - 1);

      // If the node only has a single operand, it is now ready.
      if (User->getNumOperands() == 1)
        Worklist.push_back(User);
    }
  }
コード例 #3
0
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) {
  unsigned Opcode = Node->getOpcode();
  SDLoc dl(Node);

  // 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;
}
コード例 #4
0
// Select - Convert the specified operand from a target-independent to a
// target-specific node if it hasn't already been changed.
SDNode *IA64DAGToDAGISel::Select(SDValue Op) {
    SDNode *N = Op.getNode();
    if (N->isMachineOpcode())
        return NULL;   // Already selected.
    DebugLoc dl = Op.getDebugLoc();

    switch (N->getOpcode()) {
    default:
        break;

    case IA64ISD::BRCALL: { // XXX: this is also a hack!
        SDValue Chain = N->getOperand(0);
        SDValue InFlag;  // Null incoming flag value.

        if(N->getNumOperands()==3) { // we have an incoming chain, callee and flag
            InFlag = N->getOperand(2);
        }

        unsigned CallOpcode;
        SDValue CallOperand;

        // if we can call directly, do so
        if (GlobalAddressSDNode *GASD =
                    dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
            CallOpcode = IA64::BRCALL_IPREL_GA;
            CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64);
        } else if (isa<ExternalSymbolSDNode>(N->getOperand(1))) {
            // FIXME: we currently NEED this case for correctness, to avoid
            // "non-pic code with imm reloc.n against dynamic symbol" errors
            CallOpcode = IA64::BRCALL_IPREL_ES;
            CallOperand = N->getOperand(1);
        } else {
            // otherwise we need to load the function descriptor,
            // load the branch target (function)'s entry point and GP,
            // branch (call) then restore the GP
            SDValue FnDescriptor = N->getOperand(1);

            // load the branch target's entry point [mem] and
            // GP value [mem+8]
            SDValue targetEntryPoint=
                SDValue(CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, MVT::Other,
                                              FnDescriptor, CurDAG->getEntryNode()), 0);
            Chain = targetEntryPoint.getValue(1);
            SDValue targetGPAddr=
                SDValue(CurDAG->getTargetNode(IA64::ADDS, dl, MVT::i64,
                                              FnDescriptor,
                                              CurDAG->getConstant(8, MVT::i64)), 0);
            Chain = targetGPAddr.getValue(1);
            SDValue targetGP =
                SDValue(CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64,MVT::Other,
                                              targetGPAddr, CurDAG->getEntryNode()), 0);
            Chain = targetGP.getValue(1);

            Chain = CurDAG->getCopyToReg(Chain, dl, IA64::r1, targetGP, InFlag);
            InFlag = Chain.getValue(1);
            Chain = CurDAG->getCopyToReg(Chain, dl, IA64::B6,
                                         targetEntryPoint, InFlag); // FLAG these?
            InFlag = Chain.getValue(1);

            CallOperand = CurDAG->getRegister(IA64::B6, MVT::i64);
            CallOpcode = IA64::BRCALL_INDIRECT;
        }

        // Finally, once everything is setup, emit the call itself
        if (InFlag.getNode())
            Chain = SDValue(CurDAG->getTargetNode(CallOpcode, dl, MVT::Other,
                                                  MVT::Flag, CallOperand, InFlag), 0);
        else // there might be no arguments
            Chain = SDValue(CurDAG->getTargetNode(CallOpcode, dl, MVT::Other,
                                                  MVT::Flag, CallOperand, Chain), 0);
        InFlag = Chain.getValue(1);

        std::vector<SDValue> CallResults;

        CallResults.push_back(Chain);
        CallResults.push_back(InFlag);

        for (unsigned i = 0, e = CallResults.size(); i != e; ++i)
            ReplaceUses(Op.getValue(i), CallResults[i]);
        return NULL;
    }

    case IA64ISD::GETFD: {
        SDValue Input = N->getOperand(0);
        return CurDAG->getTargetNode(IA64::GETFD, dl, MVT::i64, Input);
    }

    case ISD::FDIV:
    case ISD::SDIV:
    case ISD::UDIV:
    case ISD::SREM:
    case ISD::UREM:
        return SelectDIV(Op);

    case ISD::TargetConstantFP: {
        SDValue Chain = CurDAG->getEntryNode(); // this is a constant, so..

        SDValue V;
        ConstantFPSDNode* N2 = cast<ConstantFPSDNode>(N);
        if (N2->getValueAPF().isPosZero()) {
            V = CurDAG->getCopyFromReg(Chain, dl, IA64::F0, MVT::f64);
        } else if (N2->isExactlyValue(N2->getValueType(0) == MVT::f32 ?
                                      APFloat(+1.0f) : APFloat(+1.0))) {
            V = CurDAG->getCopyFromReg(Chain, dl, IA64::F1, MVT::f64);
        } else
            assert(0 && "Unexpected FP constant!");

        ReplaceUses(SDValue(N, 0), V);
        return 0;
    }

    case ISD::FrameIndex: { // TODO: reduce creepyness
        int FI = cast<FrameIndexSDNode>(N)->getIndex();
        if (N->hasOneUse())
            return CurDAG->SelectNodeTo(N, IA64::MOV, MVT::i64,
                                        CurDAG->getTargetFrameIndex(FI, MVT::i64));
        else
            return CurDAG->getTargetNode(IA64::MOV, dl, MVT::i64,
                                         CurDAG->getTargetFrameIndex(FI, MVT::i64));
    }

    case ISD::ConstantPool: { // TODO: nuke the constant pool
        // (ia64 doesn't need one)
        ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(N);
        Constant *C = CP->getConstVal();
        SDValue CPI = CurDAG->getTargetConstantPool(C, MVT::i64,
                      CP->getAlignment());
        return CurDAG->getTargetNode(IA64::ADDL_GA, dl, MVT::i64, // ?
                                     CurDAG->getRegister(IA64::r1, MVT::i64), CPI);
    }

    case ISD::GlobalAddress: {
        GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
        SDValue GA = CurDAG->getTargetGlobalAddress(GV, MVT::i64);
        SDValue Tmp =
            SDValue(CurDAG->getTargetNode(IA64::ADDL_GA, dl, MVT::i64,
                                          CurDAG->getRegister(IA64::r1,
                                                  MVT::i64), GA), 0);
        return CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, MVT::Other, Tmp,
                                     CurDAG->getEntryNode());
    }

    /* XXX
       case ISD::ExternalSymbol: {
         SDValue EA = CurDAG->getTargetExternalSymbol(
           cast<ExternalSymbolSDNode>(N)->getSymbol(),
           MVT::i64);
         SDValue Tmp = CurDAG->getTargetNode(IA64::ADDL_EA, dl, MVT::i64,
                                               CurDAG->getRegister(IA64::r1,
                                                                   MVT::i64),
                                               EA);
         return CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, Tmp);
       }
    */

    case ISD::LOAD: { // FIXME: load -1, not 1, for bools?
        LoadSDNode *LD = cast<LoadSDNode>(N);
        SDValue Chain = LD->getChain();
        SDValue Address = LD->getBasePtr();

        MVT TypeBeingLoaded = LD->getMemoryVT();
        unsigned Opc;
        switch (TypeBeingLoaded.getSimpleVT()) {
        default:
#ifndef NDEBUG
            N->dump(CurDAG);
#endif
            assert(0 && "Cannot load this type!");
        case MVT::i1: { // this is a bool
            Opc = IA64::LD1; // first we load a byte, then compare for != 0
            if(N->getValueType(0) == MVT::i1) { // XXX: early exit!
                return CurDAG->SelectNodeTo(N, IA64::CMPNE, MVT::i1, MVT::Other,
                                            SDValue(CurDAG->getTargetNode(Opc, dl,
                                                    MVT::i64,
                                                    Address), 0),
                                            CurDAG->getRegister(IA64::r0, MVT::i64),
                                            Chain);
            }
            /* otherwise, we want to load a bool into something bigger: LD1
               will do that for us, so we just fall through */
        }
        case MVT::i8:
            Opc = IA64::LD1;
            break;
        case MVT::i16:
            Opc = IA64::LD2;
            break;
        case MVT::i32:
            Opc = IA64::LD4;
            break;
        case MVT::i64:
            Opc = IA64::LD8;
            break;

        case MVT::f32:
            Opc = IA64::LDF4;
            break;
        case MVT::f64:
            Opc = IA64::LDF8;
            break;
        }

        // TODO: comment this
        return CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other,
                                    Address, Chain);
    }

    case ISD::STORE: {
        StoreSDNode *ST = cast<StoreSDNode>(N);
        SDValue Address = ST->getBasePtr();
        SDValue Chain = ST->getChain();

        unsigned Opc;
        if (ISD::isNON_TRUNCStore(N)) {
            switch (N->getOperand(1).getValueType().getSimpleVT()) {
            default:
                assert(0 && "unknown type in store");
            case MVT::i1: { // this is a bool
                Opc = IA64::ST1; // we store either 0 or 1 as a byte
                // first load zero!
                SDValue Initial = CurDAG->getCopyFromReg(Chain, dl, IA64::r0, MVT::i64);
                Chain = Initial.getValue(1);
                // then load 1 into the same reg iff the predicate to store is 1
                SDValue Tmp = ST->getValue();
                Tmp =
                    SDValue(CurDAG->getTargetNode(IA64::TPCADDS, dl, MVT::i64, Initial,
                                                  CurDAG->getTargetConstant(1,
                                                          MVT::i64),
                                                  Tmp), 0);
                return CurDAG->SelectNodeTo(N, Opc, MVT::Other, Address, Tmp, Chain);
            }
            case MVT::i64:
                Opc = IA64::ST8;
                break;
            case MVT::f64:
                Opc = IA64::STF8;
                break;
            }
        } else { // Truncating store
            switch(ST->getMemoryVT().getSimpleVT()) {
            default:
                assert(0 && "unknown type in truncstore");
            case MVT::i8:
                Opc = IA64::ST1;
                break;
            case MVT::i16:
                Opc = IA64::ST2;
                break;
            case MVT::i32:
                Opc = IA64::ST4;
                break;
            case MVT::f32:
                Opc = IA64::STF4;
                break;
            }
        }

        SDValue N1 = N->getOperand(1);
        SDValue N2 = N->getOperand(2);
        return CurDAG->SelectNodeTo(N, Opc, MVT::Other, N2, N1, Chain);
    }

    case ISD::BRCOND: {
        SDValue Chain = N->getOperand(0);
        SDValue CC = N->getOperand(1);
        MachineBasicBlock *Dest =
            cast<BasicBlockSDNode>(N->getOperand(2))->getBasicBlock();
        //FIXME - we do NOT need long branches all the time
        return CurDAG->SelectNodeTo(N, IA64::BRLCOND_NOTCALL, MVT::Other, CC,
                                    CurDAG->getBasicBlock(Dest), Chain);
    }

    case ISD::CALLSEQ_START:
    case ISD::CALLSEQ_END: {
        int64_t Amt = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
        unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ?
                       IA64::ADJUSTCALLSTACKDOWN : IA64::ADJUSTCALLSTACKUP;
        SDValue N0 = N->getOperand(0);
        return CurDAG->SelectNodeTo(N, Opc, MVT::Other, getI64Imm(Amt), N0);
    }

    case ISD::BR:
        // FIXME: we don't need long branches all the time!
        SDValue N0 = N->getOperand(0);
        return CurDAG->SelectNodeTo(N, IA64::BRL_NOTCALL, MVT::Other,
                                    N->getOperand(1), N0);
    }

    return SelectCode(Op);
}