diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp index 10b4660fa1988b..77f431bafa2b23 100644 --- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp @@ -74,6 +74,7 @@ class LoongArchAsmParser : public MCTargetAsmParser { Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, Match_RequiresMsbNotLessThanLsb, Match_RequiresOpnd2NotR0R1, + Match_RequiresAMORdDifferRkRj, #define GET_OPERAND_DIAGNOSTIC_TYPES #include "LoongArchGenAsmMatcher.inc" #undef GET_OPERAND_DIAGNOSTIC_TYPES @@ -667,8 +668,16 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) { - switch (Inst.getOpcode()) { + unsigned Opc = Inst.getOpcode(); + switch (Opc) { default: + if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) { + unsigned Rd = Inst.getOperand(0).getReg(); + unsigned Rk = Inst.getOperand(1).getReg(); + unsigned Rj = Inst.getOperand(2).getReg(); + if (Rd == Rk || Rd == Rj) + return Match_RequiresAMORdDifferRkRj; + } break; case LoongArch::CSRXCHG: { unsigned Rj = Inst.getOperand(2).getReg(); @@ -791,6 +800,9 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } case Match_RequiresOpnd2NotR0R1: return Error(Operands[2]->getStartLoc(), "must not be $r0 or $r1"); + case Match_RequiresAMORdDifferRkRj: + return Error(Operands[1]->getStartLoc(), + "$rd must be different from both $rk and $rj"); case Match_InvalidUImm2: return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0, /*Upper=*/(1 << 2) - 1); diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s index 5ee9659cdb7bfd..7e67a19e917bc0 100644 --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s @@ -79,3 +79,17 @@ bstrins.d $a0, $a0, 1, 2 # CHECK: :[[#@LINE+1]]:22: error: msb is less than lsb bstrpick.d $a0, $a0, 32, 63 # CHECK: ^~~~~~ + +# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj +amadd.d $zero, $zero, $zero +# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj +ammin.w $zero, $zero, $a0 +# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj +amxor.w $zero, $a0, $zero + +# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj +amadd.d $a0, $a0, $a0 +# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj +ammin.w $a0, $a0, $a1 +# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj +amxor.w $a0, $a1, $a0