aboutsummaryrefslogtreecommitdiff
path: root/third_party/llvm/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/llvm/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir')
-rw-r--r--third_party/llvm/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir1378
1 files changed, 1378 insertions, 0 deletions
diff --git a/third_party/llvm/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir b/third_party/llvm/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
new file mode 100644
index 0000000..20dc3a9
--- /dev/null
+++ b/third_party/llvm/llvm/test/CodeGen/RISCV/zilsd-ldst-opt-prera.mir
@@ -0,0 +1,1378 @@
+# 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-word-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
+
+...