This only contains the SelectionDAG implementation. GlobalISel to
follow.
The broad approach is:
- Introduce new builtins for 128-bit wide instructions.
- Lower these to @llvm.read_register.i128/@llvm.write_register.i128
- Introduce target-specific ISD nodes which have legal operands (two
i64s rather than an i128). These are named AArch64::{MRRS, MSRR} to
match the instructions they are for. These are a little complex as
they need to match the "shape" of what they're replacing or the
legaliser complains.
- Select these using the existing tryReadRegister/tryWriteRegister to
share the MDString parsing code, and introduce additional code to
ensure these are selected into the right MRRS/MSRR instructions. What
makes this hard is ensuring that the two i64s end up in an XSeqPair
register pair, because SelectionDAG doesn't care that much about
register classes if it can avoid doing so.
The main change to existing code is the reorganisation of
tryReadRegister and tryWriteRegister to try to keep the string parsing
code separate from the instruction creating code.
This also includes the changes to clang to define and use the ACLE
feature macro named `__ARM_FEATURE_SYSREG128`.
Contributors:
Sam Elliott
Lucas Prates
Differential Revision: https://reviews.llvm.org/D139086
49 lines
1.5 KiB
LLVM
49 lines
1.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple aarch64 -mattr=+d128 | FileCheck %s --check-prefixes=CHECK-LE
|
|
; RUN: llc < %s -mtriple aarch64_be -mattr=+d128 | FileCheck %s --check-prefixes=CHECK-BE
|
|
|
|
define i128 @test_rsr128() #0 {
|
|
; CHECK-LE-LABEL: test_rsr128:
|
|
; CHECK-LE: // %bb.0: // %entry
|
|
; CHECK-LE-NEXT: mrrs x0, x1, S1_2_C3_C4_5
|
|
; CHECK-LE-NEXT: ret
|
|
;
|
|
; CHECK-BE-LABEL: test_rsr128:
|
|
; CHECK-BE: // %bb.0: // %entry
|
|
; CHECK-BE-NEXT: mrrs x2, x3, S1_2_C3_C4_5
|
|
; CHECK-BE-NEXT: mov x0, x3
|
|
; CHECK-BE-NEXT: mov x1, x2
|
|
; CHECK-BE-NEXT: ret
|
|
entry:
|
|
%0 = call i128 @llvm.read_volatile_register.i128(metadata !1)
|
|
ret i128 %0
|
|
}
|
|
|
|
declare i128 @llvm.read_volatile_register.i128(metadata) #1
|
|
|
|
define void @test_wsr128(i128 noundef %v) #0 {
|
|
; CHECK-LE-LABEL: test_wsr128:
|
|
; CHECK-LE: // %bb.0: // %entry
|
|
; CHECK-LE-NEXT: // kill: def $x1 killed $x1 killed $x0_x1 def $x0_x1
|
|
; CHECK-LE-NEXT: // kill: def $x0 killed $x0 killed $x0_x1 def $x0_x1
|
|
; CHECK-LE-NEXT: msrr S1_2_C3_C4_5, x0, x1
|
|
; CHECK-LE-NEXT: ret
|
|
;
|
|
; CHECK-BE-LABEL: test_wsr128:
|
|
; CHECK-BE: // %bb.0: // %entry
|
|
; CHECK-BE-NEXT: mov x2, x1
|
|
; CHECK-BE-NEXT: mov x3, x0
|
|
; CHECK-BE-NEXT: msrr S1_2_C3_C4_5, x2, x3
|
|
; CHECK-BE-NEXT: ret
|
|
entry:
|
|
call void @llvm.write_register.i128(metadata !1, i128 %v)
|
|
ret void
|
|
}
|
|
|
|
declare void @llvm.write_register.i128(metadata, i128) #1
|
|
|
|
attributes #0 = { noinline nounwind }
|
|
attributes #1 = { nounwind }
|
|
|
|
!1 = !{!"1:2:3:4:5"}
|