[llvm] [LoongArch] Introduce PseudoAddUpperImm to deduplicate stack-frame base address materialization (PR #217250)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 02:19:36 PDT 2026
https://github.com/lrzlin created https://github.com/llvm/llvm-project/pull/217250
This is largely inspired by https://github.com/llvm/llvm-project/pull/211748, except some LoongArch specific changes, which includes merge 12-bit signed immediate into `ld/st` instructions while materializing the frame index first to generate a `lu12i.w + add` combo if we could, instead of a `lu12i.w + ori + add`. So that we could use a `PseudoAddUpperImm` to replace them for `MachineLateInstrsCleanup` to deduplicate them later on.
This patch improves SPEC CPU2026 `709.cactus_r` performance by 27% (from 1.64 to 2.09).
>From 8e414afe218d38ffcee2d14f0a87e641b60a2277 Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Tue, 18 Aug 2026 12:04:28 +0800
Subject: [PATCH 1/2] [LoongArch][NFC] Add tests for large stack-frame base
address materialization
---
.../LoongArch/frame-base-dedup-la32.mir | 98 ++++++
.../LoongArch/frame-base-dedup-la64.mir | 291 ++++++++++++++++++
2 files changed, 389 insertions(+)
create mode 100644 llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir
create mode 100644 llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir
diff --git a/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir
new file mode 100644
index 0000000000000..5ec561aa754cc
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir
@@ -0,0 +1,98 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=loongarch32 \
+# RUN: -run-pass=prolog-epilog -run-pass=machine-latecleanup -o - %s \
+# RUN: | FileCheck -check-prefix=LA32 %s
+# RUN: llc -mtriple=loongarch32 \
+# RUN: -run-pass=prolog-epilog -run-pass=machine-latecleanup \
+# RUN: -run-pass=loongarch-expand-pseudo -o - %s \
+# RUN: | FileCheck -check-prefix=LA32-EXPAND %s
+#
+# Test that identical large stack-frame base address materializations are
+# deduplicated by MachineLateInstrsCleanup via PseudoAddUpperImm.
+
+--- |
+ define void @test_la32() nounwind { ret void }
+...
+---
+# LA32 -- verify with 32-bit loads/stores, and that the pseudo expands to
+# LU12I_W + ADD_W rather than ADD_D.
+#
+# Frame: 4 + 4 + 16384 + 4 (spill slot) = 16396 -> 16400.
+# %stack.0 -> 16400 - 4 = 16396 = (4 << 12) + 12
+# %stack.1 -> 16400 - 8 = 16392 = (4 << 12) + 8
+name: test_la32
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 4
+ hasCalls: false
+ maxCallFrameSize: 0
+stack:
+ - { id: 0, size: 4, alignment: 4 }
+ - { id: 1, size: 4, alignment: 4 }
+ - { id: 2, size: 16384, alignment: 4 }
+body: |
+ bb.0:
+ liveins: $r4, $r5
+ ; LA32-LABEL: name: test_la32
+ ; LA32: liveins: $r4, $r5
+ ; LA32-NEXT: {{ $}}
+ ; LA32-NEXT: $r6 = frame-setup LU12I_W 4
+ ; LA32-NEXT: $r6 = frame-setup ORI killed $r6, 16
+ ; LA32-NEXT: $r3 = frame-setup SUB_W $r3, killed $r6
+ ; LA32-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16400
+ ; LA32-NEXT: $r6 = LU12I_W 4
+ ; LA32-NEXT: $r6 = ORI killed $r6, 12
+ ; LA32-NEXT: $r6 = ADD_W $r3, killed $r6
+ ; LA32-NEXT: ST_W $r4, killed $r6, 0 :: (store (s32))
+ ; LA32-NEXT: $r4 = LU12I_W 4
+ ; LA32-NEXT: $r4 = ORI killed $r4, 8
+ ; LA32-NEXT: $r4 = ADD_W $r3, killed $r4
+ ; LA32-NEXT: ST_W $r5, killed $r4, 0 :: (store (s32))
+ ; LA32-NEXT: $r4 = LU12I_W 4
+ ; LA32-NEXT: $r4 = ORI killed $r4, 12
+ ; LA32-NEXT: $r4 = ADD_W $r3, killed $r4
+ ; LA32-NEXT: $r6 = LD_W killed $r4, 0 :: (load (s32))
+ ; LA32-NEXT: $r4 = LU12I_W 4
+ ; LA32-NEXT: $r4 = ORI killed $r4, 8
+ ; LA32-NEXT: $r4 = ADD_W $r3, killed $r4
+ ; LA32-NEXT: $r7 = LD_W killed $r4, 0 :: (load (s32))
+ ; LA32-NEXT: $r4 = frame-destroy LU12I_W 4
+ ; LA32-NEXT: $r4 = frame-destroy ORI killed $r4, 16
+ ; LA32-NEXT: $r3 = frame-destroy ADD_W $r3, killed $r4
+ ; LA32-NEXT: PseudoRET
+ ;
+ ; LA32-EXPAND-LABEL: name: test_la32
+ ; LA32-EXPAND: liveins: $r4, $r5
+ ; LA32-EXPAND-NEXT: {{ $}}
+ ; LA32-EXPAND-NEXT: $r6 = frame-setup LU12I_W 4
+ ; LA32-EXPAND-NEXT: $r6 = frame-setup ORI killed $r6, 16
+ ; LA32-EXPAND-NEXT: $r3 = frame-setup SUB_W $r3, killed $r6
+ ; LA32-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16400
+ ; LA32-EXPAND-NEXT: $r6 = LU12I_W 4
+ ; LA32-EXPAND-NEXT: $r6 = ORI killed $r6, 12
+ ; LA32-EXPAND-NEXT: $r6 = ADD_W $r3, killed $r6
+ ; LA32-EXPAND-NEXT: ST_W $r4, killed $r6, 0 :: (store (s32))
+ ; LA32-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA32-EXPAND-NEXT: $r4 = ORI killed $r4, 8
+ ; LA32-EXPAND-NEXT: $r4 = ADD_W $r3, killed $r4
+ ; LA32-EXPAND-NEXT: ST_W $r5, killed $r4, 0 :: (store (s32))
+ ; LA32-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA32-EXPAND-NEXT: $r4 = ORI killed $r4, 12
+ ; LA32-EXPAND-NEXT: $r4 = ADD_W $r3, killed $r4
+ ; LA32-EXPAND-NEXT: $r6 = LD_W killed $r4, 0 :: (load (s32))
+ ; LA32-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA32-EXPAND-NEXT: $r4 = ORI killed $r4, 8
+ ; LA32-EXPAND-NEXT: $r4 = ADD_W $r3, killed $r4
+ ; LA32-EXPAND-NEXT: $r7 = LD_W killed $r4, 0 :: (load (s32))
+ ; LA32-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 4
+ ; LA32-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 16
+ ; LA32-EXPAND-NEXT: $r3 = frame-destroy ADD_W $r3, killed $r4
+ ; LA32-EXPAND-NEXT: PseudoRET
+ ST_W $r4, %stack.0, 0 :: (store (s32))
+ ST_W $r5, %stack.1, 0 :: (store (s32))
+ $r6 = LD_W %stack.0, 0 :: (load (s32))
+ $r7 = LD_W %stack.1, 0 :: (load (s32))
+ PseudoRET
+...
+
diff --git a/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir
new file mode 100644
index 0000000000000..09e1447137f27
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir
@@ -0,0 +1,291 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=loongarch64 \
+# RUN: -run-pass=prolog-epilog -run-pass=machine-latecleanup -o - %s \
+# RUN: | FileCheck -check-prefix=LA64 %s
+# RUN: llc -mtriple=loongarch64 \
+# RUN: -run-pass=prolog-epilog -run-pass=machine-latecleanup \
+# RUN: -run-pass=loongarch-expand-pseudo -o - %s \
+# RUN: | FileCheck -check-prefix=LA64-EXPAND %s
+#
+# Test that identical large stack-frame base address materializations are
+# deduplicated by MachineLateInstrsCleanup via PseudoAddUpperImm.
+
+--- |
+ define void @test_same_region() nounwind { ret void }
+ define void @test_different_regions() nounwind { ret void }
+ define void @test_negative_lo12() nounwind { ret void }
+ define void @test_small_offset_no_pseudo() nounwind { ret void }
+...
+---
+# Multiple accesses to stack slots in the same 4096-aligned region.
+# PEI emits 4 PseudoAddUpperImm, MachineLateInstrsCleanup CSEs to 2.
+# After expansion, only 2 LU12I_W + ADD_D pairs remain instead of 4.
+#
+# Frame: 8 + 8 + 16384 + 8 (emergency spill slot) = 16408, rounded up to the
+# 16-byte stack alignment -> 16416.
+# %stack.0 -> 16416 - 8 = 16408 = (4 << 12) + 24
+# %stack.1 -> 16416 - 16 = 16400 = (4 << 12) + 16
+name: test_same_region
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 8
+ hasCalls: false
+ maxCallFrameSize: 0
+stack:
+ - { id: 0, size: 8, alignment: 8 }
+ - { id: 1, size: 8, alignment: 8 }
+ - { id: 2, size: 16384, alignment: 8 }
+body: |
+ bb.0:
+ liveins: $r4, $r5
+ ; LA64-LABEL: name: test_same_region
+ ; LA64: liveins: $r4, $r5
+ ; LA64-NEXT: {{ $}}
+ ; LA64-NEXT: $r6 = frame-setup LU12I_W 4
+ ; LA64-NEXT: $r6 = frame-setup ORI killed $r6, 32
+ ; LA64-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
+ ; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16416
+ ; LA64-NEXT: $r6 = LU12I_W 4
+ ; LA64-NEXT: $r6 = ORI killed $r6, 24
+ ; LA64-NEXT: $r6 = ADD_D $r3, killed $r6
+ ; LA64-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 16
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 24
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 16
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-NEXT: $r4 = frame-destroy LU12I_W 4
+ ; LA64-NEXT: $r4 = frame-destroy ORI killed $r4, 32
+ ; LA64-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
+ ; LA64-NEXT: PseudoRET
+ ;
+ ; LA64-EXPAND-LABEL: name: test_same_region
+ ; LA64-EXPAND: liveins: $r4, $r5
+ ; LA64-EXPAND-NEXT: {{ $}}
+ ; LA64-EXPAND-NEXT: $r6 = frame-setup LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r6 = frame-setup ORI killed $r6, 32
+ ; LA64-EXPAND-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
+ ; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16416
+ ; LA64-EXPAND-NEXT: $r6 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r6 = ORI killed $r6, 24
+ ; LA64-EXPAND-NEXT: $r6 = ADD_D $r3, killed $r6
+ ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 16
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 24
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 16
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 32
+ ; LA64-EXPAND-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: PseudoRET
+ ST_D $r4, %stack.0, 0 :: (store (s64))
+ ST_D $r5, %stack.1, 0 :: (store (s64))
+ $r6 = LD_D %stack.0, 0 :: (load (s64))
+ $r7 = LD_D %stack.1, 0 :: (load (s64))
+ PseudoRET
+...
+---
+# Accesses to stack slots in different 4096-aligned regions.
+# Different base anchors cannot be CSE'd with each other.
+#
+# Frame: 8 + 4096 + 8 + 16384 + 8 (spill slot) = 20504 -> 20512.
+# %stack.0 -> 20512 - 8 = 20504 = (5 << 12) + 24
+# %stack.2 -> 20512 - 4112 = 16400 = (4 << 12) + 16
+name: test_different_regions
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 8
+ hasCalls: false
+ maxCallFrameSize: 0
+stack:
+ - { id: 0, size: 8, alignment: 8 }
+ - { id: 1, size: 4096, alignment: 8 }
+ - { id: 2, size: 8, alignment: 8 }
+ - { id: 3, size: 16384, alignment: 8 }
+body: |
+ bb.0:
+ liveins: $r4, $r5
+ ; LA64-LABEL: name: test_different_regions
+ ; LA64: liveins: $r4, $r5
+ ; LA64-NEXT: {{ $}}
+ ; LA64-NEXT: $r6 = frame-setup LU12I_W 5
+ ; LA64-NEXT: $r6 = frame-setup ORI killed $r6, 32
+ ; LA64-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
+ ; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 20512
+ ; LA64-NEXT: $r6 = LU12I_W 5
+ ; LA64-NEXT: $r6 = ORI killed $r6, 24
+ ; LA64-NEXT: $r6 = ADD_D $r3, killed $r6
+ ; LA64-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 16
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-NEXT: $r4 = frame-destroy LU12I_W 5
+ ; LA64-NEXT: $r4 = frame-destroy ORI killed $r4, 32
+ ; LA64-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
+ ; LA64-NEXT: PseudoRET
+ ;
+ ; LA64-EXPAND-LABEL: name: test_different_regions
+ ; LA64-EXPAND: liveins: $r4, $r5
+ ; LA64-EXPAND-NEXT: {{ $}}
+ ; LA64-EXPAND-NEXT: $r6 = frame-setup LU12I_W 5
+ ; LA64-EXPAND-NEXT: $r6 = frame-setup ORI killed $r6, 32
+ ; LA64-EXPAND-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
+ ; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 20512
+ ; LA64-EXPAND-NEXT: $r6 = LU12I_W 5
+ ; LA64-EXPAND-NEXT: $r6 = ORI killed $r6, 24
+ ; LA64-EXPAND-NEXT: $r6 = ADD_D $r3, killed $r6
+ ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 16
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 5
+ ; LA64-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 32
+ ; LA64-EXPAND-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: PseudoRET
+ ST_D $r4, %stack.0, 0 :: (store (s64))
+ ST_D $r5, %stack.2, 0 :: (store (s64))
+ PseudoRET
+...
+---
+# The lower 12 bits are folded into the ld/st with a negative si12, so the
+# upper immediate must carry a +1 with respect to a plain arithmetic shift
+# of the full offset. This is the case that a `Val >> 12` (instead of
+# `(Val - Lo12) >> 12`) gets wrong by exactly 4096 bytes.
+#
+# Frame: 8 + 8 + 18432 + 8 (spill slot) = 18456 -> 18464.
+# %stack.0 -> 18464 - 8 = 18456 = (5 << 12) - 2024
+# %stack.1 -> 18464 - 16 = 18448 = (5 << 12) - 2032
+name: test_negative_lo12
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 8
+ hasCalls: false
+ maxCallFrameSize: 0
+stack:
+ - { id: 0, size: 8, alignment: 8 }
+ - { id: 1, size: 8, alignment: 8 }
+ - { id: 2, size: 18432, alignment: 8 }
+body: |
+ bb.0:
+ liveins: $r4, $r5
+ ; LA64-LABEL: name: test_negative_lo12
+ ; LA64: liveins: $r4, $r5
+ ; LA64-NEXT: {{ $}}
+ ; LA64-NEXT: $r6 = frame-setup LU12I_W 4
+ ; LA64-NEXT: $r6 = frame-setup ORI killed $r6, 2080
+ ; LA64-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
+ ; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 18464
+ ; LA64-NEXT: $r6 = LU12I_W 4
+ ; LA64-NEXT: $r6 = ORI killed $r6, 2072
+ ; LA64-NEXT: $r6 = ADD_D $r3, killed $r6
+ ; LA64-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 2064
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 2072
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-NEXT: $r4 = LU12I_W 4
+ ; LA64-NEXT: $r4 = ORI killed $r4, 2064
+ ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-NEXT: $r4 = frame-destroy LU12I_W 4
+ ; LA64-NEXT: $r4 = frame-destroy ORI killed $r4, 2080
+ ; LA64-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
+ ; LA64-NEXT: PseudoRET
+ ;
+ ; LA64-EXPAND-LABEL: name: test_negative_lo12
+ ; LA64-EXPAND: liveins: $r4, $r5
+ ; LA64-EXPAND-NEXT: {{ $}}
+ ; LA64-EXPAND-NEXT: $r6 = frame-setup LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r6 = frame-setup ORI killed $r6, 2080
+ ; LA64-EXPAND-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
+ ; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 18464
+ ; LA64-EXPAND-NEXT: $r6 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r6 = ORI killed $r6, 2072
+ ; LA64-EXPAND-NEXT: $r6 = ADD_D $r3, killed $r6
+ ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 2064
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 2072
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 2064
+ ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 4
+ ; LA64-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 2080
+ ; LA64-EXPAND-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
+ ; LA64-EXPAND-NEXT: PseudoRET
+ ST_D $r4, %stack.0, 0 :: (store (s64))
+ ST_D $r5, %stack.1, 0 :: (store (s64))
+ $r6 = LD_D %stack.0, 0 :: (load (s64))
+ $r7 = LD_D %stack.1, 0 :: (load (s64))
+ PseudoRET
+...
+---
+# Small stack frame -- offsets fit in 12-bit signed immediate.
+# No PseudoAddUpperImm generated (and no emergency spill slot either).
+name: test_small_offset_no_pseudo
+alignment: 4
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 8
+ hasCalls: false
+ maxCallFrameSize: 0
+stack:
+ - { id: 0, size: 8, alignment: 8 }
+ - { id: 1, size: 8, alignment: 8 }
+body: |
+ bb.0:
+ liveins: $r4, $r5
+ ; LA64-LABEL: name: test_small_offset_no_pseudo
+ ; LA64: liveins: $r4, $r5
+ ; LA64-NEXT: {{ $}}
+ ; LA64-NEXT: $r3 = frame-setup ADDI_D $r3, -16
+ ; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; LA64-NEXT: ST_D $r4, $r3, 8 :: (store (s64))
+ ; LA64-NEXT: ST_D $r5, $r3, 0 :: (store (s64))
+ ; LA64-NEXT: $r3 = frame-destroy ADDI_D $r3, 16
+ ; LA64-NEXT: PseudoRET
+ ;
+ ; LA64-EXPAND-LABEL: name: test_small_offset_no_pseudo
+ ; LA64-EXPAND: liveins: $r4, $r5
+ ; LA64-EXPAND-NEXT: {{ $}}
+ ; LA64-EXPAND-NEXT: $r3 = frame-setup ADDI_D $r3, -16
+ ; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; LA64-EXPAND-NEXT: ST_D $r4, $r3, 8 :: (store (s64))
+ ; LA64-EXPAND-NEXT: ST_D $r5, $r3, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r3 = frame-destroy ADDI_D $r3, 16
+ ; LA64-EXPAND-NEXT: PseudoRET
+ ST_D $r4, %stack.0, 0 :: (store (s64))
+ ST_D $r5, %stack.1, 0 :: (store (s64))
+ PseudoRET
+...
+
>From 041d9bc8f5f5df5f16f561ac8bec9f397f938b11 Mon Sep 17 00:00:00 2001
From: Lin Runze <lrzlin at 163.com>
Date: Wed, 12 Aug 2026 17:00:50 +0800
Subject: [PATCH 2/2] [LoongArch] Introduce PseudoAddUpperImm to deduplicate
stack-frame base address materialization
---
.../LoongArch/LoongArchExpandPseudoInsts.cpp | 31 ++++++
.../Target/LoongArch/LoongArchInstrInfo.td | 7 ++
.../LoongArch/LoongArchRegisterInfo.cpp | 58 +++++++++--
.../CodeGen/LoongArch/emergency-spill-slot.ll | 3 +-
.../LoongArch/frame-base-dedup-la32.mir | 38 ++-----
.../LoongArch/frame-base-dedup-la64.mir | 98 ++++++-------------
.../CodeGen/LoongArch/stack-clash-prologue.ll | 8 +-
7 files changed, 130 insertions(+), 113 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index b3167174454a3..92537c34ce24a 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -772,6 +772,8 @@ class LoongArchExpandPseudo : public MachineFunctionPass {
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI,
bool IsTailCall);
+ bool expandAddUpperImm(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI);
};
char LoongArchExpandPseudo::ID = 0;
@@ -810,6 +812,8 @@ bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);
case LoongArch::PseudoTAIL_MEDIUM:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
+ case LoongArch::PseudoAddUpperImm:
+ return expandAddUpperImm(MBB, MBBI);
}
return false;
@@ -927,6 +931,33 @@ bool LoongArchExpandPseudo::expandFunctionCALL(
return true;
}
+bool LoongArchExpandPseudo::expandAddUpperImm(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
+ DebugLoc DL = MBBI->getDebugLoc();
+ MachineFunction *MF = MBB.getParent();
+ const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+
+ Register DstReg = MBBI->getOperand(0).getReg();
+ bool DstIsDead = MBBI->getOperand(0).isDead();
+ bool Renamable = MBBI->getOperand(0).isRenamable();
+ Register BaseReg = MBBI->getOperand(1).getReg();
+ int64_t Hi = MBBI->getOperand(2).getImm();
+ bool IsLA64 = STI.is64Bit();
+
+ // Expand to LU12I_W + ADD_W/D: the immediate is upper 20-bit.
+ BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W))
+ .addReg(DstReg, RegState::Define | getRenamableRegState(Renamable))
+ .addImm(Hi);
+ BuildMI(MBB, MBBI, DL, TII->get(IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W))
+ .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead) |
+ getRenamableRegState(Renamable))
+ .addReg(BaseReg)
+ .addReg(DstReg, RegState::Kill | getRenamableRegState(Renamable));
+
+ MBBI->eraseFromParent();
+ return true;
+}
+
} // end namespace
INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 6aacfd8138ff5..2d123e68015f1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -1891,6 +1891,13 @@ def : InstAlias<"la.local $dst, $tmp, $src",
(PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>;
} // Predicates = [HasLaLocalWithAbs]
+// Materializes "$base + (imm << 12)" as a single pseudo so that
+// MachineLateInstrsCleanup can CSE identical upper-immediate additions.
+// Expanded to LU12I_W + ADD by LoongArchExpandPseudo.
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8 in
+def PseudoAddUpperImm
+ : Pseudo<(outs GPR:$dst), (ins GPR:$base, simm20_lu12iw:$hi), []>;
+
/// BSTRINS and BSTRPICK
let Predicates = [IsLA32, Has32S] in {
diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
index 0161979618412..1be43c2571bf8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
@@ -151,6 +151,33 @@ bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int FixedOffset = Offset.getFixed();
bool OffsetLegal = true;
+ // True only when the instruction's immediate field is si12.
+ bool HasSimm12Field = false;
+ switch (MIOpc) {
+ case LoongArch::LD_B:
+ case LoongArch::LD_H:
+ case LoongArch::LD_W:
+ case LoongArch::LD_D:
+ case LoongArch::LD_BU:
+ case LoongArch::LD_HU:
+ case LoongArch::LD_WU:
+ case LoongArch::ST_B:
+ case LoongArch::ST_H:
+ case LoongArch::ST_W:
+ case LoongArch::ST_D:
+ case LoongArch::FLD_S:
+ case LoongArch::FLD_D:
+ case LoongArch::FST_S:
+ case LoongArch::FST_D:
+ case LoongArch::VLD:
+ case LoongArch::VST:
+ case LoongArch::XVLD:
+ case LoongArch::XVST:
+ case LoongArch::VLDREPL_B:
+ case LoongArch::XVLDREPL_B:
+ HasSimm12Field = true;
+ break;
+ }
// Handle offsets that exceed the immediate range of the instruction.
switch (MIOpc) {
@@ -189,22 +216,35 @@ bool LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
if (!isInt<12>(FixedOffset)) {
unsigned Addi = IsLA64 ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned Add = IsLA64 ? LoongArch::ADD_D : LoongArch::ADD_W;
+ int64_t Val = Offset.getFixed();
+ // Keep the old behaviour of materializing the whole offset for instructions
+ // do not have simm12 field or ADDI due to it will be replaced.
+ int64_t Lo12 = !HasSimm12Field ? 0 : SignExtend64<12>(Val);
+ uint64_t HiVal = (uint64_t)Val - (uint64_t)Lo12;
// The offset won't fit in an immediate, so use a scratch register instead.
// Modify Offset and FrameReg appropriately.
Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
- TII->movImm(MBB, II, DL, ScratchReg, Offset.getFixed());
- if (MIOpc == Addi) {
- BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())
+ // Move lower 12-bit of offset into original instruction.
+ Offset = StackOffset::getFixed(Lo12);
+
+ if (HasSimm12Field && isShiftedInt<20, 12>(HiVal)) {
+ BuildMI(MBB, II, DL, TII->get(LoongArch::PseudoAddUpperImm), ScratchReg)
+ .addReg(FrameReg)
+ .addImm(static_cast<uint32_t>(HiVal) >> 12);
+ } else {
+ TII->movImm(MBB, II, DL, ScratchReg, HiVal);
+ if (MIOpc == Addi) {
+ BuildMI(MBB, II, DL, TII->get(Add), MI.getOperand(0).getReg())
+ .addReg(FrameReg)
+ .addReg(ScratchReg, RegState::Kill);
+ MI.eraseFromParent();
+ return true;
+ }
+ BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)
.addReg(FrameReg)
.addReg(ScratchReg, RegState::Kill);
- MI.eraseFromParent();
- return true;
}
- BuildMI(MBB, II, DL, TII->get(Add), ScratchReg)
- .addReg(FrameReg)
- .addReg(ScratchReg, RegState::Kill);
- Offset = StackOffset::getFixed(0);
FrameReg = ScratchReg;
FrameRegIsKill = true;
}
diff --git a/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll b/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll
index 15ac95dfc6c55..158f98df38c21 100644
--- a/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll
+++ b/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll
@@ -30,9 +30,8 @@ define void @func() {
; CHECK-NEXT: ld.w $a0, $a1, 0
; CHECK-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill
; CHECK-NEXT: lu12i.w $fp, 1
-; CHECK-NEXT: ori $fp, $fp, 12
; CHECK-NEXT: add.d $fp, $sp, $fp
-; CHECK-NEXT: st.w $t8, $fp, 0
+; CHECK-NEXT: st.w $t8, $fp, 12
; CHECK-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload
; CHECK-NEXT: st.w $t8, $a1, 0
; CHECK-NEXT: st.w $t7, $a1, 0
diff --git a/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir
index 5ec561aa754cc..d36c5a54788b9 100644
--- a/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir
+++ b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la32.mir
@@ -41,22 +41,12 @@ body: |
; LA32-NEXT: $r6 = frame-setup ORI killed $r6, 16
; LA32-NEXT: $r3 = frame-setup SUB_W $r3, killed $r6
; LA32-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16400
- ; LA32-NEXT: $r6 = LU12I_W 4
- ; LA32-NEXT: $r6 = ORI killed $r6, 12
- ; LA32-NEXT: $r6 = ADD_W $r3, killed $r6
- ; LA32-NEXT: ST_W $r4, killed $r6, 0 :: (store (s32))
- ; LA32-NEXT: $r4 = LU12I_W 4
- ; LA32-NEXT: $r4 = ORI killed $r4, 8
- ; LA32-NEXT: $r4 = ADD_W $r3, killed $r4
- ; LA32-NEXT: ST_W $r5, killed $r4, 0 :: (store (s32))
- ; LA32-NEXT: $r4 = LU12I_W 4
- ; LA32-NEXT: $r4 = ORI killed $r4, 12
- ; LA32-NEXT: $r4 = ADD_W $r3, killed $r4
- ; LA32-NEXT: $r6 = LD_W killed $r4, 0 :: (load (s32))
- ; LA32-NEXT: $r4 = LU12I_W 4
- ; LA32-NEXT: $r4 = ORI killed $r4, 8
- ; LA32-NEXT: $r4 = ADD_W $r3, killed $r4
- ; LA32-NEXT: $r7 = LD_W killed $r4, 0 :: (load (s32))
+ ; LA32-NEXT: $r6 = PseudoAddUpperImm $r3, 4
+ ; LA32-NEXT: ST_W $r4, killed $r6, 12 :: (store (s32))
+ ; LA32-NEXT: $r4 = PseudoAddUpperImm $r3, 4
+ ; LA32-NEXT: ST_W $r5, $r4, 8 :: (store (s32))
+ ; LA32-NEXT: $r6 = LD_W $r4, 12 :: (load (s32))
+ ; LA32-NEXT: $r7 = LD_W killed $r4, 8 :: (load (s32))
; LA32-NEXT: $r4 = frame-destroy LU12I_W 4
; LA32-NEXT: $r4 = frame-destroy ORI killed $r4, 16
; LA32-NEXT: $r3 = frame-destroy ADD_W $r3, killed $r4
@@ -70,21 +60,13 @@ body: |
; LA32-EXPAND-NEXT: $r3 = frame-setup SUB_W $r3, killed $r6
; LA32-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16400
; LA32-EXPAND-NEXT: $r6 = LU12I_W 4
- ; LA32-EXPAND-NEXT: $r6 = ORI killed $r6, 12
; LA32-EXPAND-NEXT: $r6 = ADD_W $r3, killed $r6
- ; LA32-EXPAND-NEXT: ST_W $r4, killed $r6, 0 :: (store (s32))
+ ; LA32-EXPAND-NEXT: ST_W $r4, killed $r6, 12 :: (store (s32))
; LA32-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA32-EXPAND-NEXT: $r4 = ORI killed $r4, 8
; LA32-EXPAND-NEXT: $r4 = ADD_W $r3, killed $r4
- ; LA32-EXPAND-NEXT: ST_W $r5, killed $r4, 0 :: (store (s32))
- ; LA32-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA32-EXPAND-NEXT: $r4 = ORI killed $r4, 12
- ; LA32-EXPAND-NEXT: $r4 = ADD_W $r3, killed $r4
- ; LA32-EXPAND-NEXT: $r6 = LD_W killed $r4, 0 :: (load (s32))
- ; LA32-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA32-EXPAND-NEXT: $r4 = ORI killed $r4, 8
- ; LA32-EXPAND-NEXT: $r4 = ADD_W $r3, killed $r4
- ; LA32-EXPAND-NEXT: $r7 = LD_W killed $r4, 0 :: (load (s32))
+ ; LA32-EXPAND-NEXT: ST_W $r5, $r4, 8 :: (store (s32))
+ ; LA32-EXPAND-NEXT: $r6 = LD_W $r4, 12 :: (load (s32))
+ ; LA32-EXPAND-NEXT: $r7 = LD_W killed $r4, 8 :: (load (s32))
; LA32-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 4
; LA32-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 16
; LA32-EXPAND-NEXT: $r3 = frame-destroy ADD_W $r3, killed $r4
diff --git a/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir
index 09e1447137f27..9a9ae3e9c697d 100644
--- a/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir
+++ b/llvm/test/CodeGen/LoongArch/frame-base-dedup-la64.mir
@@ -46,22 +46,12 @@ body: |
; LA64-NEXT: $r6 = frame-setup ORI killed $r6, 32
; LA64-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16416
- ; LA64-NEXT: $r6 = LU12I_W 4
- ; LA64-NEXT: $r6 = ORI killed $r6, 24
- ; LA64-NEXT: $r6 = ADD_D $r3, killed $r6
- ; LA64-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 16
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 24
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 16
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-NEXT: $r6 = PseudoAddUpperImm $r3, 4
+ ; LA64-NEXT: ST_D $r4, killed $r6, 24 :: (store (s64))
+ ; LA64-NEXT: $r4 = PseudoAddUpperImm $r3, 4
+ ; LA64-NEXT: ST_D $r5, $r4, 16 :: (store (s64))
+ ; LA64-NEXT: $r6 = LD_D $r4, 24 :: (load (s64))
+ ; LA64-NEXT: $r7 = LD_D killed $r4, 16 :: (load (s64))
; LA64-NEXT: $r4 = frame-destroy LU12I_W 4
; LA64-NEXT: $r4 = frame-destroy ORI killed $r4, 32
; LA64-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
@@ -75,21 +65,13 @@ body: |
; LA64-EXPAND-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16416
; LA64-EXPAND-NEXT: $r6 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r6 = ORI killed $r6, 24
; LA64-EXPAND-NEXT: $r6 = ADD_D $r3, killed $r6
- ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 24 :: (store (s64))
; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 16
; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
- ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 24
- ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
- ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 16
- ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-EXPAND-NEXT: ST_D $r5, $r4, 16 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r6 = LD_D $r4, 24 :: (load (s64))
+ ; LA64-EXPAND-NEXT: $r7 = LD_D killed $r4, 16 :: (load (s64))
; LA64-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 4
; LA64-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 32
; LA64-EXPAND-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
@@ -129,14 +111,10 @@ body: |
; LA64-NEXT: $r6 = frame-setup ORI killed $r6, 32
; LA64-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 20512
- ; LA64-NEXT: $r6 = LU12I_W 5
- ; LA64-NEXT: $r6 = ORI killed $r6, 24
- ; LA64-NEXT: $r6 = ADD_D $r3, killed $r6
- ; LA64-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 16
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-NEXT: $r6 = PseudoAddUpperImm $r3, 5
+ ; LA64-NEXT: ST_D $r4, killed $r6, 24 :: (store (s64))
+ ; LA64-NEXT: $r4 = PseudoAddUpperImm $r3, 4
+ ; LA64-NEXT: ST_D $r5, killed $r4, 16 :: (store (s64))
; LA64-NEXT: $r4 = frame-destroy LU12I_W 5
; LA64-NEXT: $r4 = frame-destroy ORI killed $r4, 32
; LA64-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
@@ -150,13 +128,11 @@ body: |
; LA64-EXPAND-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 20512
; LA64-EXPAND-NEXT: $r6 = LU12I_W 5
- ; LA64-EXPAND-NEXT: $r6 = ORI killed $r6, 24
; LA64-EXPAND-NEXT: $r6 = ADD_D $r3, killed $r6
- ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 24 :: (store (s64))
; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 16
; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
+ ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 16 :: (store (s64))
; LA64-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 5
; LA64-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 32
; LA64-EXPAND-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
@@ -195,22 +171,12 @@ body: |
; LA64-NEXT: $r6 = frame-setup ORI killed $r6, 2080
; LA64-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
; LA64-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 18464
- ; LA64-NEXT: $r6 = LU12I_W 4
- ; LA64-NEXT: $r6 = ORI killed $r6, 2072
- ; LA64-NEXT: $r6 = ADD_D $r3, killed $r6
- ; LA64-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 2064
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 2072
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
- ; LA64-NEXT: $r4 = LU12I_W 4
- ; LA64-NEXT: $r4 = ORI killed $r4, 2064
- ; LA64-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-NEXT: $r6 = PseudoAddUpperImm $r3, 5
+ ; LA64-NEXT: ST_D $r4, killed $r6, -2024 :: (store (s64))
+ ; LA64-NEXT: $r4 = PseudoAddUpperImm $r3, 5
+ ; LA64-NEXT: ST_D $r5, $r4, -2032 :: (store (s64))
+ ; LA64-NEXT: $r6 = LD_D $r4, -2024 :: (load (s64))
+ ; LA64-NEXT: $r7 = LD_D killed $r4, -2032 :: (load (s64))
; LA64-NEXT: $r4 = frame-destroy LU12I_W 4
; LA64-NEXT: $r4 = frame-destroy ORI killed $r4, 2080
; LA64-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
@@ -223,22 +189,14 @@ body: |
; LA64-EXPAND-NEXT: $r6 = frame-setup ORI killed $r6, 2080
; LA64-EXPAND-NEXT: $r3 = frame-setup SUB_D $r3, killed $r6
; LA64-EXPAND-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 18464
- ; LA64-EXPAND-NEXT: $r6 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r6 = ORI killed $r6, 2072
+ ; LA64-EXPAND-NEXT: $r6 = LU12I_W 5
; LA64-EXPAND-NEXT: $r6 = ADD_D $r3, killed $r6
- ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, 0 :: (store (s64))
- ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 2064
- ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: ST_D $r5, killed $r4, 0 :: (store (s64))
- ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 2072
- ; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: $r6 = LD_D killed $r4, 0 :: (load (s64))
- ; LA64-EXPAND-NEXT: $r4 = LU12I_W 4
- ; LA64-EXPAND-NEXT: $r4 = ORI killed $r4, 2064
+ ; LA64-EXPAND-NEXT: ST_D $r4, killed $r6, -2024 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r4 = LU12I_W 5
; LA64-EXPAND-NEXT: $r4 = ADD_D $r3, killed $r4
- ; LA64-EXPAND-NEXT: $r7 = LD_D killed $r4, 0 :: (load (s64))
+ ; LA64-EXPAND-NEXT: ST_D $r5, $r4, -2032 :: (store (s64))
+ ; LA64-EXPAND-NEXT: $r6 = LD_D $r4, -2024 :: (load (s64))
+ ; LA64-EXPAND-NEXT: $r7 = LD_D killed $r4, -2032 :: (load (s64))
; LA64-EXPAND-NEXT: $r4 = frame-destroy LU12I_W 4
; LA64-EXPAND-NEXT: $r4 = frame-destroy ORI killed $r4, 2080
; LA64-EXPAND-NEXT: $r3 = frame-destroy ADD_D $r3, killed $r4
diff --git a/llvm/test/CodeGen/LoongArch/stack-clash-prologue.ll b/llvm/test/CodeGen/LoongArch/stack-clash-prologue.ll
index 4e814baf05d51..dfb468e93c04e 100644
--- a/llvm/test/CodeGen/LoongArch/stack-clash-prologue.ll
+++ b/llvm/test/CodeGen/LoongArch/stack-clash-prologue.ll
@@ -465,9 +465,9 @@ define i32 @f9(i64 %i) local_unnamed_addr #0 {
; LA64-NEXT: add.d $a1, $sp, $a1
; LA64-NEXT: ori $a2, $zero, 1
; LA64-NEXT: stx.w $a2, $a0, $a1
-; LA64-NEXT: ori $a0, $zero, 2048
+; LA64-NEXT: lu12i.w $a0, 1
; LA64-NEXT: add.d $a0, $sp, $a0
-; LA64-NEXT: ld.w $a0, $a0, 0
+; LA64-NEXT: ld.w $a0, $a0, -2048
; LA64-NEXT: lu12i.w $a1, 2
; LA64-NEXT: ori $a1, $a1, 2048
; LA64-NEXT: sub.d $sp, $fp, $a1
@@ -502,9 +502,9 @@ define i32 @f9(i64 %i) local_unnamed_addr #0 {
; LA32-NEXT: add.w $a0, $a1, $a0
; LA32-NEXT: ori $a1, $zero, 1
; LA32-NEXT: st.w $a1, $a0, 0
-; LA32-NEXT: ori $a0, $zero, 2048
+; LA32-NEXT: lu12i.w $a0, 1
; LA32-NEXT: add.w $a0, $sp, $a0
-; LA32-NEXT: ld.w $a0, $a0, 0
+; LA32-NEXT: ld.w $a0, $a0, -2048
; LA32-NEXT: lu12i.w $a1, 2
; LA32-NEXT: ori $a1, $a1, 2048
; LA32-NEXT: sub.w $sp, $fp, $a1
More information about the llvm-commits
mailing list