Skip to content

Commit 02bc62c

Browse files
committed
[LoongArch] Prevent R0/R1 allocation for rj operand of {G}CSRXCHG
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 llvm#140842
1 parent 746c682 commit 02bc62c

File tree

7 files changed

+45
-8
lines changed

7 files changed

+45
-8
lines changed

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
@@ -2431,7 +2431,7 @@ let hasSideEffects = 1, Constraints = "$rd = $dst" in {
24312431
def CSRWR : FmtCSR<0x04000020, (outs GPR:$dst),
24322432
(ins GPR:$rd, uimm14:$csr_num), "$rd, $csr_num">;
24332433
def CSRXCHG : FmtCSRXCHG<0x04000000, (outs GPR:$dst),
2434-
(ins GPR:$rd, GPR:$rj, uimm14:$csr_num),
2434+
(ins GPR:$rd, GPRNoR0R1:$rj, uimm14:$csr_num),
24352435
"$rd, $rj, $csr_num">;
24362436
} // hasSideEffects = 1, Constraints = "$rd = $dst"
24372437

@@ -2478,8 +2478,8 @@ def IDLE : MISC_I15<0x06488000>;
24782478
def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>;
24792479
def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14),
24802480
(CSRWR GPR:$rd, uimm14:$imm14)>;
2481-
def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14),
2482-
(CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>;
2481+
def : Pat<(loongarch_csrxchg GPR:$rd, GPRNoR0R1:$rj, uimm14:$imm14),
2482+
(CSRXCHG GPR:$rd, GPRNoR0R1:$rj, uimm14:$imm14)>;
24832483

24842484
def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>;
24852485
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+
}

llvm/test/MC/LoongArch/Basic/Privilege/invalid.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
## csrxchg: rj != 0,1
55
csrxchg $a0, $zero, 0
6-
# ERR: :[[#@LINE-1]]:15: error: must not be $r0 or $r1
6+
# ERR: :[[#@LINE-1]]:15: error: invalid operand for instruction
77
csrxchg $a0, $ra, 0
8-
# ERR: :[[#@LINE-1]]:15: error: must not be $r0 or $r1
8+
# ERR: :[[#@LINE-1]]:15: error: invalid operand for instruction
99

1010
## LoongArch64 mnemonics
1111
iocsrrd.d $a0, $a1

llvm/test/MC/LoongArch/lvz/lvz-err.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ gcsrxchg $a0, $a1, -1
1919
# CHECK: :[[#@LINE-1]]:20: error: immediate must be an integer in the range [0, 16383]
2020

2121
gcsrxchg $a0, $ra, 1
22-
# CHECK: :[[#@LINE-1]]:16: error: must not be $r0 or $r1
22+
# CHECK: :[[#@LINE-1]]:16: error: invalid operand for instruction
2323

2424
gcsrxchg $a0, $zero, 1
25-
# CHECK: :[[#@LINE-1]]:16: error: must not be $r0 or $r1
25+
# CHECK: :[[#@LINE-1]]:16: error: invalid operand for instruction
2626

2727
hvcl 32768
2828
# CHECK: :[[#@LINE-1]]:6: error: immediate must be an integer in the range [0, 32767]

0 commit comments

Comments
 (0)