blob: 2720e9023398676049c632bb9fc5d2d1c6c08b45 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=aarch64 -fast-isel=0 -global-isel=false -verify-machineinstrs < %s | FileCheck %s
; Tests for llvm.write_volatile_register on AArch64.
;
; Unlike llvm.write_register, the volatile variant carries IntrHasSideEffects
; and emits a FAKE_USE of the target physical register after the WRITE_REGISTER.
; The FAKE_USE prevents the CopyToReg from being dead-eliminated while avoiding
; an extra cross-domain read (fmov xN, dM) that would arise if we kept the
; register live via READ_REGISTER + CopyFromReg instead.
;
; For Windows-specific tests with reserved GP register x18 see
; clang/test/CodeGen/arm64-microsoft-intrinsics.c.
; -- Stack pointer -----------------------------------------------------------
; sp is the canonical GP test: it is always accessible regardless of ABI.
define void @write_volatile_sp(i64 %val) {
; CHECK-LABEL: write_volatile_sp:
; CHECK: // %bb.0:
; CHECK-NEXT: mov sp, x0
; CHECK-NEXT: // fake_use: $sp
; CHECK-NEXT: ret
call void @llvm.write_volatile_register.i64(metadata !0, i64 %val)
ret void
}
; -- FP/SIMD d-registers: integer bit-pattern -> FP register -----------------
;
; The caller passes an i64 bit-pattern (e.g. obtained from read_volatile_register).
; Writing it into a SIMD d-register requires a cross-domain integer->FP move
; (fmov dN, xM). The FAKE_USE ensures the CopyToReg is not dead-eliminated
; even though dN has no further GP-domain uses in this function.
define void @write_volatile_d5(i64 %bits) {
; CHECK-LABEL: write_volatile_d5:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov d5, x0
; CHECK-NEXT: // fake_use: $d5
; CHECK-NEXT: ret
call void @llvm.write_volatile_register.i64(metadata !1, i64 %bits)
ret void
}
define void @write_volatile_d31(i64 %bits) {
; CHECK-LABEL: write_volatile_d31:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov d31, x0
; CHECK-NEXT: // fake_use: $d31
; CHECK-NEXT: ret
call void @llvm.write_volatile_register.i64(metadata !2, i64 %bits)
ret void
}
; -- Back-to-back writes must both survive ------------------------------------
;
; Each call carries IntrHasSideEffects so neither may be suppressed on behalf
; of the other. Verify that both fmov + fake_use pairs appear in order.
define void @write_volatile_d5_twice(i64 %a, i64 %b) {
; CHECK-LABEL: write_volatile_d5_twice:
; CHECK: // %bb.0:
; CHECK-NEXT: fmov d5, x0
; CHECK-NEXT: // fake_use: $d5
; CHECK-NEXT: fmov d5, x1
; CHECK-NEXT: // fake_use: $d5
; CHECK-NEXT: ret
call void @llvm.write_volatile_register.i64(metadata !1, i64 %a)
call void @llvm.write_volatile_register.i64(metadata !1, i64 %b)
ret void
}
declare void @llvm.write_volatile_register.i64(metadata, i64)
!0 = !{!"sp"}
!1 = !{!"d5"}
!2 = !{!"d31"}