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...")
 
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
The NuPlusDAGToDAGISel class is used to transform target independent LLVM DAG nodes into platform dependent nodes.
+
The NaplesPUDAGToDAGISel 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>
 +
//===-- NaplesPUISelDAGToDAG.cpp - A dag to dag inst selector for NaplesPU ------===//
 +
//
 +
//                    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 "naplespu-isel"
 +
 
 +
#include "NaplesPUTargetMachine.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 NaplesPUDAGToDAGISel : public SelectionDAGISel {
 +
public:
 +
  explicit NaplesPUDAGToDAGISel(NaplesPUTargetMachine &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 "NaplesPU DAG->DAG Pattern Instruction Selection";
 +
  }
 +
 
 +
#include "NaplesPUGenDAGISel.inc"
 +
};
 +
} // end anonymous namespace
 +
 
 +
bool NaplesPUDAGToDAGISel::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 NaplesPUDAGToDAGISel::Select(SDNode *N) {
 +
SDLoc DL(N);
 +
if (N->isMachineOpcode())
 +
  return; // Already selected.
 +
 
 +
  SelectCode(N);
 +
}
 +
 
 +
bool NaplesPUDAGToDAGISel::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::createNaplesPUISelDag(NaplesPUTargetMachine &TM) {
 +
  return new NaplesPUDAGToDAGISel(TM);
 +
}
 +
</syntaxhighlight>

Latest revision as of 15:59, 21 June 2019

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

//===-- NaplesPUISelDAGToDAG.cpp - A dag to dag inst selector for NaplesPU ------===//
//
//                     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 "naplespu-isel"

#include "NaplesPUTargetMachine.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 NaplesPUDAGToDAGISel : public SelectionDAGISel {
public:
  explicit NaplesPUDAGToDAGISel(NaplesPUTargetMachine &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 "NaplesPU DAG->DAG Pattern Instruction Selection";
  }

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

bool NaplesPUDAGToDAGISel::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 NaplesPUDAGToDAGISel::Select(SDNode *N) {
 SDLoc DL(N);
 if (N->isMachineOpcode())
   return; // Already selected.

  SelectCode(N);
}

bool NaplesPUDAGToDAGISel::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::createNaplesPUISelDag(NaplesPUTargetMachine &TM) {
  return new NaplesPUDAGToDAGISel(TM);
}