aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp116
1 files changed, 112 insertions, 4 deletions
diff --git a/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp b/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp
index 145f28503635..06cccd4831bf 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp
@@ -10,9 +10,9 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "Xtensa.h"
#include "XtensaTargetMachine.h"
-#include "XtensaUtils.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
@@ -27,12 +27,23 @@ using namespace llvm;
namespace {
class XtensaDAGToDAGISel : public SelectionDAGISel {
+ const XtensaSubtarget *Subtarget = nullptr;
+
public:
- XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
+ explicit XtensaDAGToDAGISel(XtensaTargetMachine &TM, CodeGenOptLevel OptLevel)
: SelectionDAGISel(TM, OptLevel) {}
+ bool runOnMachineFunction(MachineFunction &MF) override {
+ Subtarget = &MF.getSubtarget<XtensaSubtarget>();
+ return SelectionDAGISel::runOnMachineFunction(MF);
+ }
+
void Select(SDNode *Node) override;
+ bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+ InlineAsm::ConstraintCode ConstraintID,
+ std::vector<SDValue> &OutOps) override;
+
// For load/store instructions generate (base+offset) pair from
// memory address. The offset must be a multiple of scale argument.
bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
@@ -64,10 +75,10 @@ public:
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
int64_t OffsetVal = CN->getSExtValue();
- Valid = isValidAddrOffset(Scale, OffsetVal);
+ Valid = Xtensa::isValidAddrOffset(Scale, OffsetVal);
if (Valid) {
- // If the first operand is a FI, get the TargetFI Node
+ // 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);
@@ -125,6 +136,7 @@ FunctionPass *llvm::createXtensaISelDag(XtensaTargetMachine &TM,
void XtensaDAGToDAGISel::Select(SDNode *Node) {
SDLoc DL(Node);
+ EVT VT = Node->getValueType(0);
// If we have a custom node, we already have selected!
if (Node->isMachineOpcode()) {
@@ -132,5 +144,101 @@ void XtensaDAGToDAGISel::Select(SDNode *Node) {
return;
}
+ switch (Node->getOpcode()) {
+ case ISD::SHL: {
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+ auto *C = dyn_cast<ConstantSDNode>(N1);
+ // If C is constant in range [1..31] then we can generate SLLI
+ // instruction using pattern matching, otherwise generate SLL.
+ if (!C || C->isZero()) {
+ SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N1);
+ SDNode *SLL =
+ CurDAG->getMachineNode(Xtensa::SLL, DL, VT, N0, SDValue(SSL, 0));
+ ReplaceNode(Node, SLL);
+ return;
+ }
+ break;
+ }
+ case ISD::SRL: {
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+ auto *C = dyn_cast<ConstantSDNode>(N1);
+
+ // If C is constant then we can generate SRLI
+ // instruction using pattern matching or EXTUI, otherwise generate SRL.
+ if (C) {
+ if (isUInt<4>(C->getZExtValue()))
+ break;
+ unsigned ShAmt = C->getZExtValue();
+ SDNode *EXTUI = CurDAG->getMachineNode(
+ Xtensa::EXTUI, DL, VT, N0, CurDAG->getTargetConstant(ShAmt, DL, VT),
+ CurDAG->getTargetConstant(32 - ShAmt, DL, VT));
+ ReplaceNode(Node, EXTUI);
+ return;
+ }
+
+ SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
+ SDNode *SRL =
+ CurDAG->getMachineNode(Xtensa::SRL, DL, VT, N0, SDValue(SSR, 0));
+ ReplaceNode(Node, SRL);
+ return;
+ }
+ case ISD::SRA: {
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+ auto *C = dyn_cast<ConstantSDNode>(N1);
+ // If C is constant then we can generate SRAI
+ // instruction using pattern matching, otherwise generate SRA.
+ if (!C) {
+ SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N1);
+ SDNode *SRA =
+ CurDAG->getMachineNode(Xtensa::SRA, DL, VT, N0, SDValue(SSR, 0));
+ ReplaceNode(Node, SRA);
+ return;
+ }
+ break;
+ }
+ case XtensaISD::SRCL: {
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+ SDValue N2 = Node->getOperand(2);
+ SDNode *SSL = CurDAG->getMachineNode(Xtensa::SSL, DL, MVT::Glue, N2);
+ SDNode *SRC =
+ CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSL, 0));
+ ReplaceNode(Node, SRC);
+ return;
+ }
+ case XtensaISD::SRCR: {
+ SDValue N0 = Node->getOperand(0);
+ SDValue N1 = Node->getOperand(1);
+ SDValue N2 = Node->getOperand(2);
+ SDNode *SSR = CurDAG->getMachineNode(Xtensa::SSR, DL, MVT::Glue, N2);
+ SDNode *SRC =
+ CurDAG->getMachineNode(Xtensa::SRC, DL, VT, N0, N1, SDValue(SSR, 0));
+ ReplaceNode(Node, SRC);
+ return;
+ }
+ }
+
SelectCode(Node);
}
+
+bool XtensaDAGToDAGISel::SelectInlineAsmMemoryOperand(
+ const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
+ std::vector<SDValue> &OutOps) {
+ switch (ConstraintID) {
+ default:
+ llvm_unreachable("Unexpected asm memory constraint");
+ case InlineAsm::ConstraintCode::m: {
+ SDValue Base, Offset;
+
+ selectMemRegAddr(Op, Base, Offset, 4);
+ OutOps.push_back(Base);
+ OutOps.push_back(Offset);
+
+ return false;
+ }
+ }
+ return false;
+}