CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
1379 lines
50 KiB
YAML
1379 lines
50 KiB
YAML
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
|
|
# RUN: llc -mtriple=riscv32 -mattr=+zilsd -run-pass riscv-prera-zilsd-opt %s -o - | FileCheck %s
|
|
# RUN: llc -mtriple=riscv32 -mattr=+zilsd,+zilsd-4byte-align -run-pass riscv-prera-zilsd-opt %s -o - | FileCheck %s --check-prefix=CHECK-4BYTE
|
|
--- |
|
|
declare void @external_func()
|
|
|
|
define i32 @basic_load_combine(ptr %0) {
|
|
%2 = load i32, ptr %0, align 4
|
|
%3 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%4 = load i32, ptr %3, align 4
|
|
%5 = add i32 %2, %4
|
|
ret i32 %5
|
|
}
|
|
|
|
define void @basic_store_combine(ptr %0, i32 %1, i32 %2) {
|
|
store i32 %1, ptr %0, align 4
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 1
|
|
store i32 %2, ptr %4, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @basic_store_zero_combine(ptr %0, i32 %1, i32 %2) {
|
|
store i32 0, ptr %0, align 4
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 1
|
|
store i32 0, ptr %4, align 4
|
|
ret void
|
|
}
|
|
|
|
define i32 @basic_load_combine_8_byte_aligned(ptr %0) {
|
|
%2 = load i32, ptr %0, align 8
|
|
%3 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%4 = load i32, ptr %3, align 4
|
|
%5 = add i32 %2, %4
|
|
ret i32 %5
|
|
}
|
|
|
|
define void @basic_store_combine_8_byte_aligned(ptr %0, i32 %1, i32 %2) {
|
|
store i32 %1, ptr %0, align 8
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 1
|
|
store i32 %2, ptr %4, align 4
|
|
ret void
|
|
}
|
|
|
|
|
|
define i32 @non_consecutive_offsets(ptr %0) {
|
|
%2 = load i32, ptr %0, align 4
|
|
%3 = getelementptr inbounds i32, ptr %0, i32 2
|
|
%4 = load i32, ptr %3, align 4
|
|
%5 = add i32 %2, %4
|
|
ret i32 %5
|
|
}
|
|
|
|
define i32 @different_base_regs(ptr %0, ptr %1) {
|
|
%3 = load i32, ptr %0, align 4
|
|
%4 = getelementptr inbounds i32, ptr %1, i32 1
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = add i32 %3, %5
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @call_blocks_optimization(ptr %0) {
|
|
%2 = load i32, ptr %0, align 4
|
|
call void @external_func()
|
|
%3 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%4 = load i32, ptr %3, align 4
|
|
%5 = add i32 %2, %4
|
|
ret i32 %5
|
|
}
|
|
|
|
define i32 @terminator_blocks_optimization(ptr %0, i32 %1) {
|
|
%3 = load i32, ptr %0, align 4
|
|
%4 = icmp eq i32 %1, %3
|
|
br i1 %4, label %5, label %5
|
|
5:
|
|
%6 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%7 = load i32, ptr %6, align 4
|
|
%8 = add i32 %3, %7
|
|
ret i32 %8
|
|
}
|
|
|
|
define i32 @memory_aliasing(ptr %0, i32 %1) {
|
|
%3 = load i32, ptr %0, align 4
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 2
|
|
store i32 %1, ptr %4, align 4
|
|
%5 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%6 = load i32, ptr %5, align 4
|
|
%7 = add i32 %3, %6
|
|
ret i32 %7
|
|
}
|
|
|
|
define i32 @multiple_pairs(ptr %0, ptr %1) {
|
|
%3 = load i32, ptr %0, align 4
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = add i32 %3, %5
|
|
%7 = getelementptr inbounds i32, ptr %1, i32 2
|
|
%8 = load i32, ptr %7, align 4
|
|
%9 = getelementptr inbounds i32, ptr %1, i32 3
|
|
%10 = load i32, ptr %9, align 4
|
|
%11 = add i32 %8, %10
|
|
%12 = add i32 %6, %11
|
|
ret i32 %12
|
|
}
|
|
|
|
define i32 @many_loads(ptr %0) {
|
|
%2 = getelementptr inbounds i32, ptr %0, i32 4
|
|
%3 = load i32, ptr %2, align 4
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 5
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = getelementptr inbounds i32, ptr %0, i32 6
|
|
%7 = load i32, ptr %6, align 4
|
|
%8 = getelementptr inbounds i32, ptr %0, i32 7
|
|
%9 = load i32, ptr %8, align 4
|
|
%10 = getelementptr inbounds i32, ptr %0, i32 8
|
|
%11 = load i32, ptr %10, align 4
|
|
%12 = getelementptr inbounds i32, ptr %0, i32 9
|
|
%13 = load i32, ptr %12, align 4
|
|
%14 = getelementptr inbounds i32, ptr %0, i32 10
|
|
%15 = load i32, ptr %14, align 4
|
|
%16 = getelementptr inbounds i32, ptr %0, i32 11
|
|
%17 = load i32, ptr %16, align 4
|
|
%18 = getelementptr inbounds i32, ptr %0, i32 12
|
|
%19 = load i32, ptr %18, align 4
|
|
%20 = getelementptr inbounds i32, ptr %0, i32 13
|
|
%21 = load i32, ptr %20, align 4
|
|
%22 = getelementptr inbounds i32, ptr %0, i32 14
|
|
%23 = load i32, ptr %22, align 4
|
|
%24 = getelementptr inbounds i32, ptr %0, i32 15
|
|
%25 = load i32, ptr %24, align 4
|
|
%26 = load i32, ptr %0, align 4
|
|
%27 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%28 = load i32, ptr %27, align 4
|
|
%29 = add i32 %3, %5
|
|
%30 = add i32 %7, %9
|
|
%31 = add i32 %11, %13
|
|
%32 = add i32 %15, %17
|
|
%33 = add i32 %19, %21
|
|
%34 = add i32 %23, %25
|
|
%35 = add i32 %26, %28
|
|
%36 = add i32 %29, %30
|
|
%37 = add i32 %31, %32
|
|
%38 = add i32 %33, %34
|
|
%39 = add i32 %35, %36
|
|
%40 = add i32 %37, %38
|
|
%41 = add i32 %39, %40
|
|
ret i32 %41
|
|
}
|
|
|
|
define i32 @reverse_order_loads(ptr %0) {
|
|
%2 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%3 = load i32, ptr %2, align 4
|
|
%4 = load i32, ptr %0, align 4
|
|
%5 = add i32 %3, %4
|
|
ret i32 %5
|
|
}
|
|
|
|
define i32 @offset_calculation(ptr %0) {
|
|
%2 = getelementptr inbounds i8, ptr %0, i32 100
|
|
%3 = load i32, ptr %2, align 4
|
|
%4 = getelementptr inbounds i8, ptr %0, i32 104
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = add i32 %3, %5
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @large_offsets(ptr %0) {
|
|
%2 = getelementptr inbounds i8, ptr %0, i32 2040
|
|
%3 = load i32, ptr %2, align 4
|
|
%4 = getelementptr inbounds i8, ptr %0, i32 2044
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = add i32 %3, %5
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @negative_offsets(ptr %0) {
|
|
%2 = getelementptr inbounds i8, ptr %0, i32 -8
|
|
%3 = load i32, ptr %2, align 4
|
|
%4 = getelementptr inbounds i8, ptr %0, i32 -4
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = add i32 %3, %5
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @volatile_loads(ptr %0) {
|
|
%2 = load volatile i32, ptr %0, align 4
|
|
%3 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%4 = load volatile i32, ptr %3, align 4
|
|
%5 = add i32 %2, %4
|
|
ret i32 %5
|
|
}
|
|
|
|
define i32 @store_dependency(ptr %0, i32 %1) {
|
|
%3 = load i32, ptr %0, align 4
|
|
%4 = getelementptr inbounds i32, ptr %0, i32 1
|
|
store i32 %1, ptr %4, align 4
|
|
%5 = load i32, ptr %4, align 4
|
|
%6 = add i32 %3, %5
|
|
ret i32 %6
|
|
}
|
|
|
|
define i32 @three_loads(ptr %0) {
|
|
%2 = load i32, ptr %0, align 4
|
|
%3 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%4 = load i32, ptr %3, align 4
|
|
%5 = getelementptr inbounds i32, ptr %0, i32 2
|
|
%6 = load i32, ptr %5, align 4
|
|
%7 = add i32 %2, %4
|
|
%8 = add i32 %7, %6
|
|
ret i32 %8
|
|
}
|
|
|
|
define i32 @distance_exceeds_max(ptr %0, i32 %1) {
|
|
%3 = load i32, ptr %0, align 4
|
|
%4 = add i32 %3, %1
|
|
%5 = add i32 %4, %1
|
|
%6 = add i32 %5, %1
|
|
%7 = add i32 %6, %1
|
|
%8 = add i32 %7, %1
|
|
%9 = add i32 %8, %1
|
|
%10 = add i32 %9, %1
|
|
%11 = add i32 %10, %1
|
|
%12 = add i32 %11, %1
|
|
%13 = add i32 %12, %1
|
|
%14 = add i32 %13, %1
|
|
%15 = getelementptr inbounds i32, ptr %0, i32 1
|
|
%16 = load i32, ptr %15, align 4
|
|
%17 = add i32 %14, %16
|
|
ret i32 %17
|
|
}
|
|
|
|
@global_var = external global [100 x i32]
|
|
|
|
define i32 @symbolic_operands_global() {
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @symbolic_operands_different_globals() {
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @symbolic_operands_constantpool() {
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @symbolic_operands_interleave() {
|
|
ret i32 0
|
|
}
|
|
|
|
declare void @external(ptr)
|
|
define i32 @frame_index() {
|
|
%arr = alloca [2 x i32], align 4
|
|
%arrayidx1 = getelementptr inbounds nuw i8, ptr %arr, i32 4
|
|
ret i32 0
|
|
}
|
|
|
|
define i32 @frame_index_operands_interleave() {
|
|
%arr = alloca [2 x i32], align 4
|
|
%arrayidx1 = getelementptr inbounds nuw i8, ptr %arr, i32 4
|
|
ret i32 0
|
|
}
|
|
---
|
|
# Basic case: two consecutive 32-bit loads that can be combined into LD
|
|
name: basic_load_combine
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: basic_load_combine
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: basic_load_combine
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = LW %0, 0 :: (load (s32))
|
|
%2:gpr = LW %0, 4 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Basic case: two consecutive 32-bit stores that can be combined into SD
|
|
name: basic_store_combine
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
- { reg: '$x12', virtual-reg: '%2' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11, $x12
|
|
|
|
; CHECK-LABEL: name: basic_store_combine
|
|
; CHECK: liveins: $x10, $x11, $x12
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
|
|
; CHECK-NEXT: SW [[COPY1]], [[COPY]], 0 :: (store (s32))
|
|
; CHECK-NEXT: SW [[COPY2]], [[COPY]], 4 :: (store (s32))
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: basic_store_combine
|
|
; CHECK-4BYTE: liveins: $x10, $x11, $x12
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
|
|
; CHECK-4BYTE-NEXT: PseudoSD_RV32_OPT [[COPY1]], [[COPY2]], [[COPY]], 0 :: (store (s32))
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = COPY $x12
|
|
SW %1, %0, 0 :: (store (s32))
|
|
SW %2, %0, 4 :: (store (s32))
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Basic case: two consecutive 32-bit store 0 that can be combined into SD
|
|
name: basic_store_zero_combine
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: basic_store_zero_combine
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
|
|
; CHECK-NEXT: SW [[COPY1]], [[COPY]], 0 :: (store (s32))
|
|
; CHECK-NEXT: SW [[COPY1]], [[COPY]], 4 :: (store (s32))
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: basic_store_zero_combine
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
|
|
; CHECK-4BYTE-NEXT: PseudoSD_RV32_OPT [[COPY1]], [[COPY1]], [[COPY]], 0 :: (store (s32))
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x0
|
|
SW %1, %0, 0 :: (store (s32))
|
|
SW %1, %0, 4 :: (store (s32))
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
name: basic_load_combine_8_byte_aligned
|
|
alignment: 8
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: basic_load_combine_8_byte_aligned
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32), align 8), (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: basic_load_combine_8_byte_aligned
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32), align 8), (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = LW %0, 0 :: (load (s32), align 8)
|
|
%2:gpr = LW %0, 4 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Basic case: two consecutive 32-bit stores that can be combined into SD
|
|
name: basic_store_combine_8_byte_aligned
|
|
alignment: 8
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
- { reg: '$x12', virtual-reg: '%2' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11, $x12
|
|
|
|
; CHECK-LABEL: name: basic_store_combine_8_byte_aligned
|
|
; CHECK: liveins: $x10, $x11, $x12
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
|
|
; CHECK-NEXT: PseudoSD_RV32_OPT [[COPY1]], [[COPY2]], [[COPY]], 0 :: (store (s32), align 8), (store (s32))
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: basic_store_combine_8_byte_aligned
|
|
; CHECK-4BYTE: liveins: $x10, $x11, $x12
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
|
|
; CHECK-4BYTE-NEXT: PseudoSD_RV32_OPT [[COPY1]], [[COPY2]], [[COPY]], 0 :: (store (s32), align 8), (store (s32))
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = COPY $x12
|
|
SW %1, %0, 0 :: (store (s32), align 8)
|
|
SW %2, %0, 4 :: (store (s32))
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Non-consecutive offsets - should not combine
|
|
name: non_consecutive_offsets
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: non_consecutive_offsets
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 8 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: non_consecutive_offsets
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 8 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Should not combine - offset gap is 8, not 4
|
|
%1:gpr = LW %0, 0 :: (load (s32))
|
|
%2:gpr = LW %0, 8 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Different base registers - should not combine
|
|
name: different_base_regs
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: different_base_regs
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY1]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: different_base_regs
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY1]], 4 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
; Should not combine - different base registers
|
|
%2:gpr = LW %0, 0 :: (load (s32))
|
|
%3:gpr = LW %1, 4 :: (load (s32))
|
|
%4:gpr = ADD %2, %3
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Call instruction blocks optimization
|
|
name: call_blocks_optimization
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: call_blocks_optimization
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) @external_func, csr_ilp32_lp64, implicit-def $x1
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: call_blocks_optimization
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: PseudoCALL target-flags(riscv-call) @external_func, csr_ilp32_lp64, implicit-def $x1
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = LW %0, 0 :: (load (s32))
|
|
; Call instruction should block combining across it
|
|
PseudoCALL target-flags(riscv-call) @external_func, csr_ilp32_lp64, implicit-def $x1
|
|
%2:gpr = LW %0, 4 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Terminator instruction blocks optimization
|
|
name: terminator_blocks_optimization
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
; CHECK-LABEL: name: terminator_blocks_optimization
|
|
; CHECK: bb.0:
|
|
; CHECK-NEXT: successors: %bb.1(0x80000000)
|
|
; CHECK-NEXT: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: BEQ [[COPY1]], [[LW]], %bb.1
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: bb.1:
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: terminator_blocks_optimization
|
|
; CHECK-4BYTE: bb.0:
|
|
; CHECK-4BYTE-NEXT: successors: %bb.1(0x80000000)
|
|
; CHECK-4BYTE-NEXT: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: BEQ [[COPY1]], [[LW]], %bb.1
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: bb.1:
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = LW %0, 0 :: (load (s32))
|
|
BEQ %1, %2, %bb.1
|
|
|
|
bb.1:
|
|
; Should not combine across basic block boundary
|
|
%3:gpr = LW %0, 4 :: (load (s32))
|
|
%4:gpr = ADD %2, %3
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Memory aliasing - store between loads with unknown base should prevent combining
|
|
name: memory_aliasing
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
- { reg: '$x12', virtual-reg: '%2' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11, $x12
|
|
|
|
; CHECK-LABEL: name: memory_aliasing
|
|
; CHECK: liveins: $x10, $x11, $x12
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: SW [[COPY1]], [[COPY2]], 8 :: (store (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: memory_aliasing
|
|
; CHECK-4BYTE: liveins: $x10, $x11, $x12
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: SW [[COPY1]], [[COPY2]], 8 :: (store (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = COPY $x12
|
|
%3:gpr = LW %0, 0 :: (load (s32))
|
|
SW %1, %2, 8 :: (store (s32))
|
|
%4:gpr = LW %0, 4 :: (load (s32))
|
|
%5:gpr = ADD %3, %4
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Multiple pairs in same function
|
|
name: multiple_pairs
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: multiple_pairs
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: [[LW2:%[0-9]+]]:gpr = LW [[COPY1]], 8 :: (load (s32))
|
|
; CHECK-NEXT: [[LW3:%[0-9]+]]:gpr = LW [[COPY1]], 12 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[LW2]], [[LW3]]
|
|
; CHECK-NEXT: [[ADD2:%[0-9]+]]:gpr = ADD [[ADD]], [[ADD1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: multiple_pairs
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT2:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT3:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY1]], 8 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT2]], [[PseudoLD_RV32_OPT3]]
|
|
; CHECK-4BYTE-NEXT: [[ADD2:%[0-9]+]]:gpr = ADD [[ADD]], [[ADD1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
; First pair should combine
|
|
%2:gpr = LW %0, 0 :: (load (s32))
|
|
%3:gpr = LW %0, 4 :: (load (s32))
|
|
%4:gpr = ADD %2, %3
|
|
|
|
; Second pair should also combine
|
|
%5:gpr = LW %1, 8 :: (load (s32))
|
|
%6:gpr = LW %1, 12 :: (load (s32))
|
|
%7:gpr = ADD %5, %6
|
|
%8:gpr = ADD %4, %7
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Many loads test
|
|
name: many_loads
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: many_loads
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 16 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 20 :: (load (s32))
|
|
; CHECK-NEXT: [[LW2:%[0-9]+]]:gpr = LW [[COPY]], 24 :: (load (s32))
|
|
; CHECK-NEXT: [[LW3:%[0-9]+]]:gpr = LW [[COPY]], 28 :: (load (s32))
|
|
; CHECK-NEXT: [[LW4:%[0-9]+]]:gpr = LW [[COPY]], 32 :: (load (s32))
|
|
; CHECK-NEXT: [[LW5:%[0-9]+]]:gpr = LW [[COPY]], 36 :: (load (s32))
|
|
; CHECK-NEXT: [[LW6:%[0-9]+]]:gpr = LW [[COPY]], 40 :: (load (s32))
|
|
; CHECK-NEXT: [[LW7:%[0-9]+]]:gpr = LW [[COPY]], 44 :: (load (s32))
|
|
; CHECK-NEXT: [[LW8:%[0-9]+]]:gpr = LW [[COPY]], 48 :: (load (s32))
|
|
; CHECK-NEXT: [[LW9:%[0-9]+]]:gpr = LW [[COPY]], 52 :: (load (s32))
|
|
; CHECK-NEXT: [[LW10:%[0-9]+]]:gpr = LW [[COPY]], 56 :: (load (s32))
|
|
; CHECK-NEXT: [[LW11:%[0-9]+]]:gpr = LW [[COPY]], 60 :: (load (s32))
|
|
; CHECK-NEXT: [[LW12:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW13:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[LW2]], [[LW3]]
|
|
; CHECK-NEXT: [[ADD2:%[0-9]+]]:gpr = ADD [[LW4]], [[LW5]]
|
|
; CHECK-NEXT: [[ADD3:%[0-9]+]]:gpr = ADD [[LW6]], [[LW7]]
|
|
; CHECK-NEXT: [[ADD4:%[0-9]+]]:gpr = ADD [[LW8]], [[LW9]]
|
|
; CHECK-NEXT: [[ADD5:%[0-9]+]]:gpr = ADD [[LW10]], [[LW11]]
|
|
; CHECK-NEXT: [[ADD6:%[0-9]+]]:gpr = ADD [[LW12]], [[LW13]]
|
|
; CHECK-NEXT: [[ADD7:%[0-9]+]]:gpr = ADD [[ADD]], [[ADD1]]
|
|
; CHECK-NEXT: [[ADD8:%[0-9]+]]:gpr = ADD [[ADD2]], [[ADD3]]
|
|
; CHECK-NEXT: [[ADD9:%[0-9]+]]:gpr = ADD [[ADD4]], [[ADD5]]
|
|
; CHECK-NEXT: [[ADD10:%[0-9]+]]:gpr = ADD [[ADD6]], [[ADD7]]
|
|
; CHECK-NEXT: [[ADD11:%[0-9]+]]:gpr = ADD [[ADD8]], [[ADD9]]
|
|
; CHECK-NEXT: [[ADD12:%[0-9]+]]:gpr = ADD [[ADD10]], [[ADD11]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: many_loads
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 16 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT2:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT3:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 24 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT4:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT5:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 32 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT6:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT7:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 40 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT8:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT9:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 48 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT10:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT11:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 56 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT12:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT13:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT2]], [[PseudoLD_RV32_OPT3]]
|
|
; CHECK-4BYTE-NEXT: [[ADD2:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT4]], [[PseudoLD_RV32_OPT5]]
|
|
; CHECK-4BYTE-NEXT: [[ADD3:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT6]], [[PseudoLD_RV32_OPT7]]
|
|
; CHECK-4BYTE-NEXT: [[ADD4:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT8]], [[PseudoLD_RV32_OPT9]]
|
|
; CHECK-4BYTE-NEXT: [[ADD5:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT10]], [[PseudoLD_RV32_OPT11]]
|
|
; CHECK-4BYTE-NEXT: [[ADD6:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT12]], [[PseudoLD_RV32_OPT13]]
|
|
; CHECK-4BYTE-NEXT: [[ADD7:%[0-9]+]]:gpr = ADD [[ADD]], [[ADD1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD8:%[0-9]+]]:gpr = ADD [[ADD2]], [[ADD3]]
|
|
; CHECK-4BYTE-NEXT: [[ADD9:%[0-9]+]]:gpr = ADD [[ADD4]], [[ADD5]]
|
|
; CHECK-4BYTE-NEXT: [[ADD10:%[0-9]+]]:gpr = ADD [[ADD6]], [[ADD7]]
|
|
; CHECK-4BYTE-NEXT: [[ADD11:%[0-9]+]]:gpr = ADD [[ADD8]], [[ADD9]]
|
|
; CHECK-4BYTE-NEXT: [[ADD12:%[0-9]+]]:gpr = ADD [[ADD10]], [[ADD11]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Create high register pressure with many live values
|
|
%1:gpr = LW %0, 16 :: (load (s32))
|
|
%2:gpr = LW %0, 20 :: (load (s32))
|
|
%3:gpr = LW %0, 24 :: (load (s32))
|
|
%4:gpr = LW %0, 28 :: (load (s32))
|
|
%5:gpr = LW %0, 32 :: (load (s32))
|
|
%6:gpr = LW %0, 36 :: (load (s32))
|
|
%7:gpr = LW %0, 40 :: (load (s32))
|
|
%8:gpr = LW %0, 44 :: (load (s32))
|
|
%9:gpr = LW %0, 48 :: (load (s32))
|
|
%10:gpr = LW %0, 52 :: (load (s32))
|
|
%11:gpr = LW %0, 56 :: (load (s32))
|
|
%12:gpr = LW %0, 60 :: (load (s32))
|
|
|
|
; With high register pressure, these loads might not be combined
|
|
; depending on the profitability analysis
|
|
%13:gpr = LW %0, 0 :: (load (s32))
|
|
%14:gpr = LW %0, 4 :: (load (s32))
|
|
|
|
; Use all the loaded values to keep them live
|
|
%15:gpr = ADD %1, %2
|
|
%16:gpr = ADD %3, %4
|
|
%17:gpr = ADD %5, %6
|
|
%18:gpr = ADD %7, %8
|
|
%19:gpr = ADD %9, %10
|
|
%20:gpr = ADD %11, %12
|
|
%21:gpr = ADD %13, %14
|
|
%22:gpr = ADD %15, %16
|
|
%23:gpr = ADD %17, %18
|
|
%24:gpr = ADD %19, %20
|
|
%25:gpr = ADD %21, %22
|
|
%26:gpr = ADD %23, %24
|
|
%27:gpr = ADD %25, %26
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test reverse order - second load has lower offset than first
|
|
name: reverse_order_loads
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: reverse_order_loads
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: reverse_order_loads
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT1]], [[PseudoLD_RV32_OPT]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Load at higher offset first, then lower offset
|
|
; Should still be combined as LD with lower offset
|
|
%1:gpr = LW %0, 4 :: (load (s32))
|
|
%2:gpr = LW %0, 0 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test with immediate offset calculation
|
|
name: offset_calculation
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: offset_calculation
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 100 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 104 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: offset_calculation
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 100 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Test with different immediate values that are consecutive
|
|
%1:gpr = LW %0, 100 :: (load (s32))
|
|
%2:gpr = LW %0, 104 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test large offset values
|
|
name: large_offsets
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: large_offsets
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 2040 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 2044 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: large_offsets
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 2040 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Test with large offset values
|
|
%1:gpr = LW %0, 2040 :: (load (s32))
|
|
%2:gpr = LW %0, 2044 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test with negative offsets
|
|
name: negative_offsets
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: negative_offsets
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], -8 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], -4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: negative_offsets
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], -8 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Test with negative consecutive offsets
|
|
%1:gpr = LW %0, -8 :: (load (s32))
|
|
%2:gpr = LW %0, -4 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test with volatile loads - should not combine
|
|
name: volatile_loads
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: volatile_loads
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (volatile load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (volatile load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: volatile_loads
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (volatile load (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (volatile load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Volatile loads should not be combined
|
|
%1:gpr = LW %0, 0 :: (volatile load (s32))
|
|
%2:gpr = LW %0, 4 :: (volatile load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test store dependency - store modifies same location as load
|
|
name: store_dependency
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: store_dependency
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: SW [[COPY1]], [[COPY]], 4 :: (store (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: store_dependency
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: SW [[COPY1]], [[COPY]], 4 :: (store (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = LW %0, 0 :: (load (s32))
|
|
; Store to same location as second load - should prevent combination
|
|
SW %1, %0, 4 :: (store (s32))
|
|
%3:gpr = LW %0, 4 :: (load (s32))
|
|
%4:gpr = ADD %2, %3
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test three loads:
|
|
# align 8: last two should combine
|
|
# align 4: first two should combine
|
|
name: three_loads
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: three_loads
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[LW2:%[0-9]+]]:gpr = LW [[COPY]], 8 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[ADD]], [[LW2]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: three_loads
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 8 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[ADD]], [[LW]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; First two loads should combine, third should remain separate
|
|
%1:gpr = LW %0, 0 :: (load (s32))
|
|
%2:gpr = LW %0, 4 :: (load (s32))
|
|
%3:gpr = LW %0, 8 :: (load (s32))
|
|
%4:gpr = ADD %1, %2
|
|
%5:gpr = ADD %4, %3
|
|
PseudoRET
|
|
...
|
|
---
|
|
# Test where distance between loads exceeds MaxRescheduleDistance
|
|
name: distance_exceeds_max
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: distance_exceeds_max
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[ADD]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD2:%[0-9]+]]:gpr = ADD [[ADD1]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD3:%[0-9]+]]:gpr = ADD [[ADD2]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD4:%[0-9]+]]:gpr = ADD [[ADD3]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD5:%[0-9]+]]:gpr = ADD [[ADD4]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD6:%[0-9]+]]:gpr = ADD [[ADD5]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD7:%[0-9]+]]:gpr = ADD [[ADD6]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD8:%[0-9]+]]:gpr = ADD [[ADD7]], [[COPY1]]
|
|
; CHECK-NEXT: [[ADD9:%[0-9]+]]:gpr = ADD [[ADD8]], [[COPY1]]
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: distance_exceeds_max
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[ADD]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD2:%[0-9]+]]:gpr = ADD [[ADD1]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD3:%[0-9]+]]:gpr = ADD [[ADD2]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD4:%[0-9]+]]:gpr = ADD [[ADD3]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD5:%[0-9]+]]:gpr = ADD [[ADD4]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD6:%[0-9]+]]:gpr = ADD [[ADD5]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD7:%[0-9]+]]:gpr = ADD [[ADD6]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD8:%[0-9]+]]:gpr = ADD [[ADD7]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[ADD9:%[0-9]+]]:gpr = ADD [[ADD8]], [[COPY1]]
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = LW %0, 0 :: (load (s32))
|
|
; Insert 11 instructions between the two loads
|
|
; This makes the distance greater than the configured MaxRescheduleDistance
|
|
%3:gpr = ADD %2, %1
|
|
%4:gpr = ADD %3, %1
|
|
%5:gpr = ADD %4, %1
|
|
%6:gpr = ADD %5, %1
|
|
%7:gpr = ADD %6, %1
|
|
%8:gpr = ADD %7, %1
|
|
%9:gpr = ADD %8, %1
|
|
%10:gpr = ADD %9, %1
|
|
%11:gpr = ADD %10, %1
|
|
%12:gpr = ADD %11, %1
|
|
; Second load at offset 4 - too far from first load
|
|
%14:gpr = LW %0, 4 :: (load (s32))
|
|
PseudoRET
|
|
...
|
|
---
|
|
# Test combining loads with symbolic operands (global address)
|
|
name: symbolic_operands_global
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: symbolic_operands_global
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) @global_var :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) @global_var + 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: symbolic_operands_global
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], target-flags(riscv-lo) @global_var :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Two consecutive loads with symbolic global address operands
|
|
%1:gpr = LW %0, target-flags(riscv-lo) @global_var :: (load (s32))
|
|
%2:gpr = LW %0, target-flags(riscv-lo) @global_var + 4 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test that loads with different global symbols are not combined
|
|
name: symbolic_operands_different_globals
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
stack:
|
|
- { id: 0, offset: -4, size: 4 }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: symbolic_operands_different_globals
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) @global_var :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], %stack.0 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: symbolic_operands_different_globals
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) @global_var :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], %stack.0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Should not combine - different symbol types
|
|
%1:gpr = LW %0, target-flags(riscv-lo) @global_var :: (load (s32))
|
|
%2:gpr = LW %0, %stack.0 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
# Test combining loads with constant pool operands
|
|
name: symbolic_operands_constantpool
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
constants:
|
|
- id: 0
|
|
value: 'double 3.140000e+00'
|
|
alignment: 8
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10
|
|
|
|
; CHECK-LABEL: name: symbolic_operands_constantpool
|
|
; CHECK: liveins: $x10
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) %const.0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) %const.0 + 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW1]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: symbolic_operands_constantpool
|
|
; CHECK-4BYTE: liveins: $x10
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], target-flags(riscv-lo) %const.0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
; Two consecutive loads with constant pool operands
|
|
%1:gpr = LW %0, target-flags(riscv-lo) %const.0 :: (load (s32))
|
|
%2:gpr = LW %0, target-flags(riscv-lo) %const.0 + 4 :: (load (s32))
|
|
%3:gpr = ADD %1, %2
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
name: symbolic_operands_interleave
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: symbolic_operands_interleave
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) @global_var :: (load (s32))
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[LW2:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW3:%[0-9]+]]:gpr = LW [[COPY]], target-flags(riscv-lo) @global_var + 4 :: (load (s32))
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW2]]
|
|
; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[LW1]], [[LW3]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: symbolic_operands_interleave
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], target-flags(riscv-lo) @global_var :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT2:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT3:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT2]]
|
|
; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT3]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = LW %0, target-flags(riscv-lo) @global_var :: (load (s32))
|
|
%3:gpr = LW %0, 4 :: (load (s32))
|
|
%4:gpr = LW %0, 0 :: (load (s32))
|
|
%5:gpr = LW %0, target-flags(riscv-lo) @global_var + 4 :: (load (s32))
|
|
%6:gpr = ADD %2, %4
|
|
%7:gpr = ADD %3, %5
|
|
PseudoRET
|
|
|
|
...
|
|
---
|
|
name: frame_index
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, offset: 0, size: 8, alignment: 4 }
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: frame_index
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: SW [[COPY]], %stack.0, 0 :: (store (s32) into %ir.arr)
|
|
; CHECK-NEXT: SW [[COPY1]], %stack.0, 4 :: (store (s32) into %ir.arrayidx1)
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: frame_index
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: PseudoSD_RV32_OPT [[COPY]], [[COPY1]], %stack.0, 0 :: (store (s32) into %ir.arr), (store (s32) into %ir.arrayidx1)
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
SW %0:gpr, %stack.0, 0 :: (store (s32) into %ir.arr)
|
|
SW %1:gpr, %stack.0, 4 :: (store (s32) into %ir.arrayidx1)
|
|
PseudoRET
|
|
...
|
|
---
|
|
name: frame_index_operands_interleave
|
|
alignment: 4
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, offset: 0, size: 8, alignment: 4 }
|
|
liveins:
|
|
- { reg: '$x10', virtual-reg: '%0' }
|
|
- { reg: '$x11', virtual-reg: '%1' }
|
|
body: |
|
|
bb.0:
|
|
liveins: $x10, $x11
|
|
|
|
; CHECK-LABEL: name: frame_index_operands_interleave
|
|
; CHECK: liveins: $x10, $x11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-NEXT: [[LW:%[0-9]+]]:gpr = LW %stack.0, 0 :: (load (s32) from %ir.arr)
|
|
; CHECK-NEXT: [[LW1:%[0-9]+]]:gpr = LW [[COPY]], 4 :: (load (s32))
|
|
; CHECK-NEXT: [[LW2:%[0-9]+]]:gpr = LW [[COPY]], 0 :: (load (s32))
|
|
; CHECK-NEXT: [[LW3:%[0-9]+]]:gpr = LW %stack.0, 4 :: (load (s32) from %ir.arrayidx1)
|
|
; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[LW]], [[LW2]]
|
|
; CHECK-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[LW1]], [[LW3]]
|
|
; CHECK-NEXT: PseudoRET
|
|
;
|
|
; CHECK-4BYTE-LABEL: name: frame_index_operands_interleave
|
|
; CHECK-4BYTE: liveins: $x10, $x11
|
|
; CHECK-4BYTE-NEXT: {{ $}}
|
|
; CHECK-4BYTE-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
|
|
; CHECK-4BYTE-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT1:%[0-9]+]]:gpr = PseudoLD_RV32_OPT %stack.0, 0 :: (load (s32) from %ir.arr), (load (s32) from %ir.arrayidx1)
|
|
; CHECK-4BYTE-NEXT: [[PseudoLD_RV32_OPT2:%[0-9]+]]:gpr, [[PseudoLD_RV32_OPT3:%[0-9]+]]:gpr = PseudoLD_RV32_OPT [[COPY]], 0 :: (load (s32))
|
|
; CHECK-4BYTE-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT]], [[PseudoLD_RV32_OPT2]]
|
|
; CHECK-4BYTE-NEXT: [[ADD1:%[0-9]+]]:gpr = ADD [[PseudoLD_RV32_OPT3]], [[PseudoLD_RV32_OPT1]]
|
|
; CHECK-4BYTE-NEXT: PseudoRET
|
|
%0:gpr = COPY $x10
|
|
%1:gpr = COPY $x11
|
|
%2:gpr = LW %stack.0, 0 :: (load (s32) from %ir.arr)
|
|
%3:gpr = LW %0, 4 :: (load (s32))
|
|
%4:gpr = LW %0, 0 :: (load (s32))
|
|
%5:gpr = LW %stack.0, 4 :: (load (s32) from %ir.arrayidx1)
|
|
%6:gpr = ADD %2, %4
|
|
%7:gpr = ADD %3, %5
|
|
PseudoRET
|
|
|
|
...
|