Skip to content

Commit bd8578c

Browse files
authored
[LoongArch] Prevent R0/R1 allocation for rj operand of [G]CSRXCHG (#140862)
The `[G]CSRXCHG` instruction must not use R0 or R1 as the `rj` operand, as encoding `rj` as 0 or 1 will be interpreted as `[G]CSRRD` OR `[G]CSRWR`, respectively, rather than `[G]CSRXCHG`. This patch introduces a new register class `GPRNoR0R1` and updates the `[G]CSRXCHG` instruction definition to use it for the `rj` operand, ensuring the register allocator avoids assigning R0 or R1. Fixes #140842
1 parent 7a3b5d7 commit bd8578c

File tree

6 files changed

+44
-4
lines changed

6 files changed

+44
-4
lines changed

llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,9 @@ LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
16331633
return Match_Success;
16341634
}
16351635

1636+
if (Kind == MCK_GPRNoR0R1 && (Reg == LoongArch::R0 || Reg == LoongArch::R1))
1637+
return Match_RequiresOpnd2NotR0R1;
1638+
16361639
return Match_InvalidOperand;
16371640
}
16381641

llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
6262
return MCDisassembler::Success;
6363
}
6464

65+
static DecodeStatus
66+
DecodeGPRNoR0R1RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
67+
const MCDisassembler *Decoder) {
68+
if (RegNo <= 1)
69+
return MCDisassembler::Fail;
70+
return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
71+
}
72+
6573
static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
6674
uint64_t Address,
6775
const MCDisassembler *Decoder) {

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,7 +2445,7 @@ let hasSideEffects = 1, Constraints = "$rd = $dst" in {
24452445
def CSRWR : FmtCSR<0x04000020, (outs GPR:$dst),
24462446
(ins GPR:$rd, uimm14:$csr_num), "$rd, $csr_num">;
24472447
def CSRXCHG : FmtCSRXCHG<0x04000000, (outs GPR:$dst),
2448-
(ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
2448+
(ins GPR:$rd, GPRNoR0R1:$rj, uimm14:$csr_num),
24492449
"$rd, $rj, $csr_num">;
24502450
} // hasSideEffects = 1, Constraints = "$rd = $dst"
24512451

@@ -2492,8 +2492,8 @@ def IDLE : MISC_I15<0x06488000>;
24922492
def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>;
24932493
def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14),
24942494
(CSRWR GPR:$rd, uimm14:$imm14)>;
2495-
def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14),
2496-
(CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>;
2495+
def : Pat<(loongarch_csrxchg GPR:$rd, GPRNoR0R1:$rj, uimm14:$imm14),
2496+
(CSRXCHG GPR:$rd, GPRNoR0R1:$rj, uimm14:$imm14)>;
24972497

24982498
def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>;
24992499
def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>;

llvm/lib/Target/LoongArch/LoongArchLVZInstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let Constraints = "$rd = $dst" in {
2323
def GCSRWR : FmtCSR<0x05000020, (outs GPR:$dst),
2424
(ins GPR:$rd, uimm14:$csr_num), "$rd, $csr_num">;
2525
def GCSRXCHG : FmtCSRXCHG<0x05000000, (outs GPR:$dst),
26-
(ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
26+
(ins GPR:$rd, GPRNoR0R1:$rj, uimm14:$csr_num),
2727
"$rd, $rj, $csr_num">;
2828
} // Constraints = "$rd = $dst"
2929

llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ def GPRT : GPRRegisterClass<(add // a0...a7, t0...t8
127127
// prediction.
128128
def GPRJR : GPRRegisterClass<(sub GPR, R1)>;
129129

130+
// Don't use R0 or R1 for the rj operand of [G]CSRXCHG, because when rj is
131+
// encoded as 0 or 1, the instruction is interpreted as [G]CSRRD or [G]CSRWR,
132+
// respectively, rather than [G]CSRXCHG.
133+
def GPRNoR0R1 : GPRRegisterClass<(sub GPR, R0, R1)>;
134+
130135
// Floating point registers
131136

132137
let RegAltNameIndices = [RegAliasName] in {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llc --mtriple=loongarch32 --mattr=+f --verify-machineinstrs < %s | FileCheck %s
2+
; RUN: llc --mtriple=loongarch64 --mattr=+f --verify-machineinstrs < %s | FileCheck %s
3+
4+
declare i32 @llvm.loongarch.csrxchg.w(i32, i32, i32 immarg)
5+
6+
;; Check that the rj operand of csrxchg is not R0.
7+
define void @csrxchg_w_rj_not_r0(i32 signext %a) {
8+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $r0, 0
9+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $zero, 0
10+
entry:
11+
%0 = tail call i32 @llvm.loongarch.csrxchg.w(i32 %a, i32 0, i32 0)
12+
ret void
13+
}
14+
15+
;; Check that the rj operand of csrxchg is not R1.
16+
define i32 @csrxchg_w_rj_not_r1() {
17+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $r1, 0
18+
; CHECK-NOT: csrxchg ${{[a-z]*}}, $ra, 0
19+
entry:
20+
%0 = tail call i32 asm "", "=r,r,i,{r4},{r5},{r6},{r7},{r8},{r9},{r10},{r11},{r12},{r13},{r14},{r15},{r16},{r17},{r18},{r19},{r20},{r23},{r24},{r25},{r26},{r27},{r28},{r29},{r30},{r31},0"(i32 4, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0)
21+
%1 = tail call i32 @llvm.loongarch.csrxchg.w(i32 %0, i32 4, i32 0)
22+
%2 = tail call i32 asm "", "=r,r,i,{r4},{r5},{r6},{r7},{r8},{r9},{r10},{r11},{r12},{r13},{r14},{r15},{r16},{r17},{r18},{r19},{r20},{r23},{r24},{r25},{r26},{r27},{r28},{r29},{r30},{r31},0"(i32 4, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 %1)
23+
ret i32 %2
24+
}

0 commit comments

Comments
 (0)