diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp --- 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 + 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 X(getTheCSKYTarget()); } diff --git a/llvm/lib/Target/CSKY/CMakeLists.txt b/llvm/lib/Target/CSKY/CMakeLists.txt --- a/llvm/lib/Target/CSKY/CMakeLists.txt +++ b/llvm/lib/Target/CSKY/CMakeLists.txt @@ -5,6 +5,7 @@ tablegen(LLVM CSKYGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM CSKYGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM CSKYGenCallingConv.inc -gen-callingconv) +tablegen(LLVM CSKYGenCompressInstEmitter.inc -gen-compress-inst-emitter) tablegen(LLVM CSKYGenDAGISel.inc -gen-dag-isel) tablegen(LLVM CSKYGenInstrInfo.inc -gen-instr-info) tablegen(LLVM CSKYGenMCCodeEmitter.inc -gen-emitter) diff --git a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h --- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h +++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h @@ -26,6 +26,8 @@ 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/CSKYAsmPrinter.cpp b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp --- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp +++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp @@ -30,6 +30,9 @@ #define DEBUG_TYPE "csky-asm-printer" +STATISTIC(CSKYNumInstrsCompressed, + "Number of C-SKY Compressed instructions emitted"); + CSKYAsmPrinter::CSKYAsmPrinter(llvm::TargetMachine &TM, std::unique_ptr Streamer) : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {} @@ -39,6 +42,16 @@ 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/CSKYInstrFormats16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td --- a/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td +++ b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td @@ -88,6 +88,19 @@ let Inst{1, 0} = sop; } +class R16_Z_UNOP 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 sop, string opstr> : CSKY16Inst< AddrModeNone, (outs CARRY:$ca), (ins sGPR:$rx, sGPR:$ry), !strconcat(opstr, "\t$rx, $ry"), []> { @@ -146,7 +159,7 @@ } class I16_SP_IMM7 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.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td --- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td +++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td @@ -166,9 +166,23 @@ 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, ImmLeaf; -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 +230,98 @@ 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 +747,6 @@ let Defs = [ R15 ]; } -let Predicates = [iHasE2], isCodeGenOnly = 1 in { - def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>; -} - - //===----------------------------------------------------------------------===// // Symbol address instructions. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td --- a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td +++ b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td @@ -33,16 +33,6 @@ let OperandType = "OPERAND_PCREL"; } -def SPOperand : AsmOperandClass { - let Name = "SPOperand"; - let RenderMethod = "addRegOperands"; - let DiagnosticType = !strconcat("Invalid", Name); -} - -def SPOp : RegisterOperand { - let ParserMatchClass = SPOperand; -} - def constpool_symbol_16bit : Operand { let ParserMatchClass = Constpool; let EncoderMethod = @@ -83,7 +73,7 @@ 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 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 @@ (outs), (ins mGPR:$rz, mGPR:$rx, uimm5_2:$imm)>; def LD16WSP : I16_ZSP_LDST; + (outs mGPR:$rz), (ins GPRSP:$sp, uimm8_2:$addr)>; def ST16WSP : I16_ZSP_LDST; + (outs), (ins mGPR:$rz, GPRSP:$sp, uimm8_2:$addr)>; //===----------------------------------------------------------------------===// // Compare instructions. @@ -450,3 +440,150 @@ 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/CSKYRegisterInfo.td b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td --- a/llvm/lib/Target/CSKY/CSKYRegisterInfo.td +++ b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td @@ -168,6 +168,11 @@ 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; } diff --git a/llvm/test/CodeGen/CSKY/base-i.ll b/llvm/test/CodeGen/CSKY/base-i.ll --- a/llvm/test/CodeGen/CSKY/base-i.ll +++ b/llvm/test/CodeGen/CSKY/base-i.ll @@ -4,8 +4,8 @@ define i32 @addRR(i32 %x, i32 %y) { ; CHECK-LABEL: addRR: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addu32 a0, a1, a0 -; CHECK-NEXT: rts32 +; CHECK-NEXT: addu16 a0, a1 +; CHECK-NEXT: rts16 entry: %add = add nsw i32 %y, %x ret i32 %add @@ -14,8 +14,8 @@ define i32 @addRI(i32 %x) { ; CHECK-LABEL: addRI: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi32 a0, a0, 10 -; CHECK-NEXT: rts32 +; CHECK-NEXT: addi16 a0, 10 +; CHECK-NEXT: rts16 entry: %add = add nsw i32 %x, 10 ret i32 %add @@ -25,8 +25,8 @@ ; CHECK-LABEL: addRI_X: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movi32 a1, 4097 -; CHECK-NEXT: addu32 a0, a0, a1 -; CHECK-NEXT: rts32 +; CHECK-NEXT: addu16 a0, a1 +; CHECK-NEXT: rts16 entry: %add = add nsw i32 %x, 4097 ret i32 %add diff --git a/llvm/test/MC/CSKY/basic-16bit.s b/llvm/test/MC/CSKY/basic-16bit.s --- a/llvm/test/MC/CSKY/basic-16bit.s +++ b/llvm/test/MC/CSKY/basic-16bit.s @@ -226,7 +226,7 @@ .ifdef ERR # oimm8 -addi16 a0, 0 # CHECK: :[[#@LINE]]:12: error: operand must be sp register +addi16 a0, 0 # CHECK: :[[#@LINE]]:12: error: immediate must be an integer in the range [1, 256] # oimm5 cmphsi16 a0, 0 # CHECK: :[[#@LINE]]:14: error: immediate must be an integer in the range [1, 32] @@ -267,4 +267,4 @@ lsli16 a0 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction lsl16 a0 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction -.endif \ No newline at end of file +.endif diff --git a/llvm/test/MC/CSKY/compressed-inst.s b/llvm/test/MC/CSKY/compressed-inst.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/CSKY/compressed-inst.s @@ -0,0 +1,210 @@ +# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -enable-csky-asm-compressed-inst=true -mattr=+e1 \ +# RUN: -mattr=+e2 -mattr=+2e3 -mattr=+btst16 | FileCheck -check-prefixes=CHECK-ASM %s + +# CHECK-ASM: addu16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x60] +addu32 a0, a0, a1 + +# CHECK-ASM: addu16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x60] +addu32 a0, a1, a0 + +# CHECK-ASM: addu16 a0, a1, a2 +# CHECK-ASM: encoding: [0x08,0x59] +addu32 a0, a1, a2 + +# CHECK-ASM: subu16 a0, a1 +# CHECK-ASM: encoding: [0x06,0x60] +subu32 a0, a0, a1 + +# CHECK-ASM: subu16 a0, a1, a2 +# CHECK-ASM: encoding: [0x09,0x59] +subu32 a0, a1, a2 + +# CHECK-ASM: addc16 a0, a1 +# CHECK-ASM: encoding: [0x05,0x60] +addc32 a0, a0, a1 + +# CHECK-ASM: subc16 a0, a1 +# CHECK-ASM: encoding: [0x07,0x60] +subc32 a0, a0, a1 + +# CHECK-ASM: addi16 a0, a1, 1 +# CHECK-ASM: encoding: [0x02,0x59] +addi32 a0, a1, 1 + +# CHECK-ASM: subi16 a0, a1, 1 +# CHECK-ASM: encoding: [0x03,0x59] +subi32 a0, a1, 1 + +# CHECK-ASM: addi16 a0, 10 +# CHECK-ASM: encoding: [0x09,0x20] +addi32 a0, a0, 10 + +# CHECK-ASM: subi16 a0, 10 +# CHECK-ASM: encoding: [0x09,0x28] +subi32 a0, a0, 10 + +# CHECK-ASM: addi16 sp, sp, 4 +# CHECK-ASM: encoding: [0x01,0x14] +addi32 sp, sp, 4 + +# CHECK-ASM: subi16 sp, sp, 4 +# CHECK-ASM: encoding: [0x21,0x14] +subi32 sp, sp, 4 + +# CHECK-ASM: addi16 a0, sp, 4 +# CHECK-ASM: encoding: [0x01,0x18] +addi32 a0, sp, 4 + +# CHECK-ASM: mult16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x7c] +mult32 a0, a0, a1 + +# CHECK-ASM: mult16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x7c] +mult32 a0, a1, a0 + +# CHECK-ASM: and16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x68] +and32 a0, a0, a1 + +# CHECK-ASM: and16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x68] +and32 a0, a1, a0 + +# CHECK-ASM: or16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x6c] +or32 a0, a0, a1 + +# CHECK-ASM: or16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x6c] +or32 a0, a1, a0 + +# CHECK-ASM: xor16 a0, a1 +# CHECK-ASM: encoding: [0x05,0x6c] +xor32 a0, a0, a1 + +# CHECK-ASM: xor16 a0, a1 +# CHECK-ASM: encoding: [0x05,0x6c] +xor32 a0, a1, a0 + +# CHECK-ASM: andn16 a0, a1 +# CHECK-ASM: encoding: [0x05,0x68] +andn32 a0, a0, a1 + +# CHECK-ASM: nor16 a0, a1 +# CHECK-ASM: encoding: [0x06,0x6c] +nor32 a0, a0, a1 + +# CHECK-ASM: lsl16 a0, a1 +# CHECK-ASM: encoding: [0x04,0x70] +lsl32 a0, a0, a1 + +# CHECK-ASM: lsr16 a0, a1 +# CHECK-ASM: encoding: [0x05,0x70] +lsr32 a0, a0, a1 + +# CHECK-ASM: asr16 a0, a1 +# CHECK-ASM: encoding: [0x06,0x70] +asr32 a0, a0, a1 + +# CHECK-ASM: rotl16 a0, a1 +# CHECK-ASM: encoding: [0x07,0x70] +rotl32 a0, a0, a1 + +# CHECK-ASM: revb16 a0, a1 +# CHECK-ASM: encoding: [0x06,0x78] +revb32 a0, a1 + +# CHECK-ASM: lsli16 a0, a1, 2 +# CHECK-ASM: encoding: [0x02,0x41] +lsli32 a0, a1, 2 + +# CHECK-ASM: lsri16 a0, a1, 2 +# CHECK-ASM: encoding: [0x02,0x49] +lsri32 a0, a1, 2 + +# CHECK-ASM: asri16 a0, a1, 2 +# CHECK-ASM: encoding: [0x02,0x51] +asri32 a0, a1, 2 + +# CHECK-ASM: cmphs16 a0, a1 +# CHECK-ASM: encoding: [0x40,0x64] +cmphs32 a0, a1 + +# CHECK-ASM: cmplt16 a0, a1 +# CHECK-ASM: encoding: [0x41,0x64] +cmplt32 a0, a1 + +# CHECK-ASM: cmpne16 a0, a1 +# CHECK-ASM: encoding: [0x42,0x64] +cmpne32 a0, a1 + +# CHECK-ASM: cmphsi16 a0, 1 +# CHECK-ASM: encoding: [0x00,0x38] +cmphsi32 a0, 1 + +# CHECK-ASM: cmplti16 a0, 1 +# CHECK-ASM: encoding: [0x20,0x38] +cmplti32 a0, 1 + +# CHECK-ASM: cmpnei16 a0, 1 +# CHECK-ASM: encoding: [0x41,0x38] +cmpnei32 a0, 1 + +# CHECK-ASM: jsr16 a0 +# CHECK-ASM: encoding: [0xc1,0x7b] +jsr32 a0 + +# CHECK-ASM: mvcv16 a0 +# CHECK-ASM: encoding: [0x03,0x64] +mvcv32 a0 + +# CHECK-ASM: movi16 a0, 1 +# CHECK-ASM: encoding: [0x01,0x30] +movi32 a0, 1 + +# CHECK-ASM: ld16.b a0, (a1, 1) +# CHECK-ASM: encoding: [0x01,0x81] +ld32.b a0, (a1, 1) + +# CHECK-ASM: ld16.h a0, (a1, 2) +# CHECK-ASM: encoding: [0x01,0x89] +ld32.h a0, (a1, 2) + +# CHECK-ASM: ld16.w a0, (a1, 4) +# CHECK-ASM: encoding: [0x01,0x91] +ld32.w a0, (a1, 4) + +# CHECK-ASM: ld16.w a0, (sp, 4) +# CHECK-ASM: encoding: [0x01,0x98] +ld32.w a0, (sp, 4) + +# CHECK-ASM: st16.b a0, (a1, 1) +# CHECK-ASM: encoding: [0x01,0xa1] +st32.b a0, (a1, 1) + +# CHECK-ASM: st16.h a0, (a1, 2) +# CHECK-ASM: encoding: [0x01,0xa9] +st32.h a0, (a1, 2) + +# CHECK-ASM: st16.w a0, (a1, 4) +# CHECK-ASM: encoding: [0x01,0xb1] +st32.w a0, (a1, 4) + +# CHECK-ASM: st16.w a0, (sp, 4) +# CHECK-ASM: encoding: [0x01,0xb8] +st32.w a0, (sp, 4) + +# CHECK-ASM: btsti16 a0, 1 +# CHECK-ASM: encoding: [0xc1,0x38] +btsti32 a0, 1 + +# CHECK-ASM: bclri16 a0, 1 +# CHECK-ASM: encoding: [0x81,0x38] +bclri32 a0, a0, 1 + +# CHECK-ASM: bseti16 a0, 1 +# CHECK-ASM: encoding: [0xa1,0x38] +bseti32 a0, a0, 1