Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/LoongArchBaseInfo.h"
#include "MCTargetDesc/LoongArchInstPrinter.h"
#include "MCTargetDesc/LoongArchMCExpr.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
Expand Down Expand Up @@ -1560,18 +1561,14 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,

unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
unsigned Opc = Inst.getOpcode();
const MCInstrDesc &MCID = MII.get(Opc);
switch (Opc) {
default:
if (Opc >= LoongArch::AMCAS_B && Opc <= LoongArch::AMCAS__DB_W) {
if (LoongArchII::isSubjectToAMORdConstraint(MCID.TSFlags)) {
const bool IsAMCAS = LoongArchII::isAMCAS(MCID.TSFlags);
MCRegister Rd = Inst.getOperand(0).getReg();
MCRegister Rk = Inst.getOperand(2).getReg();
MCRegister Rj = Inst.getOperand(3).getReg();
if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
return Match_RequiresAMORdDifferRkRj;
} else if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) {
MCRegister Rd = Inst.getOperand(0).getReg();
MCRegister Rk = Inst.getOperand(1).getReg();
MCRegister Rj = Inst.getOperand(2).getReg();
MCRegister Rk = Inst.getOperand(IsAMCAS ? 2 : 1).getReg();
MCRegister Rj = Inst.getOperand(IsAMCAS ? 3 : 2).getReg();
if ((Rd == Rk || Rd == Rj) && Rd != LoongArch::R0)
return Match_RequiresAMORdDifferRkRj;
}
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ class LAInst<dag outs, dag ins, string opcstr, string opnstr,
let InOperandList = ins;
let AsmString = opcstr # "\t" # opnstr;
let Pattern = pattern;

// Target-specific instruction info and defaults

bit IsSubjectToAMORdConstraint = 0;
let TSFlags{0} = IsSubjectToAMORdConstraint;

bit IsAMCAS = 0;
let TSFlags{1} = IsAMCAS;
}

// Pseudo instructions
Expand Down
18 changes: 12 additions & 6 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -711,15 +711,21 @@ class STORE_2RI14<bits<32> op>
} // hasSideEffects = 0, mayLoad = 0, mayStore = 1

let hasSideEffects = 0, mayLoad = 1, mayStore = 1,
Constraints = "@earlyclobber $rd" in class AM_3R<bits<32> op>
IsSubjectToAMORdConstraint = 1 in {
class AM_3R<bits<32> op>
: Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AM_3R is incompatible with amcas,
Unlike other am** instructions, amcas rd rk rj , rd should be read, pervious version consider rd write only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AM_3R is incompatible with amcas, Unlike other am** instructions, amcas rd rk rj , rd should be read, pervious version consider rd write only.

Thanks for the suggestion, I have posted #114508 to precede this PR.

"$rd, $rk, $rj">;
"$rd, $rk, $rj"> {
let Constraints = "@earlyclobber $rd";
}

let hasSideEffects = 0, mayLoad = 1, mayStore = 1,
Constraints =
"@earlyclobber $rd_wb, $rd_wb = $rd" in class AMCAS_3R<bits<32> op>
class AMCAS_3R<bits<32> op>
: Fmt3R<op, (outs GPR:$rd_wb), (ins GPR:$rd, GPR:$rk, GPRMemAtomic:$rj),
"$rd, $rk, $rj">;
"$rd, $rk, $rj"> {
let Constraints = "@earlyclobber $rd_wb, $rd_wb = $rd";
let IsAMCAS = 1;
}
} // hasSideEffects = 0, mayLoad = 1, mayStore = 1,
// IsSubjectToAMORdConstraint = 1

let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
class LLBase<bits<32> op>
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,36 @@ enum {
MO_DESC_CALL,
// TODO: Add more flags.
};

// Target-specific flags of LAInst.
// All definitions must match LoongArchInstrFormats.td.
enum {
// Whether the instruction's rd is normally required to differ from rj and
// rk, in the way the 3-register atomic memory operations behave
// (Section 2.2.7.1 and 2.2.7.2, LoongArch Reference Manual Volume 1 v1.10;
// while Section 2.2.7.3 lacked similar description for the AMCAS
// instructions, at least the INE exception is still signaled on Loongson
// 3A6000 when its rd == rj).
//
// Used for generating diagnostics for assembler input that violate the
// constraint. As described on the manual, the covered instructions require
// rd != rj && rd != rk to work as intended.
IsSubjectToAMORdConstraintShift = 0,
IsSubjectToAMORdConstraintMask = 1 << IsSubjectToAMORdConstraintShift,

// Whether the instruction belongs to the AMCAS family.
IsAMCASShift = IsSubjectToAMORdConstraintShift + 1,
IsAMCASMask = 1 << IsAMCASShift,
};

/// \returns true if this instruction's rd is normally required to differ
/// from rj and rk, in the way 3-register atomic memory operations behave.
static inline bool isSubjectToAMORdConstraint(uint64_t TSFlags) {
return TSFlags & IsSubjectToAMORdConstraintMask;
}

/// \returns true if this instruction belongs to the AMCAS family.
static inline bool isAMCAS(uint64_t TSFlags) { return TSFlags & IsAMCASMask; }
} // end namespace LoongArchII

namespace LoongArchABI {
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,14 @@ amxor.w $a0, $a1, $a0
amadd.d $a0, $a1, $a2, $a3
# CHECK: :[[#@LINE+1]]:24: error: optional integer offset must be 0
amadd.d $a0, $a1, $a2, 1

## According to experiment results on real LA664 HW, the AMCAS instructions
## are subject to the same constraint as the other 3-register atomic insns.
## This is undocumented in v1.10 of the LoongArch Reference Manual.

# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj
amcas.b $a0, $a0, $a0
# CHECK: :[[#@LINE+1]]:10: error: $rd must be different from both $rk and $rj
amcas.h $a0, $a0, $a1
# CHECK: :[[#@LINE+1]]:13: error: $rd must be different from both $rk and $rj
amcas_db.w $a0, $a1, $a0
Loading