summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/CSKY
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-12-25 22:30:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-12-25 22:30:44 +0000
commit77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (patch)
tree5c0eb39553003b9c75a901af6bc4ddabd6f2f28c /llvm/lib/Target/CSKY
parentf65dcba83ce5035ab88a85fe17628b447eb56e1b (diff)
Diffstat (limited to 'llvm/lib/Target/CSKY')
-rw-r--r--llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp91
-rw-r--r--llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp13
-rw-r--r--llvm/lib/Target/CSKY/CSKYAsmPrinter.h2
-rw-r--r--llvm/lib/Target/CSKY/CSKYCallingConv.td2
-rw-r--r--llvm/lib/Target/CSKY/CSKYFrameLowering.cpp2
-rw-r--r--llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp89
-rw-r--r--llvm/lib/Target/CSKY/CSKYISelLowering.cpp40
-rw-r--r--llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td15
-rw-r--r--llvm/lib/Target/CSKY/CSKYInstrInfo.cpp288
-rw-r--r--llvm/lib/Target/CSKY/CSKYInstrInfo.h25
-rw-r--r--llvm/lib/Target/CSKY/CSKYInstrInfo.td241
-rw-r--r--llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td165
-rw-r--r--llvm/lib/Target/CSKY/CSKYMCInstLower.cpp2
-rw-r--r--llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp181
-rw-r--r--llvm/lib/Target/CSKY/CSKYRegisterInfo.h12
-rw-r--r--llvm/lib/Target/CSKY/CSKYRegisterInfo.td5
16 files changed, 1114 insertions, 59 deletions
diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
index ebc04b40d428..29b99a84a6cd 100644
--- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
+++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
@@ -11,6 +11,7 @@
#include "MCTargetDesc/CSKYMCTargetDesc.h"
#include "TargetInfo/CSKYTargetInfo.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/MC/MCContext.h"
@@ -25,11 +26,24 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+using namespace llvm;
+
#define DEBUG_TYPE "csky-asm-parser"
-using namespace llvm;
+// Include the auto-generated portion of the compress emitter.
+#define GEN_COMPRESS_INSTR
+#include "CSKYGenCompressInstEmitter.inc"
+
+STATISTIC(CSKYNumInstrsCompressed,
+ "Number of C-SKY Compressed instructions emitted");
+
+static cl::opt<bool>
+ EnableCompressedInst("enable-csky-asm-compressed-inst", cl::Hidden,
+ cl::init(false),
+ cl::desc("Enable C-SKY asm compressed instruction"));
namespace {
struct CSKYOperand;
@@ -55,6 +69,10 @@ class CSKYAsmParser : public MCTargetAsmParser {
bool ParseDirective(AsmToken DirectiveID) override;
+ // Helper to actually emit an instruction to the MCStreamer. Also, when
+ // possible, compression of the instruction is performed.
+ void emitToStreamer(MCStreamer &S, const MCInst &Inst);
+
OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) override;
@@ -264,12 +282,6 @@ public:
bool isConstpool() const { return isConstPoolOp(); }
bool isDataSymbol() const { return isConstPoolOp(); }
- bool isSPOperand() const {
- if (!isReg())
- return false;
- return getReg() == CSKY::R14;
- }
-
bool isPSRFlag() const {
int64_t Imm;
// Must be of 'immediate' type and a constant.
@@ -755,10 +767,6 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "register is out of range");
}
- case Match_InvalidSPOperand: {
- SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
- return Error(ErrorLoc, "operand must be sp register");
- }
case Match_RequiresSameSrcAndDst: {
SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "src and dst operand must be same");
@@ -776,27 +784,62 @@ bool CSKYAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
OperandVector &Operands,
MCStreamer &Out) {
- if (Inst.getOpcode() == CSKY::LDQ32 || Inst.getOpcode() == CSKY::STQ32) {
+ switch (Inst.getOpcode()) {
+ default:
+ break;
+ case CSKY::LDQ32:
+ case CSKY::STQ32:
if (Inst.getOperand(1).getReg() != CSKY::R4 ||
Inst.getOperand(2).getReg() != CSKY::R7) {
return Error(IDLoc, "Register sequence is not valid. 'r4-r7' expected");
}
Inst.setOpcode(Inst.getOpcode() == CSKY::LDQ32 ? CSKY::LDM32 : CSKY::STM32);
- Out.emitInstruction(Inst, getSTI());
- return false;
- } else if (Inst.getOpcode() == CSKY::SEXT32 ||
- Inst.getOpcode() == CSKY::ZEXT32) {
+ break;
+ case CSKY::SEXT32:
+ case CSKY::ZEXT32:
if (Inst.getOperand(2).getImm() < Inst.getOperand(3).getImm())
return Error(IDLoc, "msb must be greater or equal to lsb");
- } else if (Inst.getOpcode() == CSKY::INS32) {
+ break;
+ case CSKY::INS32:
if (Inst.getOperand(3).getImm() < Inst.getOperand(4).getImm())
return Error(IDLoc, "msb must be greater or equal to lsb");
- } else if (Inst.getOpcode() == CSKY::IDLY32) {
+ break;
+ case CSKY::IDLY32:
if (Inst.getOperand(0).getImm() > 32 || Inst.getOperand(0).getImm() < 0)
return Error(IDLoc, "n must be in range [0,32]");
+ break;
+ case CSKY::ADDC32:
+ case CSKY::SUBC32:
+ case CSKY::ADDC16:
+ case CSKY::SUBC16:
+ Inst.erase(std::next(Inst.begin()));
+ Inst.erase(std::prev(Inst.end()));
+ Inst.insert(std::next(Inst.begin()), MCOperand::createReg(CSKY::C));
+ Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
+ break;
+ case CSKY::CMPNEI32:
+ case CSKY::CMPNEI16:
+ case CSKY::CMPNE32:
+ case CSKY::CMPNE16:
+ case CSKY::CMPHSI32:
+ case CSKY::CMPHSI16:
+ case CSKY::CMPHS32:
+ case CSKY::CMPHS16:
+ case CSKY::CMPLTI32:
+ case CSKY::CMPLTI16:
+ case CSKY::CMPLT32:
+ case CSKY::CMPLT16:
+ case CSKY::BTSTI32:
+ Inst.erase(Inst.begin());
+ Inst.insert(Inst.begin(), MCOperand::createReg(CSKY::C));
+ break;
+ case CSKY::MVCV32:
+ Inst.erase(std::next(Inst.begin()));
+ Inst.insert(Inst.end(), MCOperand::createReg(CSKY::C));
+ break;
}
- Out.emitInstruction(Inst, getSTI());
+ emitToStreamer(Out, Inst);
return false;
}
@@ -1422,6 +1465,16 @@ OperandMatchResultTy CSKYAsmParser::tryParseRegister(unsigned &RegNo,
bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
+void CSKYAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
+ MCInst CInst;
+ bool Res = false;
+ if (EnableCompressedInst)
+ Res = compressInst(CInst, Inst, getSTI(), S.getContext());
+ if (Res)
+ ++CSKYNumInstrsCompressed;
+ S.emitInstruction((Res ? CInst : Inst), getSTI());
+}
+
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmParser() {
RegisterMCAsmParser<CSKYAsmParser> X(getTheCSKYTarget());
}
diff --git a/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
index 1c38c5d1fde6..85129f78e726 100644
--- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
+++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
@@ -30,6 +30,9 @@ using namespace llvm;
#define DEBUG_TYPE "csky-asm-printer"
+STATISTIC(CSKYNumInstrsCompressed,
+ "Number of C-SKY Compressed instructions emitted");
+
CSKYAsmPrinter::CSKYAsmPrinter(llvm::TargetMachine &TM,
std::unique_ptr<llvm::MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {}
@@ -39,6 +42,16 @@ bool CSKYAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
return AsmPrinter::runOnMachineFunction(MF);
}
+#define GEN_COMPRESS_INSTR
+#include "CSKYGenCompressInstEmitter.inc"
+void CSKYAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
+ MCInst CInst;
+ bool Res = compressInst(CInst, Inst, *Subtarget, OutStreamer->getContext());
+ if (Res)
+ ++CSKYNumInstrsCompressed;
+ AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
+}
+
// Simple pseudo-instructions have their lowering (with expansion to real
// instructions) auto-generated.
#include "CSKYGenMCPseudoLowering.inc"
diff --git a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
index f0f5d8657c04..b30311e0ca64 100644
--- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
+++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
@@ -26,6 +26,8 @@ public:
StringRef getPassName() const override { return "CSKY Assembly Printer"; }
+ void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
+
/// tblgen'erated driver function for lowering simple MI->MC
/// pseudo instructions.
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
diff --git a/llvm/lib/Target/CSKY/CSKYCallingConv.td b/llvm/lib/Target/CSKY/CSKYCallingConv.td
index 87e2e6b9dc31..91102e3714df 100644
--- a/llvm/lib/Target/CSKY/CSKYCallingConv.td
+++ b/llvm/lib/Target/CSKY/CSKYCallingConv.td
@@ -79,4 +79,4 @@ def RetCC_CSKY_ABIV2_FP : CallingConv<[
CCIfType<[i32], CCAssignToReg<[R0, R1]>>,
CCIfType<[f32], CCAssignToReg<[F0_32]>>,
CCIfType<[f64], CCAssignToReg<[F0_64]>>
-]>; \ No newline at end of file
+]>;
diff --git a/llvm/lib/Target/CSKY/CSKYFrameLowering.cpp b/llvm/lib/Target/CSKY/CSKYFrameLowering.cpp
index 9b22c95cfe21..3a8ee5713584 100644
--- a/llvm/lib/Target/CSKY/CSKYFrameLowering.cpp
+++ b/llvm/lib/Target/CSKY/CSKYFrameLowering.cpp
@@ -54,4 +54,4 @@ void CSKYFrameLowering::emitPrologue(MachineFunction &MF,
void CSKYFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
// FIXME: Implement this when we have function calls
-} \ No newline at end of file
+}
diff --git a/llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp b/llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp
index fc9ef8bfd9d9..8dc91904b8cc 100644
--- a/llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp
+++ b/llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp
@@ -40,6 +40,8 @@ public:
}
void Select(SDNode *N) override;
+ bool selectAddCarry(SDNode *N);
+ bool selectSubCarry(SDNode *N);
#include "CSKYGenDAGISel.inc"
};
@@ -60,7 +62,12 @@ void CSKYDAGToDAGISel::Select(SDNode *N) {
switch (Opcode) {
default:
break;
- // FIXME: Add selection nodes needed later.
+ case ISD::ADDCARRY:
+ IsSelected = selectAddCarry(N);
+ break;
+ case ISD::SUBCARRY:
+ IsSelected = selectSubCarry(N);
+ break;
}
if (IsSelected)
@@ -70,6 +77,86 @@ void CSKYDAGToDAGISel::Select(SDNode *N) {
SelectCode(N);
}
+bool CSKYDAGToDAGISel::selectAddCarry(SDNode *N) {
+ MachineSDNode *NewNode = nullptr;
+ auto Type0 = N->getValueType(0);
+ auto Type1 = N->getValueType(1);
+ auto Op0 = N->getOperand(0);
+ auto Op1 = N->getOperand(1);
+ auto Op2 = N->getOperand(2);
+
+ SDLoc Dl(N);
+
+ if (isNullConstant(Op2)) {
+ auto *CA = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
+ NewNode = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
+ {Op0, Op1, SDValue(CA, 0)});
+ } else if (isOneConstant(Op2)) {
+ auto *CA = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
+ NewNode = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
+ {Op0, Op1, SDValue(CA, 0)});
+ } else {
+ NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::ADDC32
+ : CSKY::ADDC16,
+ Dl, {Type0, Type1}, {Op0, Op1, Op2});
+ }
+ ReplaceNode(N, NewNode);
+ return true;
+}
+
+static SDValue InvertCarryFlag(const CSKYSubtarget *Subtarget,
+ SelectionDAG *DAG, SDLoc Dl, SDValue OldCarry) {
+ auto NewCarryReg =
+ DAG->getMachineNode(Subtarget->has2E3() ? CSKY::MVCV32 : CSKY::MVCV16, Dl,
+ MVT::i32, OldCarry);
+ auto NewCarry =
+ DAG->getMachineNode(Subtarget->hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16,
+ Dl, OldCarry.getValueType(), SDValue(NewCarryReg, 0),
+ DAG->getTargetConstant(0, Dl, MVT::i32));
+ return SDValue(NewCarry, 0);
+}
+
+bool CSKYDAGToDAGISel::selectSubCarry(SDNode *N) {
+ MachineSDNode *NewNode = nullptr;
+ auto Type0 = N->getValueType(0);
+ auto Type1 = N->getValueType(1);
+ auto Op0 = N->getOperand(0);
+ auto Op1 = N->getOperand(1);
+ auto Op2 = N->getOperand(2);
+
+ SDLoc Dl(N);
+
+ if (isNullConstant(Op2)) {
+ auto *CA = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
+ NewNode = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
+ {Op0, Op1, SDValue(CA, 0)});
+ } else if (isOneConstant(Op2)) {
+ auto *CA = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
+ NewNode = CurDAG->getMachineNode(
+ Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
+ {Op0, Op1, SDValue(CA, 0)});
+ } else {
+ auto CarryIn = InvertCarryFlag(Subtarget, CurDAG, Dl, Op2);
+ NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::SUBC32
+ : CSKY::SUBC16,
+ Dl, {Type0, Type1}, {Op0, Op1, CarryIn});
+ }
+ auto CarryOut = InvertCarryFlag(Subtarget, CurDAG, Dl, SDValue(NewNode, 1));
+
+ ReplaceUses(SDValue(N, 0), SDValue(NewNode, 0));
+ ReplaceUses(SDValue(N, 1), CarryOut);
+ CurDAG->RemoveDeadNode(N);
+
+ return true;
+}
+
FunctionPass *llvm::createCSKYISelDag(CSKYTargetMachine &TM) {
return new CSKYDAGToDAGISel(TM);
}
diff --git a/llvm/lib/Target/CSKY/CSKYISelLowering.cpp b/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
index ac6d069e592c..a1f7cc685d4c 100644
--- a/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
+++ b/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
@@ -37,6 +37,46 @@ CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM,
// Register Class
addRegisterClass(MVT::i32, &CSKY::GPRRegClass);
+ setOperationAction(ISD::ADDCARRY, MVT::i32, Legal);
+ setOperationAction(ISD::SUBCARRY, MVT::i32, Legal);
+ setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);
+
+ setOperationAction(ISD::SREM, MVT::i32, Expand);
+ setOperationAction(ISD::UREM, MVT::i32, Expand);
+ setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
+ setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
+ setOperationAction(ISD::CTTZ, MVT::i32, Expand);
+ setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+ setOperationAction(ISD::ROTR, MVT::i32, Expand);
+ setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
+ setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
+ setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
+ setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
+ setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
+ setOperationAction(ISD::MULHS, MVT::i32, Expand);
+ setOperationAction(ISD::MULHU, MVT::i32, Expand);
+
+ setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote);
+ setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote);
+ setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote);
+
+ if (!Subtarget.hasE2()) {
+ setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand);
+ setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand);
+ setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+ setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+ }
+
+ if (!Subtarget.has2E3()) {
+ setOperationAction(ISD::ABS, MVT::i32, Expand);
+ setOperationAction(ISD::BITREVERSE, MVT::i32, Expand);
+ setOperationAction(ISD::SDIV, MVT::i32, Expand);
+ setOperationAction(ISD::UDIV, MVT::i32, Expand);
+ }
+
// Compute derived properties from the register classes.
computeRegisterProperties(STI.getRegisterInfo());
diff --git a/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td
index 6d42bddcdd78..ea0761d97545 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td
@@ -88,6 +88,19 @@ class R16_XZ_UNOP<bits<4> op, bits<2> sop, string opstr> : CSKY16Inst<
let Inst{1, 0} = sop;
}
+class R16_Z_UNOP<bits<4> op, bits<2> sop, string opstr> : CSKY16Inst<
+ AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rx), !strconcat(opstr, "\t$rz"),
+ []> {
+ bits<4> rz;
+ bits<4> rx;
+ let Inst{15, 14} = 0b01;
+ let Inst{13 - 10} = op;
+ let Inst{9 - 6} = rz;
+ let Inst{5 - 2} = rx;
+ let Inst{1, 0} = sop;
+ let Constraints = "$rz = $rx";
+}
+
class R16_XY_CMP<bits<2> sop, string opstr> : CSKY16Inst<
AddrModeNone, (outs CARRY:$ca), (ins sGPR:$rx, sGPR:$ry), !strconcat(opstr, "\t$rx, $ry"),
[]> {
@@ -146,7 +159,7 @@ class I16_X_CMP<bits<3> sop, string opstr, Operand Immoperand> : CSKY16Inst<
}
class I16_SP_IMM7<bits<3> sop, string opstr> : CSKY16Inst<
- AddrModeNone, (outs SPOp:$sp2), (ins SPOp:$sp1, uimm7_2:$imm7),
+ AddrModeNone, (outs GPRSP:$sp2), (ins GPRSP:$sp1, uimm7_2:$imm7),
!strconcat(opstr, "\t$sp2, $sp1, $imm7"), []> {
bits<7> imm7;
let Inst{15, 14} = 0b00;
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.cpp b/llvm/lib/Target/CSKY/CSKYInstrInfo.cpp
index e12235cf9478..6fcb136cd99b 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.cpp
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.cpp
@@ -11,6 +11,8 @@
//===----------------------------------------------------------------------===//
#include "CSKYInstrInfo.h"
+#include "CSKYMachineFunctionInfo.h"
+#include "CSKYTargetMachine.h"
#include "llvm/MC/MCContext.h"
#define DEBUG_TYPE "csky-instr-info"
@@ -23,3 +25,289 @@ using namespace llvm;
CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI)
: CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) {
}
+
+Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ const DebugLoc &DL, int64_t Val,
+ MachineInstr::MIFlag Flag) const {
+ assert(isUInt<32>(Val) && "should be uint32");
+
+ MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+
+ Register DstReg;
+ if (STI.hasE2()) {
+ DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
+
+ if (isUInt<16>(Val)) {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg)
+ .addImm(Val & 0xFFFF)
+ .setMIFlags(Flag);
+ } else if (isShiftedUInt<16, 16>(Val)) {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
+ .addImm((Val >> 16) & 0xFFFF)
+ .setMIFlags(Flag);
+ } else {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
+ .addImm((Val >> 16) & 0xFFFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg)
+ .addReg(DstReg)
+ .addImm(Val & 0xFFFF)
+ .setMIFlags(Flag);
+ }
+
+ } else {
+ DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
+ if (isUInt<8>(Val)) {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
+ .addImm(Val & 0xFF)
+ .setMIFlags(Flag);
+ } else if (isUInt<16>(Val)) {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
+ .addImm((Val >> 8) & 0xFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
+ .addReg(DstReg)
+ .addImm(8)
+ .setMIFlags(Flag);
+ if ((Val & 0xFF) != 0)
+ BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
+ .addReg(DstReg)
+ .addImm(Val & 0xFF)
+ .setMIFlags(Flag);
+ } else if (isUInt<24>(Val)) {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
+ .addImm((Val >> 16) & 0xFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
+ .addReg(DstReg)
+ .addImm(8)
+ .setMIFlags(Flag);
+ if (((Val >> 8) & 0xFF) != 0)
+ BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
+ .addReg(DstReg)
+ .addImm((Val >> 8) & 0xFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
+ .addReg(DstReg)
+ .addImm(8)
+ .setMIFlags(Flag);
+ if ((Val & 0xFF) != 0)
+ BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
+ .addReg(DstReg)
+ .addImm(Val & 0xFF)
+ .setMIFlags(Flag);
+ } else {
+ BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
+ .addImm((Val >> 24) & 0xFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
+ .addReg(DstReg)
+ .addImm(8)
+ .setMIFlags(Flag);
+ if (((Val >> 16) & 0xFF) != 0)
+ BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
+ .addReg(DstReg)
+ .addImm((Val >> 16) & 0xFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
+ .addReg(DstReg)
+ .addImm(8)
+ .setMIFlags(Flag);
+ if (((Val >> 8) & 0xFF) != 0)
+ BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
+ .addReg(DstReg)
+ .addImm((Val >> 8) & 0xFF)
+ .setMIFlags(Flag);
+ BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
+ .addReg(DstReg)
+ .addImm(8)
+ .setMIFlags(Flag);
+ if ((Val & 0xFF) != 0)
+ BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
+ .addReg(DstReg)
+ .addImm(Val & 0xFF)
+ .setMIFlags(Flag);
+ }
+ }
+
+ return DstReg;
+}
+
+unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
+ int &FrameIndex) const {
+ switch (MI.getOpcode()) {
+ default:
+ return 0;
+ case CSKY::LD16B:
+ case CSKY::LD16H:
+ case CSKY::LD16W:
+ case CSKY::LD32B:
+ case CSKY::LD32BS:
+ case CSKY::LD32H:
+ case CSKY::LD32HS:
+ case CSKY::LD32W:
+ case CSKY::RESTORE_CARRY:
+ break;
+ }
+
+ if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
+ MI.getOperand(2).getImm() == 0) {
+ FrameIndex = MI.getOperand(1).getIndex();
+ return MI.getOperand(0).getReg();
+ }
+
+ return 0;
+}
+
+unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
+ int &FrameIndex) const {
+ switch (MI.getOpcode()) {
+ default:
+ return 0;
+ case CSKY::ST16B:
+ case CSKY::ST16H:
+ case CSKY::ST16W:
+ case CSKY::ST32B:
+ case CSKY::ST32H:
+ case CSKY::ST32W:
+ case CSKY::SPILL_CARRY:
+ break;
+ }
+
+ if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
+ MI.getOperand(2).getImm() == 0) {
+ FrameIndex = MI.getOperand(1).getIndex();
+ return MI.getOperand(0).getReg();
+ }
+
+ return 0;
+}
+
+void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ Register SrcReg, bool IsKill, int FI,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const {
+ DebugLoc DL;
+ if (I != MBB.end())
+ DL = I->getDebugLoc();
+
+ MachineFunction &MF = *MBB.getParent();
+ CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ unsigned Opcode = 0;
+
+ if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
+ Opcode = CSKY::ST32W; // Optimize for 16bit
+ } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
+ Opcode = CSKY::SPILL_CARRY;
+ CFI->setSpillsCR();
+ } else {
+ llvm_unreachable("Unknown RegisterClass");
+ }
+
+ MachineMemOperand *MMO = MF.getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
+ MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
+
+ BuildMI(MBB, I, DL, get(Opcode))
+ .addReg(SrcReg, getKillRegState(IsKill))
+ .addFrameIndex(FI)
+ .addImm(0)
+ .addMemOperand(MMO);
+}
+
+void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ Register DestReg, int FI,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const {
+ DebugLoc DL;
+ if (I != MBB.end())
+ DL = I->getDebugLoc();
+
+ MachineFunction &MF = *MBB.getParent();
+ CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ unsigned Opcode = 0;
+
+ if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
+ Opcode = CSKY::LD32W;
+ } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
+ Opcode = CSKY::RESTORE_CARRY;
+ CFI->setSpillsCR();
+ } else {
+ llvm_unreachable("Unknown RegisterClass");
+ }
+
+ MachineMemOperand *MMO = MF.getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
+ MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
+
+ BuildMI(MBB, I, DL, get(Opcode), DestReg)
+ .addFrameIndex(FI)
+ .addImm(0)
+ .addMemOperand(MMO);
+}
+
+void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, MCRegister DestReg,
+ MCRegister SrcReg, bool KillSrc) const {
+
+ MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+
+ if (CSKY::GPRRegClass.contains(SrcReg) &&
+ CSKY::CARRYRegClass.contains(DestReg)) {
+ if (STI.hasE2()) {
+ BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc))
+ .addImm(0);
+ } else {
+ assert(SrcReg < CSKY::R8);
+ BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc))
+ .addImm(0);
+ }
+ return;
+ }
+
+ if (CSKY::CARRYRegClass.contains(SrcReg) &&
+ CSKY::GPRRegClass.contains(DestReg)) {
+
+ if (STI.hasE2()) {
+ BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc));
+ } else {
+ assert(DestReg < CSKY::R16);
+ assert(DestReg < CSKY::R8);
+ BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0);
+ BuildMI(MBB, I, DL, get(CSKY::ADDC16))
+ .addReg(DestReg, RegState::Define)
+ .addReg(SrcReg, RegState::Define)
+ .addReg(DestReg, getKillRegState(true))
+ .addReg(DestReg, getKillRegState(true))
+ .addReg(SrcReg, getKillRegState(true));
+ BuildMI(MBB, I, DL, get(CSKY::BTSTI16))
+ .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc))
+ .addReg(DestReg)
+ .addImm(0);
+ }
+ return;
+ }
+
+ unsigned Opcode = 0;
+ if (CSKY::GPRRegClass.contains(DestReg, SrcReg))
+ Opcode = CSKY::MOV32;
+ else {
+ LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg);
+ LLVM_DEBUG(I->dump());
+ llvm_unreachable("Unknown RegisterClass");
+ }
+
+ BuildMI(MBB, I, DL, get(Opcode), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc));
+}
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.h b/llvm/lib/Target/CSKY/CSKYInstrInfo.h
index 04be9da27b57..450641d96b74 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.h
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.h
@@ -29,6 +29,31 @@ protected:
public:
explicit CSKYInstrInfo(CSKYSubtarget &STI);
+
+ unsigned isLoadFromStackSlot(const MachineInstr &MI,
+ int &FrameIndex) const override;
+ unsigned isStoreToStackSlot(const MachineInstr &MI,
+ int &FrameIndex) const override;
+
+ void storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI, Register SrcReg,
+ bool IsKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const override;
+
+ void loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI, Register DestReg,
+ int FrameIndex, const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const override;
+
+ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
+ bool KillSrc) const override;
+
+ // Materializes the given integer Val into DstReg.
+ Register movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+ const DebugLoc &DL, int64_t Val,
+ MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
};
} // namespace llvm
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
index 9dda3159e446..30d9206eec68 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
@@ -52,6 +52,11 @@ class OImmAsmOperand<int width, string suffix = "">
: ImmAsmOperand<"O", width, suffix> {
}
+def to_tframeindex : SDNodeXForm<frameindex, [{
+ auto FI = cast<FrameIndexSDNode>(N);
+ return CurDAG->getTargetFrameIndex(FI->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout()));
+}]>;
+
class oimm<int num> : Operand<i32>,
ImmLeaf<i32, "return isUInt<"#num#">(Imm - 1);"> {
let EncoderMethod = "getOImmOpValue";
@@ -166,9 +171,23 @@ def bare_symbol : Operand<iPTR> {
let OperandType = "OPERAND_PCREL";
}
-def oimm3 : oimm<3>;
+def oimm3 : oimm<3> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<3>(Imm - 1);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def oimm4 : oimm<4>;
-def oimm5 : oimm<5>;
+def oimm5 : oimm<5> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<5>(Imm - 1);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def oimm6 : oimm<6>;
def imm5_idly : Operand<i32>, ImmLeaf<i32,
@@ -177,9 +196,30 @@ def imm5_idly : Operand<i32>, ImmLeaf<i32,
let DecoderMethod = "decodeOImmOperand<5>";
}
-def oimm8 : oimm<8>;
-def oimm12 : oimm<12>;
-def oimm16 : oimm<16>;
+def oimm8 : oimm<8> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<8>(Imm - 1);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def oimm12 : oimm<12> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<12>(Imm - 1);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def oimm16 : oimm<16> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<16>(Imm - 1);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def nimm12 : nimm<12>;
@@ -195,28 +235,98 @@ def uimm2_jmpix : Operand<i32>,
def uimm3 : uimm<3>;
def uimm4 : uimm<4>;
-def uimm5 : uimm<5>;
+def uimm5 : uimm<5> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<5, 0>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def uimm5_msb_size : uimm<5> {
let EncoderMethod = "getImmOpValueMSBSize";
}
-def uimm5_1 : uimm<5, 1>;
-def uimm5_2 : uimm<5, 2>;
+def uimm5_1 : uimm<5, 1> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<5, 1>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def uimm5_2 : uimm<5, 2> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<5, 2>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def uimm6 : uimm<6>;
def uimm7 : uimm<7>;
def uimm7_1 : uimm<7, 1>;
-def uimm7_2 : uimm<7, 2>;
+def uimm7_2 : uimm<7, 2>{
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<7, 2>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def uimm7_3 : uimm<7, 3>;
-def uimm8 : uimm<8>;
-def uimm8_2 : uimm<8, 2>;
+def uimm8 : uimm<8> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<8, 0>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def uimm8_2 : uimm<8, 2> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<8, 2>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def uimm8_3 : uimm<8, 3>;
def uimm8_8 : uimm<8, 8>;
def uimm8_16 : uimm<8, 16>;
def uimm8_24 : uimm<8, 24>;
-def uimm12 : uimm<12>;
-def uimm12_1 : uimm<12, 1>;
-def uimm12_2 : uimm<12, 2>;
-def uimm16 : uimm<16>;
+def uimm12 : uimm<12> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<12, 0>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def uimm12_1 : uimm<12, 1> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<12, 1>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def uimm12_2 : uimm<12, 2> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<12, 2>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+def uimm16 : uimm<16> {
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isShiftedUInt<16, 0>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
def uimm16_8 : uimm<16, 8>;
def uimm16_16 : uimm<16, 16>;
def uimm20 : uimm<20>;
@@ -642,11 +752,6 @@ def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
let Defs = [ R15 ];
}
-let Predicates = [iHasE2], isCodeGenOnly = 1 in {
- def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>;
-}
-
-
//===----------------------------------------------------------------------===//
// Symbol address instructions.
//===----------------------------------------------------------------------===//
@@ -872,6 +977,102 @@ def TRAP32 : CSKY32Inst<AddrModeNone, 0x30, (outs), (ins uimm2:$imm2), "trap32 $
}
+//===----------------------------------------------------------------------===//
+// Instruction Patterns.
+//===----------------------------------------------------------------------===//
+
+// Load & Store Patterns
+multiclass LdPat<PatFrag LoadOp, ImmLeaf imm_type, Instruction Inst, ValueType Type> {
+ def : Pat<(Type (LoadOp GPR:$rs1)), (Inst GPR:$rs1, 0)>;
+ def : Pat<(Type (LoadOp (i32 frameindex:$rs1))), (Inst (i32 (to_tframeindex tframeindex:$rs1)), 0)>;
+ def : Pat<(Type (LoadOp (add GPR:$rs1, imm_type:$uimm))),
+ (Inst GPR:$rs1, imm_type:$uimm)>;
+ def : Pat<(Type (LoadOp (add frameindex:$rs1, imm_type:$uimm))),
+ (Inst (i32 (to_tframeindex tframeindex:$rs1)), imm_type:$uimm)>;
+ def : Pat<(Type (LoadOp (eqToAdd frameindex:$rs1, imm_type:$uimm))),
+ (Inst (i32 (to_tframeindex tframeindex:$rs1)), imm_type:$uimm)>;
+ def : Pat<(Type (LoadOp (add GPR:$rs1, tglobaladdr:$gd))),
+ (Inst GPR:$rs1, tglobaladdr:$gd)>;
+}
+
+defm : LdPat<extloadi8, uimm12, LD32B, i32>;
+defm : LdPat<zextloadi8, uimm12, LD32B, i32>;
+let Predicates = [iHasE2] in {
+ defm : LdPat<sextloadi8, uimm12, LD32BS, i32>;
+}
+defm : LdPat<extloadi16, uimm12_1, LD32H, i32>;
+defm : LdPat<zextloadi16, uimm12_1, LD32H, i32>;
+let Predicates = [iHasE2] in {
+defm : LdPat<sextloadi16, uimm12_1, LD32HS, i32>;
+}
+defm : LdPat<load, uimm12_2, LD32W, i32>;
+
+multiclass LdrPat<PatFrag LoadOp, Instruction Inst, ValueType Type> {
+ def : Pat<(Type (LoadOp (add GPR:$rs1, GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2, 0)>;
+ def : Pat<(Type (LoadOp (add GPR:$rs1, (shl GPR:$rs2, (i32 1))))), (Inst GPR:$rs1, GPR:$rs2, 1)>;
+ def : Pat<(Type (LoadOp (add GPR:$rs1, (shl GPR:$rs2, (i32 2))))), (Inst GPR:$rs1, GPR:$rs2, 2)>;
+ def : Pat<(Type (LoadOp (add GPR:$rs1, (shl GPR:$rs2, (i32 3))))), (Inst GPR:$rs1, GPR:$rs2, 3)>;
+}
+
+let Predicates = [iHas2E3] in {
+ defm : LdrPat<zextloadi8, LDR32B, i32>;
+ defm : LdrPat<sextloadi8, LDR32BS, i32>;
+ defm : LdrPat<extloadi8, LDR32BS, i32>;
+ defm : LdrPat<zextloadi16, LDR32H, i32>;
+ defm : LdrPat<sextloadi16, LDR32HS, i32>;
+ defm : LdrPat<extloadi16, LDR32HS, i32>;
+ defm : LdrPat<load, LDR32W, i32>;
+}
+
+multiclass StPat<PatFrag StoreOp, ValueType Type, ImmLeaf imm_type, Instruction Inst> {
+ def : Pat<(StoreOp Type:$rs2, GPR:$rs1), (Inst Type:$rs2, GPR:$rs1, 0)>;
+ def : Pat<(StoreOp Type:$rs2, frameindex:$rs1), (Inst Type:$rs2, (i32 (to_tframeindex tframeindex:$rs1)), 0)>;
+ def : Pat<(StoreOp Type:$rs2, (add GPR:$rs1, imm_type:$uimm12)),
+ (Inst Type:$rs2, GPR:$rs1, imm_type:$uimm12)>;
+ def : Pat<(StoreOp Type:$rs2, (add frameindex:$rs1, imm_type:$uimm12)),
+ (Inst Type:$rs2, (i32 (to_tframeindex tframeindex:$rs1)), imm_type:$uimm12)>;
+ def : Pat<(StoreOp Type:$rs2, (eqToAdd frameindex:$rs1, imm_type:$uimm12)),
+ (Inst Type:$rs2, (i32 (to_tframeindex tframeindex:$rs1)), imm_type:$uimm12)>;
+}
+
+defm : StPat<truncstorei8, i32, uimm12, ST32B>;
+defm : StPat<truncstorei16, i32, uimm12_1, ST32H>;
+defm : StPat<store, i32, uimm12_2, ST32W>;
+
+multiclass StrPat<PatFrag StoreOp, ValueType Type, Instruction Inst> {
+ def : Pat<(StoreOp Type:$rz, (add GPR:$rs1, GPR:$rs2)), (Inst Type:$rz, GPR:$rs1, GPR:$rs2, 0)>;
+ def : Pat<(StoreOp Type:$rz, (add GPR:$rs1, (shl GPR:$rs2, (i32 1)))), (Inst Type:$rz, GPR:$rs1, GPR:$rs2, 1)>;
+ def : Pat<(StoreOp Type:$rz, (add GPR:$rs1, (shl GPR:$rs2, (i32 2)))), (Inst Type:$rz, GPR:$rs1, GPR:$rs2, 2)>;
+ def : Pat<(StoreOp Type:$rz, (add GPR:$rs1, (shl GPR:$rs2, (i32 3)))), (Inst Type:$rz, GPR:$rs1, GPR:$rs2, 3)>;
+}
+
+let Predicates = [iHas2E3] in {
+ defm : StrPat<truncstorei8, i32, STR32B>;
+ defm : StrPat<truncstorei16, i32, STR32H>;
+ defm : StrPat<store, i32, STR32W>;
+
+ // Sext & Zext Patterns
+ def : Pat<(sext_inreg GPR:$src, i1), (SEXT32 GPR:$src, 0, 0)>;
+ def : Pat<(and GPR:$src, 255), (ZEXT32 GPR:$src, 7, 0)>;
+ def : Pat<(and GPR:$src, 65535), (ZEXT32 GPR:$src, 15, 0)>;
+}
+
+// Constant materialize patterns.
+let Predicates = [iHasE2] in
+ def : Pat<(i32 imm:$imm),
+ (ORI32 (MOVIH32 (uimm32_hi16 imm:$imm)), (uimm32_lo16 imm:$imm))>;
+
+
+// Other operations.
+let Predicates = [iHasE2] in {
+ def : Pat<(rotl GPR:$rs1, GPR:$rs2),
+ (ROTL32 GPR:$rs1, (ANDI32 GPR:$rs2, 0x1f))>;
+ let Predicates = [iHas2E3] in {
+ def : Pat<(bitreverse GPR:$rx), (BREV32 GPR:$rx)>;
+ def : Pat<(bswap GPR:$rx), (REVB32 GPR:$rx)>;
+ }
+ def : Pat<(i32 (ctlz GPR:$rx)), (FF1 GPR:$rx)>;
+}
//===----------------------------------------------------------------------===//
// Pseudo for assembly
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td
index c98f43622155..6a9dd03dfa1d 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td
@@ -33,16 +33,6 @@ def br_symbol_16bit : Operand<iPTR> {
let OperandType = "OPERAND_PCREL";
}
-def SPOperand : AsmOperandClass {
- let Name = "SPOperand";
- let RenderMethod = "addRegOperands";
- let DiagnosticType = !strconcat("Invalid", Name);
-}
-
-def SPOp : RegisterOperand<GPR> {
- let ParserMatchClass = SPOperand;
-}
-
def constpool_symbol_16bit : Operand<iPTR> {
let ParserMatchClass = Constpool;
let EncoderMethod =
@@ -83,7 +73,7 @@ let isCommutable = 1 in {
def XOR16 : R16_XZ_BINOP<0b1011, 0b01, "xor16", BinOpFrag<(xor node:$LHS, node:$RHS)>>;
def NOR16 : R16_XZ_BINOP<0b1011, 0b10, "nor16", BinOpFrag<(not (or node:$LHS, node:$RHS))>>;
let isCodeGenOnly = 1 in
- def NOT16 : R16_XZ_UNOP<0b1011, 0b10, "not16">;
+ def NOT16 : R16_Z_UNOP<0b1011, 0b10, "not16">;
def MULT16 : R16_XZ_BINOP<0b1111, 0b00, "mult16", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
}
def SUBU16XZ : R16_XZ_BINOP<0b1000, 0b10, "subu16", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
@@ -108,7 +98,7 @@ let Constraints = "$rZ = $rz", isReMaterializable = 1, isAsCheapAsAMove = 1 in {
}
let isAdd = 1 in
-def ADDI16ZSP : I16_Z_8<0b011, (ins SPOp:$sp, uimm8_2:$imm8),
+def ADDI16ZSP : I16_Z_8<0b011, (ins GPRSP:$sp, uimm8_2:$imm8),
"addi16\t$rz, $sp, $imm8">;
let isAdd = 1 in
@@ -150,9 +140,9 @@ def ST16W : I16_XZ_LDST<AddrMode16W, 0b110, "st16.w",
(outs), (ins mGPR:$rz, mGPR:$rx, uimm5_2:$imm)>;
def LD16WSP : I16_ZSP_LDST<AddrMode16W, 0b011, "ld16.w",
- (outs mGPR:$rz), (ins SPOp:$sp, uimm8_2:$addr)>;
+ (outs mGPR:$rz), (ins GPRSP:$sp, uimm8_2:$addr)>;
def ST16WSP : I16_ZSP_LDST<AddrMode16W, 0b111, "st16.w",
- (outs), (ins mGPR:$rz, SPOp:$sp, uimm8_2:$addr)>;
+ (outs), (ins mGPR:$rz, GPRSP:$sp, uimm8_2:$addr)>;
//===----------------------------------------------------------------------===//
// Compare instructions.
@@ -450,3 +440,150 @@ def JBF16 : JBranchPseudo<(outs),
let mayLoad = 1, Size = 2, isCodeGenOnly = 0 in
def PseudoLRW16 : CSKYPseudo<(outs mGPR:$rz),
(ins bare_symbol:$src), "lrw16 $rz, $src", []>;
+
+
+//===----------------------------------------------------------------------===//
+// Compress Instruction tablegen backend.
+//===----------------------------------------------------------------------===//
+
+def : CompressPat<(ADDU32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (ADDU16XZ sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(ADDU32 sGPR:$rd, sGPR:$rs1, sGPR:$rd),
+ (ADDU16XZ sGPR:$rd, sGPR:$rs1)>;
+def : CompressPat<(ADDU32 mGPR:$rd, mGPR:$rs1, mGPR:$rs2),
+ (ADDU16 mGPR:$rd, mGPR:$rs1, mGPR:$rs2)>;
+def : CompressPat<(SUBU32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (SUBU16XZ sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(SUBU32 mGPR:$rd, mGPR:$rs1, mGPR:$rs2),
+ (SUBU16 mGPR:$rd, mGPR:$rs1, mGPR:$rs2)>;
+
+def : CompressPat<
+ (ADDC32 sGPR:$rd, CARRY:$cout, sGPR:$rd, sGPR:$rs2, CARRY:$cout),
+ (ADDC16 sGPR:$rd, CARRY:$cout, sGPR:$rs2, CARRY:$cout)
+ >;
+def : CompressPat<
+ (SUBC32 sGPR:$rd, CARRY:$cout, sGPR:$rd, sGPR:$rs2, CARRY:$cout),
+ (SUBC16 sGPR:$rd, CARRY:$cout, sGPR:$rs2, CARRY:$cout)
+ >;
+
+def : CompressPat<(ADDI32 mGPR:$rd, mGPR:$rs, oimm3:$imm),
+ (ADDI16XZ mGPR:$rd, mGPR:$rs, oimm3:$imm)>;
+def : CompressPat<(SUBI32 mGPR:$rd, mGPR:$rs, oimm3:$imm),
+ (SUBI16XZ mGPR:$rd, mGPR:$rs, oimm3:$imm)>;
+
+def : CompressPat<(ADDI32 mGPR:$rd, mGPR:$rd, oimm8:$imm),
+ (ADDI16 mGPR:$rd, oimm8:$imm)>;
+def : CompressPat<(SUBI32 mGPR:$rd, mGPR:$rd, oimm8:$imm),
+ (SUBI16 mGPR:$rd, oimm8:$imm)>;
+
+def : CompressPat<(ADDI32 GPRSP:$sp, GPRSP:$sp, uimm7_2:$imm),
+ (ADDI16SPSP GPRSP:$sp, GPRSP:$sp, uimm7_2:$imm)>;
+def : CompressPat<(SUBI32 GPRSP:$sp, GPRSP:$sp, uimm7_2:$imm),
+ (SUBI16SPSP GPRSP:$sp, GPRSP:$sp, uimm7_2:$imm)>;
+
+def : CompressPat<(ADDI32 mGPR:$rd, GPRSP:$sp, uimm8_2:$imm),
+ (ADDI16ZSP mGPR:$rd, GPRSP:$sp, uimm8_2:$imm)>;
+
+def : CompressPat<(MULT32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (MULT16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(MULT32 sGPR:$rd, sGPR:$rs1, sGPR:$rd),
+ (MULT16 sGPR:$rd, sGPR:$rs1)>;
+def : CompressPat<(AND32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (AND16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(AND32 sGPR:$rd, sGPR:$rs1, sGPR:$rd),
+ (AND16 sGPR:$rd, sGPR:$rs1)>;
+def : CompressPat<(OR32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (OR16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(OR32 sGPR:$rd, sGPR:$rs1, sGPR:$rd),
+ (OR16 sGPR:$rd, sGPR:$rs1)>;
+def : CompressPat<(XOR32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (XOR16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(XOR32 sGPR:$rd, sGPR:$rs1, sGPR:$rd),
+ (XOR16 sGPR:$rd, sGPR:$rs1)>;
+
+def : CompressPat<(ANDN32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (ANDN16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(NOR32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (NOR16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(LSL32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (LSL16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(LSR32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (LSR16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(ASR32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (ASR16 sGPR:$rd, sGPR:$rs2)>;
+def : CompressPat<(ROTL32 sGPR:$rd, sGPR:$rd, sGPR:$rs2),
+ (ROTL16 sGPR:$rd, sGPR:$rs2)>;
+
+def : CompressPat<(NOT32 sGPR:$rd, sGPR:$rd),
+ (NOT16 sGPR:$rd)>;
+
+let Predicates = [iHas2E3] in
+def : CompressPat<(REVB32 sGPR:$rd, sGPR:$rs),
+ (REVB16 sGPR:$rd, sGPR:$rs)>;
+
+def : CompressPat<(LSLI32 mGPR:$rd, mGPR:$rs, uimm5:$imm),
+ (LSLI16 mGPR:$rd, mGPR:$rs, uimm5:$imm)>;
+def : CompressPat<(LSRI32 mGPR:$rd, mGPR:$rs, uimm5:$imm),
+ (LSRI16 mGPR:$rd, mGPR:$rs, uimm5:$imm)>;
+def : CompressPat<(ASRI32 mGPR:$rd, mGPR:$rs, uimm5:$imm),
+ (ASRI16 mGPR:$rd, mGPR:$rs, uimm5:$imm)>;
+
+def : CompressPat<(CMPHS32 CARRY:$ca, sGPR:$rs1, sGPR:$rs2),
+ (CMPHS16 CARRY:$ca, sGPR:$rs1, sGPR:$rs2)>;
+def : CompressPat<(CMPLT32 CARRY:$ca, sGPR:$rs1, sGPR:$rs2),
+ (CMPLT16 CARRY:$ca, sGPR:$rs1, sGPR:$rs2)>;
+def : CompressPat<(CMPNE32 CARRY:$ca, sGPR:$rs1, sGPR:$rs2),
+ (CMPNE16 CARRY:$ca, sGPR:$rs1, sGPR:$rs2)>;
+
+def : CompressPat<(CMPHSI32 CARRY:$ca, mGPR:$rs, oimm5:$imm),
+ (CMPHSI16 CARRY:$ca, mGPR:$rs, oimm5:$imm)>;
+def : CompressPat<(CMPLTI32 CARRY:$ca, mGPR:$rs, oimm5:$imm),
+ (CMPLTI16 CARRY:$ca, mGPR:$rs, oimm5:$imm)>;
+def : CompressPat<(CMPNEI32 CARRY:$ca, mGPR:$rs, uimm5:$imm),
+ (CMPNEI16 CARRY:$ca, mGPR:$rs, uimm5:$imm)>;
+
+def : CompressPat<(JSR32 sGPR:$rd),
+ (JSR16 sGPR:$rd)>;
+
+
+def : CompressPat<(MVCV32 sGPR:$rd, CARRY:$ca),
+ (MVCV16 sGPR:$rd, CARRY:$ca)>;
+def : CompressPat<(MOV32 sGPR:$rd, sGPR:$ca),
+ (MOV16 sGPR:$rd, sGPR:$ca)>;
+def : CompressPat<(MOVI32 mGPR:$rd, uimm8:$imm),
+ (MOVI16 mGPR:$rd, uimm8:$imm)>;
+
+def : CompressPat<(LD32B mGPR:$rd, mGPR:$rs, uimm5:$imm),
+ (LD16B mGPR:$rd, mGPR:$rs, uimm5:$imm)>;
+def : CompressPat<(LD32H mGPR:$rd, mGPR:$rs, uimm5_1:$imm),
+ (LD16H mGPR:$rd, mGPR:$rs, uimm5_1:$imm)>;
+def : CompressPat<(LD32W mGPR:$rd, mGPR:$rs, uimm5_2:$imm),
+ (LD16W mGPR:$rd, mGPR:$rs, uimm5_2:$imm)>;
+def : CompressPat<(LD32W mGPR:$rd, GPRSP:$sp, uimm8_2:$imm),
+ (LD16WSP mGPR:$rd, GPRSP:$sp, uimm8_2:$imm)>;
+
+def : CompressPat<(ST32B mGPR:$rd, mGPR:$rs, uimm5:$imm),
+ (ST16B mGPR:$rd, mGPR:$rs, uimm5:$imm)>;
+def : CompressPat<(ST32H mGPR:$rd, mGPR:$rs, uimm5_1:$imm),
+ (ST16H mGPR:$rd, mGPR:$rs, uimm5_1:$imm)>;
+def : CompressPat<(ST32W mGPR:$rd, mGPR:$rs, uimm5_2:$imm),
+ (ST16W mGPR:$rd, mGPR:$rs, uimm5_2:$imm)>;
+def : CompressPat<(ST32W mGPR:$rd, GPRSP:$sp, uimm8_2:$imm),
+ (ST16WSP mGPR:$rd, GPRSP:$sp, uimm8_2:$imm)>;
+
+let Predicates = [HasBTST16] in
+def : CompressPat<(BTSTI32 CARRY:$ca, mGPR:$rs, uimm5:$imm),
+ (BTSTI16 CARRY:$ca, mGPR:$rs, uimm5:$imm)>;
+def : CompressPat<(BCLRI32 mGPR:$rd, mGPR:$rd, uimm5:$imm),
+ (BCLRI16 mGPR:$rd, uimm5:$imm)>;
+def : CompressPat<(BSETI32 mGPR:$rd, mGPR:$rd, uimm5:$imm),
+ (BSETI16 mGPR:$rd, uimm5:$imm)>;
+
+def : CompressPat<(ZEXTB32 sGPR:$rd, sGPR:$rs),
+ (ZEXTB16 sGPR:$rd, sGPR:$rs)>;
+def : CompressPat<(ZEXTH32 sGPR:$rd, sGPR:$rs),
+ (ZEXTH16 sGPR:$rd, sGPR:$rs)>;
+def : CompressPat<(SEXTB32 sGPR:$rd, sGPR:$rs),
+ (SEXTB16 sGPR:$rd, sGPR:$rs)>;
+def : CompressPat<(SEXTH32 sGPR:$rd, sGPR:$rs),
+ (SEXTH16 sGPR:$rd, sGPR:$rs)>;
diff --git a/llvm/lib/Target/CSKY/CSKYMCInstLower.cpp b/llvm/lib/Target/CSKY/CSKYMCInstLower.cpp
index c42a56bfb04e..7e0b9bcd7549 100644
--- a/llvm/lib/Target/CSKY/CSKYMCInstLower.cpp
+++ b/llvm/lib/Target/CSKY/CSKYMCInstLower.cpp
@@ -114,4 +114,4 @@ bool CSKYMCInstLower::lowerOperand(const MachineOperand &MO,
break;
}
return true;
-} \ No newline at end of file
+}
diff --git a/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp b/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp
index a1d45fea534b..57b6ae3c27b5 100644
--- a/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp
+++ b/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp
@@ -88,8 +88,187 @@ CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_I32_SaveList;
}
+static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI,
+ int &Offset) {
+ const MCInstrDesc &Desc = MI->getDesc();
+ unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask);
+ unsigned i = 0;
+ for (; !MI->getOperand(i).isFI(); ++i) {
+ assert(i + 1 < MI->getNumOperands() &&
+ "Instr doesn't have FrameIndex operand!");
+ }
+
+ if (MI->getOpcode() == CSKY::ADDI32) {
+ if (!isUInt<12>(std::abs(Offset) - 1))
+ return false;
+ if (Offset < 0) {
+ MI->setDesc(TII->get(CSKY::SUBI32));
+ Offset = -Offset;
+ }
+
+ return true;
+ }
+
+ if (MI->getOpcode() == CSKY::ADDI16XZ)
+ return false;
+
+ if (Offset < 0)
+ return false;
+
+ unsigned NumBits = 0;
+ unsigned Scale = 1;
+ switch (AddrMode) {
+ case CSKYII::AddrMode32B:
+ Scale = 1;
+ NumBits = 12;
+ break;
+ case CSKYII::AddrMode32H:
+ Scale = 2;
+ NumBits = 12;
+ break;
+ case CSKYII::AddrMode32WD:
+ Scale = 4;
+ NumBits = 12;
+ break;
+ case CSKYII::AddrMode16B:
+ Scale = 1;
+ NumBits = 5;
+ break;
+ case CSKYII::AddrMode16H:
+ Scale = 2;
+ NumBits = 5;
+ break;
+ case CSKYII::AddrMode16W:
+ Scale = 4;
+ NumBits = 5;
+ break;
+ case CSKYII::AddrMode32SDF:
+ Scale = 4;
+ NumBits = 8;
+ break;
+ default:
+ llvm_unreachable("Unsupported addressing mode!");
+ }
+
+ // Cannot encode offset.
+ if ((Offset & (Scale - 1)) != 0)
+ return false;
+
+ unsigned Mask = (1 << NumBits) - 1;
+ if ((unsigned)Offset <= Mask * Scale)
+ return true;
+
+ // Offset out of range.
+ return false;
+}
+
void CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
-} \ No newline at end of file
+
+ MachineInstr *MI = &*II;
+ MachineBasicBlock &MBB = *MI->getParent();
+ MachineFunction &MF = *MI->getParent()->getParent();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo();
+ DebugLoc DL = MI->getDebugLoc();
+ const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
+
+ switch (MI->getOpcode()) {
+ default:
+ break;
+ case CSKY::RESTORE_CARRY: {
+ Register NewReg = STI.hasE2()
+ ? MRI.createVirtualRegister(&CSKY::GPRRegClass)
+ : MRI.createVirtualRegister(&CSKY::mGPRRegClass);
+
+ auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg)
+ .add(MI->getOperand(1))
+ .add(MI->getOperand(2))
+ .getInstr();
+
+ BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16),
+ MI->getOperand(0).getReg())
+ .addReg(NewReg, getKillRegState(true))
+ .addImm(0);
+
+ MI = Temp;
+
+ MBB.erase(II);
+ break;
+ }
+ case CSKY::SPILL_CARRY: {
+ Register NewReg;
+ if (STI.hasE2()) {
+ NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
+ BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg)
+ .add(MI->getOperand(0));
+ } else {
+ NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
+ BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0);
+ BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16))
+ .addReg(NewReg, RegState::Define)
+ .addReg(MI->getOperand(0).getReg(), RegState::Define)
+ .addReg(NewReg, getKillRegState(true))
+ .addReg(NewReg, getKillRegState(true))
+ .addReg(MI->getOperand(0).getReg());
+
+ BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg())
+ .addReg(NewReg)
+ .addImm(0);
+ }
+
+ MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W))
+ .addReg(NewReg, getKillRegState(true))
+ .add(MI->getOperand(1))
+ .add(MI->getOperand(2))
+ .getInstr();
+
+ MBB.erase(II);
+
+ break;
+ }
+ }
+
+ int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
+ Register FrameReg;
+ int Offset = getFrameLowering(MF)
+ ->getFrameIndexReference(MF, FrameIndex, FrameReg)
+ .getFixed() +
+ MI->getOperand(FIOperandNum + 1).getImm();
+
+ if (!isInt<32>(Offset))
+ report_fatal_error(
+ "Frame offsets outside of the signed 32-bit range not supported");
+
+ bool FrameRegIsKill = false;
+ MachineBasicBlock::iterator NewII(MI);
+ if (!IsLegalOffset(TII, MI, Offset)) {
+ assert(isInt<32>(Offset) && "Int32 expected");
+ // The offset won't fit in an immediate, so use a scratch register instead
+ // Modify Offset and FrameReg appropriately
+ assert(Offset >= 0);
+ Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset);
+ BuildMI(MBB, NewII, DL,
+ TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg)
+ .addReg(ScratchReg, RegState::Kill)
+ .addReg(FrameReg);
+
+ Offset = 0;
+ FrameReg = ScratchReg;
+ FrameRegIsKill = true;
+ }
+
+ if (Offset == 0 &&
+ (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) {
+ MI->setDesc(TII->get(TargetOpcode::COPY));
+ MI->getOperand(FIOperandNum)
+ .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
+ MI->RemoveOperand(FIOperandNum + 1);
+ } else {
+ MI->getOperand(FIOperandNum)
+ .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
+ MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
+ }
+}
diff --git a/llvm/lib/Target/CSKY/CSKYRegisterInfo.h b/llvm/lib/Target/CSKY/CSKYRegisterInfo.h
index 779ea6493c7e..5b3b62ec0db2 100644
--- a/llvm/lib/Target/CSKY/CSKYRegisterInfo.h
+++ b/llvm/lib/Target/CSKY/CSKYRegisterInfo.h
@@ -38,6 +38,18 @@ public:
void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS) const override;
+
+ bool requiresFrameIndexScavenging(const MachineFunction &MF) const override {
+ return true;
+ }
+
+ bool requiresRegisterScavenging(const MachineFunction &MF) const override {
+ return true;
+ }
+
+ bool useFPForScavengingIndex(const MachineFunction &MF) const override {
+ return false;
+ }
};
} // namespace llvm
diff --git a/llvm/lib/Target/CSKY/CSKYRegisterInfo.td b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td
index 7548c22bb2c5..ade5c7f795af 100644
--- a/llvm/lib/Target/CSKY/CSKYRegisterInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td
@@ -168,6 +168,11 @@ def mGPR : RegisterClass<"CSKY", [i32], 32,
let Size = 32;
}
+// Register class for SP only.
+def GPRSP : RegisterClass<"CSKY", [i32], 32, (add R14)> {
+ let Size = 32;
+}
+
def GPRPair : RegisterClass<"CSKY", [untyped], 32, (add GPRTuple)> {
let Size = 64;
}