[llvm] bdd7c53 - [CSKY] Add compressed instruction mapping between 32-bit and 16-bit instruction
Zi Xuan Wu via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 5 22:05:11 PST 2021
Author: Zi Xuan Wu
Date: 2021-12-06T14:04:54+08:00
New Revision: bdd7c53dc5e0fc3c3fde408df2fd187b11bb8330
URL: https://github.com/llvm/llvm-project/commit/bdd7c53dc5e0fc3c3fde408df2fd187b11bb8330
DIFF: https://github.com/llvm/llvm-project/commit/bdd7c53dc5e0fc3c3fde408df2fd187b11bb8330.diff
LOG: [CSKY] Add compressed instruction mapping between 32-bit and 16-bit instruction
Add all CompressPat to map instructions between 16-bit and 32-bit with using the CompressInstEmitter infra.
Although it's only used in asm printer, also enable it in asm parser to debug mapping when -enable-csky-asm-compressed-inst is on.
Differential Revision: https://reviews.llvm.org/D115026
Added:
llvm/test/MC/CSKY/compressed-inst.s
Modified:
llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
llvm/lib/Target/CSKY/CMakeLists.txt
llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
llvm/lib/Target/CSKY/CSKYAsmPrinter.h
llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td
llvm/lib/Target/CSKY/CSKYInstrInfo.td
llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td
llvm/lib/Target/CSKY/CSKYRegisterInfo.td
llvm/test/CodeGen/CSKY/base-i.ll
llvm/test/MC/CSKY/basic-16bit.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
index ebc04b40d428d..29b99a84a6cd3 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 @@ struct CSKYOperand : public MCParsedAsmOperand {
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/CMakeLists.txt b/llvm/lib/Target/CSKY/CMakeLists.txt
index c7eb89773b751..e107b013a296d 100644
--- a/llvm/lib/Target/CSKY/CMakeLists.txt
+++ b/llvm/lib/Target/CSKY/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_TARGET_DEFINITIONS CSKY.td)
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.cpp b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
index 1c38c5d1fde6e..85129f78e7268 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 f0f5d8657c04d..b30311e0ca649 100644
--- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
+++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
@@ -26,6 +26,8 @@ class LLVM_LIBRARY_VISIBILITY CSKYAsmPrinter : public AsmPrinter {
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/CSKYInstrFormats16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td
index 6d42bddcdd782..ea0761d97545d 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.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
index 9dda3159e446e..32e6cfd7e40f0 100644
--- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td
+++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td
@@ -166,9 +166,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 +191,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 +230,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 +747,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.
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td
index c98f436221557..6a9dd03dfa1d4 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/CSKYRegisterInfo.td b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td
index 7548c22bb2c5e..ade5c7f795af2 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;
}
diff --git a/llvm/test/CodeGen/CSKY/base-i.ll b/llvm/test/CodeGen/CSKY/base-i.ll
index 083d939954b8e..c1fa0f63eae42 100644
--- 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 @@ entry:
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 @@ define i32 @addRI_X(i32 %x) {
; 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
index 9b484431f6e9b..8323df13213d8 100644
--- a/llvm/test/MC/CSKY/basic-16bit.s
+++ b/llvm/test/MC/CSKY/basic-16bit.s
@@ -226,7 +226,7 @@ lrw16 a0, [.L.test14]
.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, a1, 0x11, 0x60 # CHECK: :[[@LINE]]:22: error: invalid operand for ins
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
index 0000000000000..2418d108501b5
--- /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
More information about the llvm-commits
mailing list