
This prevents it CSEing multiple nodes together from "volatile" registers as they would end up with the same chain. The new chain out should be the chain from the new READ_REGISTER node. Fixes #144845
125 lines
3.4 KiB
LLVM
125 lines
3.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: llc < %s -mtriple=arm-none-eabi -mcpu=cortex-a8 2>&1 | FileCheck %s --check-prefix=ARM --check-prefix=ACORE
|
|
; RUN: llc < %s -mtriple=thumb-none-eabi -mcpu=cortex-m4 2>&1 | FileCheck %s --check-prefix=ARM --check-prefix=MCORE
|
|
|
|
define i32 @read_i32_encoded_register() nounwind {
|
|
; ARM-LABEL: read_i32_encoded_register:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: mrc p1, #2, r0, c3, c4, #5
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
%reg = call i32 @llvm.read_register.i32(metadata !0)
|
|
ret i32 %reg
|
|
}
|
|
|
|
define i64 @read_i64_encoded_register() nounwind {
|
|
; ARM-LABEL: read_i64_encoded_register:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: mrrc p1, #2, r0, r1, c3
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
%reg = call i64 @llvm.read_register.i64(metadata !1)
|
|
ret i64 %reg
|
|
}
|
|
|
|
define i64 @read_volatile_i64_twice() {
|
|
; ACORE-LABEL: read_volatile_i64_twice:
|
|
; ACORE: @ %bb.0: @ %entry
|
|
; ACORE-NEXT: mrrc p15, #1, r0, r1, c14
|
|
; ACORE-NEXT: mrrc p15, #1, r2, r3, c14
|
|
; ACORE-NEXT: eor r0, r2, r0
|
|
; ACORE-NEXT: eor r1, r3, r1
|
|
; ACORE-NEXT: bx lr
|
|
;
|
|
; MCORE-LABEL: read_volatile_i64_twice:
|
|
; MCORE: @ %bb.0: @ %entry
|
|
; MCORE-NEXT: mrrc p15, #1, r0, r1, c14
|
|
; MCORE-NEXT: mrrc p15, #1, r2, r3, c14
|
|
; MCORE-NEXT: eors r0, r2
|
|
; MCORE-NEXT: eors r1, r3
|
|
; MCORE-NEXT: bx lr
|
|
entry:
|
|
%0 = tail call i64 @llvm.read_volatile_register.i64(metadata !5)
|
|
%1 = tail call i64 @llvm.read_volatile_register.i64(metadata !5)
|
|
%xor = xor i64 %1, %0
|
|
ret i64 %xor
|
|
}
|
|
|
|
|
|
define i32 @read_apsr() nounwind {
|
|
; ARM-LABEL: read_apsr:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: mrs r0, apsr
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
%reg = call i32 @llvm.read_register.i32(metadata !2)
|
|
ret i32 %reg
|
|
}
|
|
|
|
define i32 @read_fpscr() nounwind {
|
|
; ARM-LABEL: read_fpscr:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: vmrs r0, fpscr
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
%reg = call i32 @llvm.read_register.i32(metadata !3)
|
|
ret i32 %reg
|
|
}
|
|
|
|
define void @write_i32_encoded_register(i32 %x) nounwind {
|
|
; ARM-LABEL: write_i32_encoded_register:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: mcr p1, #2, r0, c3, c4, #5
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
call void @llvm.write_register.i32(metadata !0, i32 %x)
|
|
ret void
|
|
}
|
|
|
|
define void @write_i64_encoded_register(i64 %x) nounwind {
|
|
; ARM-LABEL: write_i64_encoded_register:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: mcrr p1, #2, r0, r1, c3
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
call void @llvm.write_register.i64(metadata !1, i64 %x)
|
|
ret void
|
|
}
|
|
|
|
define void @write_apsr(i32 %x) nounwind {
|
|
; ACORE-LABEL: write_apsr:
|
|
; ACORE: @ %bb.0: @ %entry
|
|
; ACORE-NEXT: msr APSR_nzcvq, r0
|
|
; ACORE-NEXT: bx lr
|
|
;
|
|
; MCORE-LABEL: write_apsr:
|
|
; MCORE: @ %bb.0: @ %entry
|
|
; MCORE-NEXT: msr apsr_nzcvq, r0
|
|
; MCORE-NEXT: bx lr
|
|
entry:
|
|
call void @llvm.write_register.i32(metadata !4, i32 %x)
|
|
ret void
|
|
}
|
|
|
|
define void @write_fpscr(i32 %x) nounwind {
|
|
; ARM-LABEL: write_fpscr:
|
|
; ARM: @ %bb.0: @ %entry
|
|
; ARM-NEXT: vmsr fpscr, r0
|
|
; ARM-NEXT: bx lr
|
|
entry:
|
|
call void @llvm.write_register.i32(metadata !3, i32 %x)
|
|
ret void
|
|
}
|
|
|
|
declare i32 @llvm.read_register.i32(metadata) nounwind
|
|
declare i64 @llvm.read_register.i64(metadata) nounwind
|
|
declare void @llvm.write_register.i32(metadata, i32) nounwind
|
|
declare void @llvm.write_register.i64(metadata, i64) nounwind
|
|
|
|
!0 = !{!"cp1:2:c3:c4:5"}
|
|
!1 = !{!"cp1:2:c3"}
|
|
!2 = !{!"apsr"}
|
|
!3 = !{!"fpscr"}
|
|
!4 = !{!"apsr_nzcvq"}
|
|
!5 = !{!"cp15:1:c14"}
|