Difference between revisions of "NaplesPUISelDAGToDAG.cpp"

From NaplesPU Documentation
Jump to: navigation, search
(Created page with "The NuPlusDAGToDAGISel class is used to transform target independent LLVM DAG nodes into platform dependent nodes. The class implements the following methods: * The '''Select...")
 
Line 1: Line 1:
 
The NuPlusDAGToDAGISel class is used to transform target independent LLVM DAG nodes into platform dependent nodes.
 
The NuPlusDAGToDAGISel class is used to transform target independent LLVM DAG nodes into platform dependent nodes.
The class implements the following methods:  
+
 
* The '''SelectADDRri''', used to handle the nu+ addressing modes (similar to SPARC). The name of this method must be compliant with the third parameter of the ComplexPattern instances defined in the beginning of the [[NuPlusInstrFormats.td | NuPlusInstrFormats.td]] file. Basically, if the node is a '''FrameIndexSDNode''', the address is evaluated as base address + offset.
+
<syntaxhighlight>
 +
//===-- NuPlusISelDAGToDAG.cpp - A dag to dag inst selector for NuPlus ------===//
 +
//
 +
//                    The LLVM Compiler Infrastructure
 +
//
 +
// This file is distributed under the University of Illinois Open Source
 +
// License. See LICENSE.TXT for details.
 +
//
 +
//===----------------------------------------------------------------------===//
 +
//
 +
// This pass transforms target independent LLVM DAG nodes into platform
 +
// dependent nodes that map, for the most part, directly to target instructions.
 +
//
 +
//===----------------------------------------------------------------------===//
 +
 
 +
#define DEBUG_TYPE "nuplus-isel"
 +
 
 +
#include "NuPlusTargetMachine.h"
 +
#include "llvm/CodeGen/SelectionDAGISel.h"
 +
#include "llvm/IR/Intrinsics.h"
 +
#include "llvm/Support/Compiler.h"
 +
#include "llvm/Support/Debug.h"
 +
#include "llvm/Support/ErrorHandling.h"
 +
#include "llvm/Support/raw_ostream.h"
 +
using namespace llvm;
 +
 
 +
namespace {
 +
class NuPlusDAGToDAGISel : public SelectionDAGISel {
 +
public:
 +
  explicit NuPlusDAGToDAGISel(NuPlusTargetMachine &tm) : SelectionDAGISel(tm) {}
 +
 
 +
  void Select(SDNode *N) override;
 +
 
 +
  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
 +
                                    std::vector<SDValue> &OutOps) override; 
 +
 
 +
  bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
 +
 
 +
  StringRef getPassName() const override {
 +
    return "NuPlus DAG->DAG Pattern Instruction Selection";
 +
  }
 +
 
 +
#include "NuPlusGenDAGISel.inc"
 +
};
 +
} // end anonymous namespace
 +
 
 +
bool NuPlusDAGToDAGISel::SelectADDRri(SDValue Addr, SDValue &Base,
 +
                                    SDValue &Offset) {
 +
 
 +
  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
 +
    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
 +
    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
 +
    return true;
 +
  }
 +
 
 +
  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
 +
      Addr.getOpcode() == ISD::TargetGlobalAddress)
 +
    return false; // direct calls.
 +
 
 +
  if (Addr.getOpcode() == ISD::ADD) {
 +
        if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
 +
      if (isInt<9>(CN->getSExtValue())) {
 +
        if (FrameIndexSDNode *FIN =
 +
                dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
 +
          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
 +
        } else {
 +
          Base = Addr.getOperand(0);
 +
        }
 +
        Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr),
 +
                                          MVT::i32);
 +
        return true;
 +
      }
 +
    }
 +
  }
 +
  Base = Addr;
 +
  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
 +
  return true;
 +
}
 +
 
 +
void NuPlusDAGToDAGISel::Select(SDNode *N) {
 +
SDLoc DL(N);
 +
if (N->isMachineOpcode())
 +
  return; // Already selected.
 +
 
 +
  SelectCode(N);
 +
}
 +
 
 +
bool NuPlusDAGToDAGISel::SelectInlineAsmMemoryOperand(
 +
    const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
 +
  SDValue Op0, Op1;
 +
  switch (ConstraintCode) {
 +
  default:
 +
    return true;
 +
 
 +
  case 'm': // memory
 +
    SelectADDRri(Op, Op0, Op1);
 +
    break;
 +
 
 +
  }
 +
 
 +
  OutOps.push_back(Op0);
 +
  OutOps.push_back(Op1);
 +
  return false;
 +
}
 +
 
 +
FunctionPass *llvm::createNuPlusISelDag(NuPlusTargetMachine &TM) {
 +
  return new NuPlusDAGToDAGISel(TM);
 +
}
 +
</syntaxhighlight>

Revision as of 14:11, 5 April 2019

The NuPlusDAGToDAGISel class is used to transform target independent LLVM DAG nodes into platform dependent nodes.

//===-- NuPlusISelDAGToDAG.cpp - A dag to dag inst selector for NuPlus ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass transforms target independent LLVM DAG nodes into platform
// dependent nodes that map, for the most part, directly to target instructions.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "nuplus-isel"

#include "NuPlusTargetMachine.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

namespace {
class NuPlusDAGToDAGISel : public SelectionDAGISel {
public:
  explicit NuPlusDAGToDAGISel(NuPlusTargetMachine &tm) : SelectionDAGISel(tm) {}

  void Select(SDNode *N) override;

  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
                                    std::vector<SDValue> &OutOps) override;  

  bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);

  StringRef getPassName() const override {
    return "NuPlus DAG->DAG Pattern Instruction Selection";
  }

#include "NuPlusGenDAGISel.inc"
};
} // end anonymous namespace

bool NuPlusDAGToDAGISel::SelectADDRri(SDValue Addr, SDValue &Base,
                                     SDValue &Offset) {

  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
    return true;
  }

  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
      Addr.getOpcode() == ISD::TargetGlobalAddress)
    return false; // direct calls.

  if (Addr.getOpcode() == ISD::ADD) {
        if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
      if (isInt<9>(CN->getSExtValue())) {
        if (FrameIndexSDNode *FIN =
                dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
        } else {
          Base = Addr.getOperand(0);
        }
        Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr),
                                           MVT::i32);
        return true;
      }
    }
  }
  Base = Addr;
  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
  return true;
}

void NuPlusDAGToDAGISel::Select(SDNode *N) {
 SDLoc DL(N);
 if (N->isMachineOpcode())
   return; // Already selected.

  SelectCode(N);
}

bool NuPlusDAGToDAGISel::SelectInlineAsmMemoryOperand(
    const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
  SDValue Op0, Op1;
  switch (ConstraintCode) {
  default:
    return true;

  case 'm': // memory
    SelectADDRri(Op, Op0, Op1);
    break;

  }

  OutOps.push_back(Op0);
  OutOps.push_back(Op1);
  return false;
}

FunctionPass *llvm::createNuPlusISelDag(NuPlusTargetMachine &TM) {
  return new NuPlusDAGToDAGISel(TM);
}