Skip to content

Commit

Permalink
[LoongArch] Add back SDNPSideEffect properties to CSR and IOCSR read ops
Browse files Browse the repository at this point in the history
In general, CSR and IOCSR reads should be treated as volatile because:

* there may well be intervening writes between seemingly common
  expressions;
* the stateful entity behind a given (IO)CSR may well be volatile.

Confirmed to fix broken Clang Linux/LoongArch builds (dying when a
userspace process tries to use FPU, panicking when that process happens
to be PID 1) with this patch.

Fixes: #63549
Fixes: 2efdacf ("[LoongArch] Add missing chains and remove unnecessary `SDNPSideEffect` property for some intrinsic nodes")

Reviewed By: SixWeining, hev

Differential Revision: https://reviews.llvm.org/D153865
  • Loading branch information
xen0n authored and SixWeining committed Jun 28, 2023
1 parent 1e31cdf commit c88f27f
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 5 deletions.
10 changes: 5 additions & 5 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -114,20 +114,20 @@ def loongarch_movgr2fcsr : SDNode<"LoongArchISD::MOVGR2FCSR",
def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI,
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_csrrd : SDNode<"LoongArchISD::CSRRD", SDT_LoongArchCsrrd,
[SDNPHasChain]>;
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr,
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG",
SDT_LoongArchCsrxchg,
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp,
[SDNPHasChain]>;
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp,
[SDNPHasChain]>;
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp,
[SDNPHasChain]>;
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp,
[SDNPHasChain]>;
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B",
SDT_LoongArchIocsrwr,
[SDNPHasChain, SDNPSideEffect]>;
Expand Down
47 changes: 47 additions & 0 deletions llvm/test/CodeGen/LoongArch/intrinsic-csr-side-effects.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s
; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s

declare i32 @llvm.loongarch.csrrd.w(i32 immarg) nounwind
declare i32 @llvm.loongarch.csrwr.w(i32, i32 immarg) nounwind
declare void @bug()

define dso_local void @foo(i32 noundef signext %flag) nounwind {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: beqz $a0, .LBB0_2
; CHECK-NEXT: # %bb.1: # %if.then
; CHECK-NEXT: csrrd $a0, 2
; CHECK-NEXT: ori $a0, $a0, 1
; CHECK-NEXT: csrwr $a0, 2
; CHECK-NEXT: .LBB0_2: # %if.end
; CHECK-NEXT: csrrd $a0, 2
; CHECK-NEXT: andi $a0, $a0, 1
; CHECK-NEXT: bnez $a0, .LBB0_4
; CHECK-NEXT: # %bb.3: # %if.then2
; CHECK-NEXT: b %plt(bug)
; CHECK-NEXT: .LBB0_4: # %if.end3
; CHECK-NEXT: ret
entry:
%tobool.not = icmp eq i32 %flag, 0
br i1 %tobool.not, label %if.end, label %if.then

if.then: ; preds = %entry
%0 = tail call i32 @llvm.loongarch.csrrd.w(i32 2)
%or = or i32 %0, 1
%1 = tail call i32 @llvm.loongarch.csrwr.w(i32 %or, i32 2)
br label %if.end

if.end: ; preds = %if.then, %entry
%2 = tail call i32 @llvm.loongarch.csrrd.w(i32 2)
%and = and i32 %2, 1
%tobool1.not = icmp eq i32 %and, 0
br i1 %tobool1.not, label %if.then2, label %if.end3

if.then2: ; preds = %if.end
tail call void @bug()
br label %if.end3

if.end3: ; preds = %if.then2, %if.end
ret void
}
180 changes: 180 additions & 0 deletions llvm/test/CodeGen/LoongArch/intrinsic-iocsr-side-effects.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s

declare i32 @llvm.loongarch.iocsrrd.b(i32) nounwind
declare void @llvm.loongarch.iocsrwr.b(i32, i32) nounwind
declare i32 @llvm.loongarch.iocsrrd.h(i32) nounwind
declare void @llvm.loongarch.iocsrwr.h(i32, i32) nounwind
declare i32 @llvm.loongarch.iocsrrd.w(i32) nounwind
declare void @llvm.loongarch.iocsrwr.w(i32, i32) nounwind
declare i64 @llvm.loongarch.iocsrrd.d(i32) nounwind
declare void @llvm.loongarch.iocsrwr.d(i64, i32) nounwind
declare void @bug()

define dso_local void @test_b(i32 noundef signext %flag) nounwind {
; CHECK-LABEL: test_b:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: beqz $a0, .LBB0_2
; CHECK-NEXT: # %bb.1: # %if.then
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.b $a1, $a0
; CHECK-NEXT: ori $a1, $a1, 1
; CHECK-NEXT: iocsrwr.b $a1, $a0
; CHECK-NEXT: .LBB0_2: # %if.end
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.b $a0, $a0
; CHECK-NEXT: andi $a0, $a0, 1
; CHECK-NEXT: bnez $a0, .LBB0_4
; CHECK-NEXT: # %bb.3: # %if.then2
; CHECK-NEXT: b %plt(bug)
; CHECK-NEXT: .LBB0_4: # %if.end3
; CHECK-NEXT: ret
entry:
%tobool.not = icmp eq i32 %flag, 0
br i1 %tobool.not, label %if.end, label %if.then

if.then: ; preds = %entry
%0 = tail call i32 @llvm.loongarch.iocsrrd.b(i32 2)
%or = or i32 %0, 1
tail call void @llvm.loongarch.iocsrwr.b(i32 %or, i32 2)
br label %if.end

if.end: ; preds = %if.then, %entry
%1 = tail call i32 @llvm.loongarch.iocsrrd.b(i32 2)
%and = and i32 %1, 1
%tobool1.not = icmp eq i32 %and, 0
br i1 %tobool1.not, label %if.then2, label %if.end3

if.then2: ; preds = %if.end
tail call void @bug()
br label %if.end3

if.end3: ; preds = %if.then2, %if.end
ret void
}

define dso_local void @test_h(i32 noundef signext %flag) nounwind {
; CHECK-LABEL: test_h:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: beqz $a0, .LBB1_2
; CHECK-NEXT: # %bb.1: # %if.then
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.h $a1, $a0
; CHECK-NEXT: ori $a1, $a1, 1
; CHECK-NEXT: iocsrwr.h $a1, $a0
; CHECK-NEXT: .LBB1_2: # %if.end
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.h $a0, $a0
; CHECK-NEXT: andi $a0, $a0, 1
; CHECK-NEXT: bnez $a0, .LBB1_4
; CHECK-NEXT: # %bb.3: # %if.then2
; CHECK-NEXT: b %plt(bug)
; CHECK-NEXT: .LBB1_4: # %if.end3
; CHECK-NEXT: ret
entry:
%tobool.not = icmp eq i32 %flag, 0
br i1 %tobool.not, label %if.end, label %if.then

if.then: ; preds = %entry
%0 = tail call i32 @llvm.loongarch.iocsrrd.h(i32 2)
%or = or i32 %0, 1
tail call void @llvm.loongarch.iocsrwr.h(i32 %or, i32 2)
br label %if.end

if.end: ; preds = %if.then, %entry
%1 = tail call i32 @llvm.loongarch.iocsrrd.h(i32 2)
%and = and i32 %1, 1
%tobool1.not = icmp eq i32 %and, 0
br i1 %tobool1.not, label %if.then2, label %if.end3

if.then2: ; preds = %if.end
tail call void @bug()
br label %if.end3

if.end3: ; preds = %if.then2, %if.end
ret void
}

define dso_local void @test_w(i32 noundef signext %flag) nounwind {
; CHECK-LABEL: test_w:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: beqz $a0, .LBB2_2
; CHECK-NEXT: # %bb.1: # %if.then
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.w $a1, $a0
; CHECK-NEXT: ori $a1, $a1, 1
; CHECK-NEXT: iocsrwr.w $a1, $a0
; CHECK-NEXT: .LBB2_2: # %if.end
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.w $a0, $a0
; CHECK-NEXT: andi $a0, $a0, 1
; CHECK-NEXT: bnez $a0, .LBB2_4
; CHECK-NEXT: # %bb.3: # %if.then2
; CHECK-NEXT: b %plt(bug)
; CHECK-NEXT: .LBB2_4: # %if.end3
; CHECK-NEXT: ret
entry:
%tobool.not = icmp eq i32 %flag, 0
br i1 %tobool.not, label %if.end, label %if.then

if.then: ; preds = %entry
%0 = tail call i32 @llvm.loongarch.iocsrrd.w(i32 2)
%or = or i32 %0, 1
tail call void @llvm.loongarch.iocsrwr.w(i32 %or, i32 2)
br label %if.end

if.end: ; preds = %if.then, %entry
%1 = tail call i32 @llvm.loongarch.iocsrrd.w(i32 2)
%and = and i32 %1, 1
%tobool1.not = icmp eq i32 %and, 0
br i1 %tobool1.not, label %if.then2, label %if.end3

if.then2: ; preds = %if.end
tail call void @bug()
br label %if.end3

if.end3: ; preds = %if.then2, %if.end
ret void
}

define dso_local void @test_d(i32 noundef signext %flag) nounwind {
; CHECK-LABEL: test_d:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: beqz $a0, .LBB3_2
; CHECK-NEXT: # %bb.1: # %if.then
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.d $a1, $a0
; CHECK-NEXT: ori $a1, $a1, 1
; CHECK-NEXT: iocsrwr.d $a1, $a0
; CHECK-NEXT: .LBB3_2: # %if.end
; CHECK-NEXT: ori $a0, $zero, 2
; CHECK-NEXT: iocsrrd.d $a0, $a0
; CHECK-NEXT: andi $a0, $a0, 1
; CHECK-NEXT: bnez $a0, .LBB3_4
; CHECK-NEXT: # %bb.3: # %if.then2
; CHECK-NEXT: b %plt(bug)
; CHECK-NEXT: .LBB3_4: # %if.end3
; CHECK-NEXT: ret
entry:
%tobool.not = icmp eq i32 %flag, 0
br i1 %tobool.not, label %if.end, label %if.then

if.then: ; preds = %entry
%0 = tail call i64 @llvm.loongarch.iocsrrd.d(i32 2)
%or = or i64 %0, 1
tail call void @llvm.loongarch.iocsrwr.d(i64 %or, i32 2)
br label %if.end

if.end: ; preds = %if.then, %entry
%1 = tail call i64 @llvm.loongarch.iocsrrd.d(i32 2)
%and = and i64 %1, 1
%tobool1.not = icmp eq i64 %and, 0
br i1 %tobool1.not, label %if.then2, label %if.end3

if.then2: ; preds = %if.end
tail call void @bug()
br label %if.end3

if.end3: ; preds = %if.then2, %if.end
ret void
}
2 changes: 2 additions & 0 deletions llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ entry:
define void @csrrd_d_noret() {
; CHECK-LABEL: csrrd_d_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrrd $a0, 1
; CHECK-NEXT: ret
entry:
%0 = tail call i64 @llvm.loongarch.csrrd.d(i32 1)
Expand Down Expand Up @@ -239,6 +240,7 @@ entry:
define void @iocsrrd_d_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_d_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.d $a0, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i64 @llvm.loongarch.iocsrrd.d(i32 %a)
Expand Down
4 changes: 4 additions & 0 deletions llvm/test/CodeGen/LoongArch/intrinsic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ entry:
define void @csrrd_w_noret() {
; CHECK-LABEL: csrrd_w_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: csrrd $a0, 1
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.csrrd.w(i32 1)
Expand Down Expand Up @@ -184,6 +185,7 @@ entry:
define void @iocsrrd_b_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_b_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.b $a0, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.iocsrrd.b(i32 %a)
Expand All @@ -193,6 +195,7 @@ entry:
define void @iocsrrd_h_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_h_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.h $a0, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.iocsrrd.h(i32 %a)
Expand All @@ -202,6 +205,7 @@ entry:
define void @iocsrrd_w_noret(i32 %a) {
; CHECK-LABEL: iocsrrd_w_noret:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: iocsrrd.w $a0, $a0
; CHECK-NEXT: ret
entry:
%0 = tail call i32 @llvm.loongarch.iocsrrd.w(i32 %a)
Expand Down

0 comments on commit c88f27f

Please sign in to comment.