llvm-project/llvm/lib/Target/Foot/FootISelDAGToDAG.cpp

1055 lines
31 KiB
C++

#include "Foot.h"
#include "FootISelLowering.h"
#include "FootTargetMachine.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
using namespace llvm;
namespace {
enum FootAddrModes {
FOOT_ADDRMODE_M = 0,
FOOT_ADDRMODE_D = 1,
FOOT_ADDRMODE_I = 2,
FOOT_ADDRMODE_A = 3,
FOOT_ADDRMODE_COUNT = 4
};
} // namespace
class FootDAGToDAGISel : public SelectionDAGISel {
public:
explicit FootDAGToDAGISel(TargetMachine &TM) : SelectionDAGISel(TM) {}
private:
void SelectLoad(SDNode *N, SDLoc &Loc);
void SelectStore(SDNode *N, SDLoc &Loc);
void SelectAdd(SDNode *N, SDLoc &Loc);
void SelectSub(SDNode *N, SDLoc &Loc);
void SelectMul(SDNode *N, SDLoc &Loc);
void SelectSrem(SDNode *N, SDLoc &Loc);
void SelectOr(SDNode *N, SDLoc &Loc);
void SelectAnd(SDNode *N, SDLoc &Loc);
void SelectXor(SDNode *N, SDLoc &Loc);
void SelectShl(SDNode *N, SDLoc &Loc);
void SelectSra(SDNode *N, SDLoc &Loc);
void SelectSrl(SDNode *N, SDLoc &Loc);
void SelectConstant(SDNode *N, SDLoc &Loc);
void SelectGlobalAddress(SDNode *N, SDLoc &Loc);
void SelectFrameIndex(SDNode *N, SDLoc &Loc);
void SelectCall(SDNode *N, SDLoc &Loc);
void SelectBr(SDNode *N, SDLoc &Loc);
void SelectBrL(SDNode *N, SDLoc &Loc);
void SelectBrLE(SDNode *N, SDLoc &Loc);
void SelectBrE(SDNode *N, SDLoc &Loc);
void SelectBrGE(SDNode *N, SDLoc &Loc);
void SelectBrG(SDNode *N, SDLoc &Loc);
void SelectBrNE(SDNode *N, SDLoc &Loc);
void SelectCmpChain(SDNode *N, SDLoc &Loc);
void SelectSelectCC(SDNode *N, SDLoc &Loc);
void Select(SDNode *N) override;
ConstantSDNode *DoesConstantFitImm(SDNode *N);
#include "FootGenDAGISel.inc"
};
class FootDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
public:
static char ID;
FootDAGToDAGISelLegacy(FootTargetMachine &TM)
: SelectionDAGISelLegacy(ID, std::make_unique<FootDAGToDAGISel>(TM)) {}
StringRef getPassName() const override { return "FootDAGToDAGISelLegacy"; }
};
void FootDAGToDAGISel::SelectLoad(SDNode *N, SDLoc &Loc) {
LoadSDNode *LN = cast<LoadSDNode>(N);
SDValue Addr = LN->getBasePtr();
SDValue Chain = LN->getChain();
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
if (GlobalAddressSDNode *GAN =
dyn_cast<GlobalAddressSDNode>(Addr.getNode())) {
Addr = CurDAG->getTargetGlobalAddress(GAN->getGlobal(), Loc, MVT::i32);
}
SDValue Ops[] = {Addr, Zero, Chain};
SDNode *NewNode = CurDAG->getMachineNode(Foot::BWOR_D_I_M_A, Loc,
{MVT::i32, MVT::Other}, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectStore(SDNode *N, SDLoc &Loc) {
StoreSDNode *SN = cast<StoreSDNode>(N);
SDValue Val = SN->getValue();
SDValue Addr = SN->getBasePtr();
SDValue Chain = SN->getChain();
SDNode *Store;
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode());
if (CN && CN->getSExtValue() >= 0 && CN->getSExtValue() <= 0xFFFF) {
Val = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
SDValue Ops[] = {Addr, Val, Chain};
Store = CurDAG->getMachineNode(Foot::CNST_STR_I_A, Loc, MVT::Other, Ops);
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
SDValue Ops[] = {Addr, Val, Zero, Chain};
Store =
CurDAG->getMachineNode(Foot::BWOR_STR_I_D_M_A, Loc, MVT::Other, Ops);
}
ReplaceNode(N, Store);
}
void FootDAGToDAGISel::SelectAdd(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::ADDI_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::ADDI_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ADDI_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::ADDI_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ADDI_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::ADDI_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::ADDI_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ADDI_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectSub(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::SUBT_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::SUBT_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::SUBT_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::SUBT_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::SUBT_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::SUBT_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::SUBT_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::SUBT_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectMul(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::MULT_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::MULT_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::MULT_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::MULT_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::MULT_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::MULT_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::MULT_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::MULT_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectSrem(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::MODU_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::MODU_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::MODU_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::MODU_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::MODU_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::MODU_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::MODU_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::MODU_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectOr(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::BWOR_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::BWOR_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BWOR_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::BWOR_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BWOR_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::BWOR_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::BWOR_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BWOR_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectAnd(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::BAND_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::BAND_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BAND_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::BAND_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BAND_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::BAND_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::BAND_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BAND_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectXor(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::BXOR_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::BXOR_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BXOR_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::BXOR_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BXOR_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::BXOR_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::BXOR_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::BXOR_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectShl(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::ZLSH_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::ZLSH_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ZLSH_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::ZLSH_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ZLSH_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::ZLSH_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::ZLSH_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ZLSH_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectSra(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::SRSH_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::SRSH_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::SRSH_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::SRSH_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::SRSH_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::SRSH_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::SRSH_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::SRSH_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectSrl(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(LHS.getNode())) {
LHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (isa<FrameIndexSDNode>(RHS.getNode())) {
RHS_AddrMode = FOOT_ADDRMODE_I;
} else if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::ZRSH_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::ZRSH_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ZRSH_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::ZRSH_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ZRSH_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::ZRSH_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::ZRSH_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_I:
Opc = Foot::ZRSH_D_I_I_A;
break;
}
SDValue Ops[] = {LHS, RHS};
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectConstant(SDNode *N, SDLoc &Loc) {
assert(isa<ConstantSDNode>(N) && "expected constant node");
ConstantSDNode *CN = cast<ConstantSDNode>(N);
SDNode *NewNode;
int64_t Val = CN->getSExtValue();
assert(Val >= -static_cast<int64_t>(0xFFFFFFFF) && Val <= 0xFFFFFFFF &&
"Constant too large!");
Val &= 0xFFFFFFFF;
if (Val > 0xFFFF) {
APInt Adjusted(32, Val);
ConstantInt *CI = ConstantInt::get(*CurDAG->getContext(), Adjusted);
SDValue TgtVal = CurDAG->getTargetConstantPool(CI, MVT::i32);
SDNode *Addr =
CurDAG->getMachineNode(Foot::CNST_D_A, Loc, MVT::i32, TgtVal);
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_D_I_M_A, Loc, MVT::i32,
{SDValue(Addr, 0), Zero});
} else {
SDValue TgtVal = CurDAG->getTargetConstant(Val, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::CNST_D_A, Loc, MVT::i32, TgtVal);
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectGlobalAddress(SDNode *N, SDLoc &Loc) {
assert(isa<GlobalAddressSDNode>(N) && "expected global address");
GlobalAddressSDNode *GAN = cast<GlobalAddressSDNode>(N);
SDValue TgtGA =
CurDAG->getTargetGlobalAddress(GAN->getGlobal(), Loc, MVT::i32);
SDNode *NewNode =
CurDAG->getMachineNode(Foot::CNST_D_A, Loc, MVT::i32, TgtGA);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectFrameIndex(SDNode *N, SDLoc &Loc) {
assert(N->getOpcode() == ISD::FrameIndex && "expected frame index");
FrameIndexSDNode *FN = cast<FrameIndexSDNode>(N);
SDValue TFN = CurDAG->getTargetFrameIndex(FN->getIndex(), MVT::i32);
ReplaceUses(SDValue(N, 0), TFN);
CurDAG->RemoveDeadNode(N);
}
void FootDAGToDAGISel::SelectCall(SDNode *N, SDLoc &Loc) {
SDValue Chain = N->getOperand(0);
SDValue Callee = N->getOperand(1);
SDValue RPC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue RRA = CurDAG->getRegister(Foot::RRA, MVT::i32);
SDValue One = CurDAG->getTargetConstant(1, Loc, MVT::i32);
SDValue CopyOps[] = {RRA, RPC, One, Chain};
SDNode *CopyToRA =
CurDAG->getMachineNode(Foot::ADDI_STR_D_D_M_A, Loc, MVT::Other, CopyOps);
SDValue Ops[] = {RPC, Callee, SDValue(CopyToRA, 0)};
SDNode *Jump = CurDAG->getMachineNode(Foot::CNST_JMP_D_A, Loc,
{MVT::Other, MVT::Glue}, Ops);
ReplaceNode(N, Jump);
}
void FootDAGToDAGISel::SelectCmpChain(SDNode *N, SDLoc &Loc) {
SDValue Chain = N->getOperand(0);
SDValue LHS = N->getOperand(1);
SDValue RHS = N->getOperand(2);
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (ConstantSDNode *CN = DoesConstantFitImm(LHS.getNode())) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
// since LHS and RHS are swapped, set RHS mode
RHS_AddrMode = FOOT_ADDRMODE_M;
}
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (ConstantSDNode *CN = DoesConstantFitImm(RHS.getNode())) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
// since LHS and RHS are swapped, set LHS mode
LHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::CMPR_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::CMPR_D_M_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_D:
Opc = Foot::CMPR_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT *FOOT_ADDRMODE_M:
Opc = Foot::CMPR_M_M_A;
break;
}
// swap LHS and RHS, as dst is 'b' operand, so it should be first
SDNode *NewNode =
CurDAG->getMachineNode(Opc, Loc, MVT::Other, {RHS, LHS, Chain});
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBr(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Chain = N->getOperand(0);
SDValue Target = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_A, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_A, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBrL(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Target = N->getOperand(0);
SDValue Chain = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_L, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_L, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBrLE(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Target = N->getOperand(0);
SDValue Chain = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_LE, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_LE, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBrE(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Target = N->getOperand(0);
SDValue Chain = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_E, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_E, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBrGE(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Target = N->getOperand(0);
SDValue Chain = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_GE, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_GE, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBrG(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Target = N->getOperand(0);
SDValue Chain = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_G, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_G, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectBrNE(SDNode *N, SDLoc &Loc) {
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Target = N->getOperand(0);
SDValue Chain = N->getOperand(1);
SDNode *NewNode;
if (isa<BasicBlockSDNode>(Target.getNode()) ||
isa<GlobalAddressSDNode>(Target.getNode())) {
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_NE, Loc, MVT::Other,
{PC, Target, Chain});
} else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_NE, Loc, MVT::Other,
{PC, Target, Zero, Chain});
}
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectSelectCC(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
SDValue IfTrue = N->getOperand(2);
SDValue IfFalse = N->getOperand(3);
SDValue CC = N->getOperand(4);
unsigned TCCVal = 0; // always
assert(isa<CondCodeSDNode>(CC.getNode()) && "expected condition code");
switch (cast<CondCodeSDNode>(CC.getNode())->get()) {
case ISD::SETLT:
case ISD::SETULT:
TCCVal = 1;
break;
case ISD::SETLE:
case ISD::SETULE:
TCCVal = 2;
break;
case ISD::SETEQ:
case ISD::SETUEQ:
TCCVal = 3;
break;
case ISD::SETGE:
case ISD::SETUGE:
TCCVal = 4;
break;
case ISD::SETGT:
case ISD::SETUGT:
TCCVal = 5;
break;
case ISD::SETNE:
case ISD::SETUNE:
TCCVal = 6;
break;
default:
llvm_unreachable("Unexpected condition code");
}
SDValue TCC = CurDAG->getTargetConstant(TCCVal, Loc, MVT::i32);
SDNode *Pseudo = CurDAG->getMachineNode(Foot::PSEUDO_SELECT, Loc, MVT::i32,
{LHS, RHS, IfTrue, IfFalse, TCC});
ReplaceNode(N, Pseudo);
}
void FootDAGToDAGISel::Select(SDNode *N) {
if (N->isMachineOpcode()) {
return;
}
SDLoc DL(N);
switch (N->getOpcode()) {
case ISD::LOAD:
SelectLoad(N, DL);
break;
case ISD::STORE:
SelectStore(N, DL);
break;
case ISD::ADD:
SelectAdd(N, DL);
break;
case ISD::SUB:
SelectSub(N, DL);
break;
case ISD::MUL:
SelectMul(N, DL);
break;
case ISD::SREM:
SelectSrem(N, DL);
break;
case ISD::OR:
SelectOr(N, DL);
break;
case ISD::AND:
SelectAnd(N, DL);
break;
case ISD::XOR:
SelectXor(N, DL);
break;
case ISD::SHL:
SelectShl(N, DL);
break;
case ISD::SRA:
SelectSra(N, DL);
break;
case ISD::SRL:
SelectSrl(N, DL);
break;
case ISD::Constant:
SelectConstant(N, DL);
break;
case ISD::GlobalAddress:
SelectGlobalAddress(N, DL);
break;
case ISD::FrameIndex:
SelectFrameIndex(N, DL);
break;
case ISD::BR:
SelectBr(N, DL);
break;
case ISD::SELECT_CC:
SelectSelectCC(N, DL);
break;
case FootISD::CALL:
SelectCall(N, DL);
break;
case FootISD::CMP_CHAIN:
SelectCmpChain(N, DL);
break;
case FootISD::BR_L:
SelectBrL(N, DL);
break;
case FootISD::BR_LE:
SelectBrLE(N, DL);
break;
case FootISD::BR_E:
SelectBrE(N, DL);
break;
case FootISD::BR_GE:
SelectBrGE(N, DL);
break;
case FootISD::BR_G:
SelectBrG(N, DL);
break;
case FootISD::BR_NE:
SelectBrNE(N, DL);
break;
default:
SelectCode(N);
break;
}
}
ConstantSDNode *FootDAGToDAGISel::DoesConstantFitImm(SDNode *N) {
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
if (CN->getSExtValue() >= 0 && CN->getSExtValue() < 32) {
return CN;
}
}
return nullptr;
}
char FootDAGToDAGISelLegacy::ID = 0;
Pass *llvm::createFootISelDAG(FootTargetMachine &TM) {
return new FootDAGToDAGISelLegacy(TM);
}