diff options
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.mir | 1378 |
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 + +... |
