Skip to content

[LoongArch][NFC] Fix the operand constraint of AMCAS instructions #114508

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 19, 2024

Conversation

xen0n
Copy link
Contributor

@xen0n xen0n commented Nov 1, 2024

The rd operand of AMCAS instructions is both read and written, because of the nature of compare-and-swap operations, but currently it is not declared as such. Fix it for upcoming codegen enablement changes. In order to do that, a piece of LoongArchAsmParser logic that relied on TableGen-erated enum variants being ordered in a specific way needs updating; this will be addressed in a following refactor. No functional change intended.

While at it, restore vertical alignment for the definition lines.

Suggested-by: tangaac [email protected]
Link: #114398 (comment)

@llvmbot
Copy link
Member

llvmbot commented Nov 1, 2024

@llvm/pr-subscribers-backend-loongarch

Author: WÁNG Xuěruì (xen0n)

Changes

The rd operand of AMCAS instructions is both read and written, because of the nature of compare-and-swap operations, but currently it is not declared as such. Fix it for upcoming codegen enablement changes. No functional change.

While at it, restore vertical alignment for the definition lines.

Suggested-by: tangaac <[email protected]>
Link: #114398 (comment)


Full diff: https://github.com/llvm/llvm-project/pull/114508.diff

2 Files Affected:

  • (modified) llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (+2-1)
  • (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (+13-8)
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index b4b19caed8999e..7e285f0facb2dd 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -1562,7 +1562,8 @@ unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
   unsigned Opc = Inst.getOpcode();
   switch (Opc) {
   default:
-    if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W) {
+    if (Opc >= LoongArch::AMADD_D && Opc <= LoongArch::AMXOR_W &&
+        !(Opc >= LoongArch::AMCAS_B && Opc <= LoongArch::AMCAS__DB_W)) {
       MCRegister Rd = Inst.getOperand(0).getReg();
       MCRegister Rk = Inst.getOperand(1).getReg();
       MCRegister Rj = Inst.getOperand(2).getReg();
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index ccdd5165728231..8a9316f1133c9b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -715,6 +715,11 @@ class AM_3R<bits<32> op>
     : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj),
             "$rd, $rk, $rj">;
 
+let hasSideEffects = 0, mayLoad = 1, mayStore = 1, Constraints = "$rd = $rd_wb" in
+class AMCAS_3R<bits<32> op>
+    : Fmt3R<op, (outs GPR:$rd_wb), (ins GPR:$rd, GPR:$rk, GPRMemAtomic:$rj),
+            "$rd, $rk, $rj">;
+
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
 class LLBase<bits<32> op>
     : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14),
@@ -1024,14 +1029,14 @@ def AMMAX__DB_WU : AM_3R<0x38700000>;
 def AMMAX__DB_DU : AM_3R<0x38708000>;
 def AMMIN__DB_WU : AM_3R<0x38710000>;
 def AMMIN__DB_DU : AM_3R<0x38718000>;
-def AMCAS_B     : AM_3R<0x38580000>;
-def AMCAS_H     : AM_3R<0x38588000>;
-def AMCAS_W     : AM_3R<0x38590000>;
-def AMCAS_D     : AM_3R<0x38598000>;
-def AMCAS__DB_B     : AM_3R<0x385a0000>;
-def AMCAS__DB_H     : AM_3R<0x385a8000>;
-def AMCAS__DB_W     : AM_3R<0x385b0000>;
-def AMCAS__DB_D     : AM_3R<0x385b8000>;
+def AMCAS_B      : AMCAS_3R<0x38580000>;
+def AMCAS_H      : AMCAS_3R<0x38588000>;
+def AMCAS_W      : AMCAS_3R<0x38590000>;
+def AMCAS_D      : AMCAS_3R<0x38598000>;
+def AMCAS__DB_B  : AMCAS_3R<0x385a0000>;
+def AMCAS__DB_H  : AMCAS_3R<0x385a8000>;
+def AMCAS__DB_W  : AMCAS_3R<0x385b0000>;
+def AMCAS__DB_D  : AMCAS_3R<0x385b8000>;
 def LL_D : LLBase<0x22000000>;
 def SC_D : SCBase<0x23000000>;
 def SC_Q : SCBase_128<0x38570000>;

@tangaac
Copy link
Contributor

tangaac commented Nov 1, 2024

AMADD_B, AMXOR__DB_D, AMXOR_DB_W escape from the check.

From the inc file, it should be

Opc >= LoongArch::AMADD_B && Opc <= LoongArch::AMXOR_DB_W

@xen0n
Copy link
Contributor Author

xen0n commented Nov 1, 2024

AMADD_B, AMXOR__DB_D, AMXOR_DB_W escape from the check.

From the inc file, it should be

Opc >= LoongArch::AMADD_B && Opc <= LoongArch::AMXOR_DB_W

Then it's a functional change. As I already plan to fix the root cause of the problem once and for all in #114398 I'm not going to temporarily fix it here.

@xen0n xen0n force-pushed the loong-amcas-operand-fix branch from e20d353 to 85dec17 Compare November 1, 2024 13:28
@xen0n
Copy link
Contributor Author

xen0n commented Nov 1, 2024

Turns out the TableGen change actually caused the test to fail... perfect show of how fragile the original implementation was.

I've minimally fixed it and the CI should be green now.

@xen0n xen0n force-pushed the loong-amcas-operand-fix branch 2 times, most recently from 9a54730 to f925724 Compare November 2, 2024 08:37
@xen0n xen0n force-pushed the loong-amcas-operand-fix branch from f925724 to 830b8f5 Compare November 10, 2024 11:37
The `rd` operand of AMCAS instructions is both read and written, because
of the nature of compare-and-swap operations, but currently it is not
declared as such. Fix it for upcoming codegen enablement changes. In
order to do that, a piece of LoongArchAsmParser logic that relied on
TableGen-erated enum variants being ordered in a specific way needs
updating; this will be addressed in a following refactor. No functional
change intended.

While at it, restore vertical alignment for the definition lines.

Suggested-by: tangaac <[email protected]>
Link: llvm#114398 (comment)
@xen0n xen0n force-pushed the loong-amcas-operand-fix branch from 830b8f5 to f0d7771 Compare November 18, 2024 06:07
@SixWeining SixWeining merged commit 75a04c6 into llvm:main Nov 19, 2024
8 checks passed
@xen0n xen0n deleted the loong-amcas-operand-fix branch November 19, 2024 13:04
SixWeining pushed a commit that referenced this pull request Nov 20, 2024
…114398)

Depends on #114508

The LoongArch Reference Manual says that the 3-register atomic memory
operations cannot have their rd equal to either rj or rk [^1], and both
GNU as and LLVM IAS enforce the constraint for non-zero rd. However,
currently LoongArch AsmParser is checking for the opcode with a direct
numerical comparison on the opcode, which is enum-typed: the fact that
all AMO insns have adjacent numerical values is merely a coincidence,
and it is better to not rely on the current TableGen implementation
behavior.

Instead, start to leverage the target-specific flags field of
MCInstrDesc, and record the constraint with TableGen, so we can stop
treating the opcode value as number. In doing so, we also have to mark
whether the instruction is AMCAS, because the operand index of rj and rk
for the AMCAS instructions is different.

While documenting the new flag, it was found that v1.10 of the Manual
did not specify the similar constraint for the AMCAS instructions.
Experiments were done on a Loongson 3A6000 (LA664 uarch) and it turned
out that at least AMCAS will still signal INE with `rd == rj`. The `rd
== rk` case should be a no-op according to the semantics, but as it is
meaningless to perform CAS with the "old value" same as the "new value",
it is not worth special-casing. So the current behavior of also
enforcing the constraint for AMCAS is kept.

[^1]: if `rd == rj` an INE would be signaled; if `rd == rk` it is UB.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants