Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -63,9 +63,13 @@ bool parseOperand(OperandVector &Operands); + unsigned checkEarlyTargetMatchPredicate(MCInst &Inst, + const OperandVector &Operands) override; + public: enum RISCVMatchResultTy { Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, + Match_RequiresSameSrcAndDst, #define GET_OPERAND_DIAGNOSTIC_TYPES #include "RISCVGenAsmMatcher.inc" #undef GET_OPERAND_DIAGNOSTIC_TYPES @@ -492,6 +496,19 @@ assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createImm(getRoundingMode())); } + + bool isValidForTie(const RISCVOperand &Other) const { + if (Kind != Other.Kind) + return false; + + switch (Kind) { + default: + llvm_unreachable("Unexpected kind"); + return false; + case Register: + return getReg() == Other.getReg(); + } + } }; } // end anonymous namespace. @@ -584,6 +601,8 @@ Inst.setLoc(IDLoc); Out.EmitInstruction(Inst, getSTI()); return false; + case Match_RequiresSameSrcAndDst: + return Error(IDLoc, "instruction use requires same src and destination."); case Match_MissingFeature: return Error(IDLoc, "instruction use requires an option to be enabled"); case Match_MnemonicFail: @@ -859,6 +878,58 @@ return true; } +unsigned +RISCVAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst, + const OperandVector &Operands) { + StringRef ExpandedOp; + + switch (Inst.getOpcode()) { + default: + return Match_Success; + case RISCV::C_ADD: + ExpandedOp = "add"; break; + case RISCV::C_ADDW: + ExpandedOp = "addw"; break; + case RISCV::C_SUB: + ExpandedOp = "sub"; break; + case RISCV::C_SUBW: + ExpandedOp = "subw"; break; + case RISCV::C_AND: + ExpandedOp = "and"; break; + case RISCV::C_OR: + ExpandedOp = "or"; break; + case RISCV::C_XOR: + ExpandedOp = "xor"; break; + case RISCV::C_ADDI: + ExpandedOp = "addi"; break; + case RISCV::C_ANDI: + ExpandedOp = "andi"; break; + case RISCV::C_SLLI: + ExpandedOp = "slli"; break; + case RISCV::C_SRLI: + ExpandedOp = "srli"; break; + case RISCV::C_SRAI: + ExpandedOp = "srai"; break; + } + + if (((RISCVOperand&)*Operands[0]).getToken() != ExpandedOp) + return Match_Success; + + // Check for tied src and dst operands. + if (static_cast(*Operands[1]) + .isValidForTie(static_cast(*Operands[2]))) + return Match_Success; + + // Check for commuted tied src and dst operands. + if (ExpandedOp == "add" || ExpandedOp == "addw" || ExpandedOp == "and" || + ExpandedOp == "or" || ExpandedOp == "xor") + if (static_cast(*Operands[1]) + .isValidForTie(static_cast(*Operands[3]))) + return Match_Success; + + return Match_RequiresSameSrcAndDst; +} + bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { Index: lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfoC.td +++ lib/Target/RISCV/RISCVInstrInfoC.td @@ -416,4 +416,46 @@ let Inst{9-7} = imm{8-6}; } +def : InstAlias<"add {$rs1, $rs1, $rs2 | $rs1, $rs2, $rs1}", + (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; +def : InstAlias<"and {$rs1, $rs1, $rs2 | $rs1, $rs2, $rs1}", + (C_AND GPRC:$rs1, GPRC:$rs2)>; +def : InstAlias<"or {$rs1, $rs1, $rs2 | $rs1, $rs2, $rs1}", + (C_OR GPRC:$rs1, GPRC:$rs2)>; +def : InstAlias<"xor {$rs1, $rs1, $rs2 | $rs1, $rs2, $rs1}", + (C_XOR GPRC:$rs1, GPRC:$rs2)>; +def : InstAlias<"sub $rs1, $rs1, $rs2", (C_SUB GPRC:$rs1, GPRC:$rs2)>; +def : InstAlias<"addi $rs1, $rs1, $imm", (C_ADDI GPRNoX0:$rs1, simm6:$imm)>; +def : InstAlias<"andi $rs1, $rs1, $imm", (C_ANDI GPRC:$rs1, simm6:$imm)>; +def : InstAlias<"slli $rs1, $rs1, $imm", (C_SLLI GPRC:$rs1, uimmlog2xlennonzero:$imm)>; +def : InstAlias<"srli $rs1, $rs1, $imm", (C_SLLI GPRC:$rs1, uimmlog2xlennonzero:$imm)>; +def : InstAlias<"srai $rs1, $rs1, $imm", (C_SRAI GPRC:$rs1, uimmlog2xlennonzero:$imm)>; + +def : InstAlias<"jal x0, $offset", (C_J simm12_lsb0:$offset)>; +def : InstAlias<"jal x1, $offset", (C_JAL simm12_lsb0:$offset)>; +def : InstAlias<"beq, $rs1, x0, $imm", (C_BEQZ GPRC:$rs1, simm9_lsb0:$imm)>; +def : InstAlias<"bne, $rs1, x0, $imm", (C_BNEZ GPRC:$rs1, simm9_lsb0:$imm)>; +def : InstAlias<"addi $rd, x0, $imm", (C_LI GPRNoX0:$rd, simm6:$imm)>; +def : InstAlias<"add $rs1, x0, $rs2", (C_MV GPRNoX0:$rs1, GPRNoX0:$rs2)>; +def : InstAlias<"add $rs1, $rs2, x0", (C_MV GPRNoX0:$rs1, GPRNoX0:$rs2)>; +def : InstAlias<"addi x2, x2, $imm", (C_ADDI16SP X2, simm10_lsb0000:$imm)>; +def : InstAlias<"lw $rd, $imm (${rs1})", (C_LWSP GPRNoX0:$rd, SP:$rs1, uimm8_lsb00:$imm)>; +def : InstAlias<"addi $rd, $rs1, $imm", (C_ADDI4SPN GPRC:$rd, SP:$rs1, uimm10_lsb00nonzero:$imm), 0>; +def : InstAlias<"lui $rd, $imm", (C_LUI GPRNoX0X2:$rd, uimm6nonzero:$imm), 0>; +def : InstAlias<"sw $rs2, $imm (${rs1})", (C_SW GPRC:$rs2, GPRC:$rs1, uimm7_lsb00:$imm)>; + +// Not working yet +//def : InstAlias<"jalr x1, $rs1, 0", (C_JALR GPRNoX0:$rs1), 0>; +//def : InstAlias<"sw $rs2, $imm (${rs1})", (C_SWSP GPR:$rs2, SP:$rs1, uimm8_lsb00:$imm)>; + } // Predicates = [HasStdExtC] + +let Predicates = [HasStdExtC, IsRV64] in { +def : InstAlias<"addw {$rs1, $rs1, $rs2 | $rs1, $rs2, $rs1}", + (C_ADDW GPRC:$rs1, GPRC:$rs2)>; +def : InstAlias<"subw $rs1, $rs1, $rs2", (C_SUBW GPRC:$rs1, GPRC:$rs2)>; +} // Predicates = [HasStdExtC, IsRV64] + +// todo: add D and Q aliases +// todo: add FP aliases + Index: utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- utils/TableGen/AsmMatcherEmitter.cpp +++ utils/TableGen/AsmMatcherEmitter.cpp @@ -1526,7 +1526,7 @@ II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst); // Validate the alias definitions. - II->validate(CommentDelimiter, false); + II->validate(CommentDelimiter, true); Matchables.push_back(std::move(II)); }