diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-12-25 22:30:44 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-12-25 22:30:44 +0000 |
| commit | 77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (patch) | |
| tree | 5c0eb39553003b9c75a901af6bc4ddabd6f2f28c /llvm/lib/Target/CSKY | |
| parent | f65dcba83ce5035ab88a85fe17628b447eb56e1b (diff) | |
Diffstat (limited to 'llvm/lib/Target/CSKY')
| -rw-r--r-- | llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp | 91 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYAsmPrinter.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYCallingConv.td | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYFrameLowering.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYISelDAGToDAG.cpp | 89 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYISelLowering.cpp | 40 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td | 15 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrInfo.cpp | 288 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrInfo.h | 25 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrInfo.td | 241 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td | 165 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYMCInstLower.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp | 181 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYRegisterInfo.h | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/CSKY/CSKYRegisterInfo.td | 5 |
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; } |
