[llvm] [AArch64MIPeepholeOpt] Coalesce sibling base-address materializations (PR #223682)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 15 19:00:23 PDT 2026
https://github.com/whokeke updated https://github.com/llvm/llvm-project/pull/223682
>From e1f6b845ebbed6a47f6f044dcaded81a1ffbce80 Mon Sep 17 00:00:00 2001
From: whoiskk <hukeke2 at huawei.com>
Date: Fri, 31 Jul 2026 05:02:44 +0800
Subject: [PATCH] [AArch64MIPeepholeOpt] Coalesce sibling base-address
materializations
ISel materializes an independent SUBXri/ADDXri base for each negative
far-offset load/store whose offset falls outside LDUR's 9-bit signed
range, giving the accesses different base registers and preventing the
LoadStoreOptimizer from pairing them into LDP/STP.
Add AArch64MIPeepholeOpt::shareBaseAddresses, which coalesces sibling
single-use ADDXri/SUBXri (shift 0) materializations feeding scaled
LDRui/STRui within a basic block. The minimum-offset materialization
becomes the primary; each secondary load/store is rewritten to use it
with an adjusted scaled offset and its def is erased, restoring a
shared base so the LoadStoreOptimizer can pair the accesses. Gated by
-aarch64-base-address-cse (default on); runs pre-RA on SSA form, so
no register scavenger is needed.
Test: base-address-cse.mir (pass-level SHARED/NOBASECSE),
base-address-cse.ll (end-to-end i32/i64/Q load + store,
large offset, ENABLED vs NOBASECSE)
---
.../Target/AArch64/AArch64MIPeepholeOpt.cpp | 110 ++++++++++
llvm/test/CodeGen/AArch64/base-address-cse.ll | 207 ++++++++++++++++++
.../test/CodeGen/AArch64/base-address-cse.mir | 101 +++++++++
3 files changed, 418 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/base-address-cse.ll
create mode 100644 llvm/test/CodeGen/AArch64/base-address-cse.mir
diff --git a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp
index 554d5938cf2cd..d06020fd95f67 100644
--- a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp
@@ -72,13 +72,20 @@
#include "AArch64ExpandImm.h"
#include "AArch64InstrInfo.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
#define DEBUG_TYPE "aarch64-mi-peephole-opt"
+static cl::opt<bool> EnableBaseAddressCSE(
+ "aarch64-base-address-cse", cl::init(true), cl::Hidden,
+ cl::desc("Coalesce sibling base-address materializations to enable "
+ "LDP/STP pairing"));
+
namespace {
class AArch64MIPeepholeOptImpl {
@@ -143,6 +150,8 @@ class AArch64MIPeepholeOptImpl {
bool visitFMOVDr(MachineInstr &MI);
bool visitUBFMXri(MachineInstr &MI);
bool visitCopy(MachineInstr &MI);
+
+ bool shareBaseAddresses(MachineBasicBlock &MBB);
};
struct AArch64MIPeepholeOptLegacy : public MachineFunctionPass {
@@ -957,6 +966,106 @@ bool AArch64MIPeepholeOptImpl::visitCopy(MachineInstr &MI) {
return true;
}
+bool AArch64MIPeepholeOptImpl::shareBaseAddresses(MachineBasicBlock &MBB) {
+ if (!EnableBaseAddressCSE)
+ return false;
+
+ bool Changed = false;
+
+ struct Cand {
+ MachineInstr *DefMI;
+ Register SrcReg;
+ unsigned Opc;
+ int64_t C;
+ Register BaseReg;
+ MachineInstr *UserMI;
+ int Scale;
+ int64_t OldOff;
+ };
+ SmallVector<Cand, 8> Cands;
+ using Key = std::pair<Register, unsigned>;
+ MapVector<Key, SmallVector<unsigned, 4>> Groups;
+
+ DenseMap<MachineInstr *, unsigned> Pos;
+ unsigned Idx = 0;
+ for (MachineInstr &MI : MBB.instrs()) {
+ Pos[&MI] = Idx++;
+ unsigned Opc = MI.getOpcode();
+ if (Opc != AArch64::ADDXri && Opc != AArch64::SUBXri)
+ continue;
+ if (!MI.getOperand(2).isImm() || !MI.getOperand(3).isImm() ||
+ MI.getOperand(3).getImm() != 0) // shift must be 0 (no LSL #12)
+ continue;
+ Register SrcReg = MI.getOperand(1).getReg();
+ Register BaseReg = MI.getOperand(0).getReg();
+ if (!SrcReg.isVirtual() || !BaseReg.isVirtual() ||
+ !MRI->hasOneUse(BaseReg)) // secondary def is erased below
+ continue;
+ MachineInstr &User = *MRI->use_instr_begin(BaseReg);
+ if (!User.mayLoadOrStore() || AArch64InstrInfo::isPairedLdSt(User) ||
+ AArch64InstrInfo::isPreLdSt(User) || // different operand layout
+ TII->hasUnscaledLdStOffset(User) || // rewrite below assumes scaled
+ !AArch64InstrInfo::getLdStOffsetOp(User).isImm())
+ continue;
+ const MachineOperand &BaseOp = AArch64InstrInfo::getLdStBaseOp(User);
+ if (!BaseOp.isReg() || BaseOp.getReg() != BaseReg)
+ continue;
+ unsigned CIdx = Cands.size();
+ Cands.push_back({&MI, SrcReg, Opc, MI.getOperand(2).getImm(), BaseReg,
+ &User, TII->getMemScale(User),
+ AArch64InstrInfo::getLdStOffsetOp(User).getImm()});
+ Groups[{SrcReg, Opc}].push_back(CIdx);
+ }
+
+ auto Eff = [](const Cand &C) {
+ return C.Opc == AArch64::ADDXri ? C.C : -C.C;
+ };
+
+ for (auto &Group : Groups) {
+ auto &Idxs = Group.second;
+ if (Idxs.size() < 2)
+ continue;
+ unsigned PrimaryIdx = Idxs[0];
+ for (unsigned i : Idxs)
+ if (Eff(Cands[i]) < Eff(Cands[PrimaryIdx]))
+ PrimaryIdx = i;
+ const Cand &Primary = Cands[PrimaryIdx];
+ Register PrimaryBaseReg = Primary.BaseReg;
+ MachineInstr *PrimaryDef = Primary.DefMI;
+
+ for (unsigned i : Idxs) {
+ if (i == PrimaryIdx)
+ continue;
+ Cand &Sec = Cands[i];
+ int64_t Delta = Eff(Sec) - Eff(Primary);
+ if (Delta % Sec.Scale != 0)
+ continue;
+ int64_t NewOff = Sec.OldOff + Delta / Sec.Scale;
+ if (NewOff < 0 || NewOff > 0xFFF)
+ continue;
+ if (Pos[PrimaryDef] >= Pos[Sec.UserMI])
+ continue;
+ bool IsPairOrPre = AArch64InstrInfo::isPairedLdSt(*Sec.UserMI) ||
+ AArch64InstrInfo::isPreLdSt(*Sec.UserMI);
+ unsigned BaseIdx = IsPairOrPre ? 2 : 1;
+ unsigned OffIdx = IsPairOrPre ? 3 : 2;
+ MachineOperand &BaseOp = Sec.UserMI->getOperand(BaseIdx);
+ BaseOp.setReg(PrimaryBaseReg);
+ BaseOp.setIsKill(false);
+ Sec.UserMI->getOperand(OffIdx).setImm(NewOff);
+ for (MachineInstr &UseMI : MRI->use_instructions(PrimaryBaseReg))
+ for (MachineOperand &MO : UseMI.operands())
+ if (MO.isReg() && MO.getReg() == PrimaryBaseReg)
+ MO.setIsKill(false);
+ LLVM_DEBUG(dbgs() << "Coalesced base address materialization "
+ << *Sec.DefMI << " into: " << *PrimaryDef);
+ Sec.DefMI->eraseFromParent();
+ Changed = true;
+ }
+ }
+ return Changed;
+}
+
bool AArch64MIPeepholeOptImpl::run(MachineFunction &MF) {
TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
TRI = static_cast<const AArch64RegisterInfo *>(
@@ -968,6 +1077,7 @@ bool AArch64MIPeepholeOptImpl::run(MachineFunction &MF) {
bool Changed = false;
for (MachineBasicBlock &MBB : MF) {
+ Changed |= shareBaseAddresses(MBB);
for (MachineInstr &MI : make_early_inc_range(MBB)) {
switch (MI.getOpcode()) {
default:
diff --git a/llvm/test/CodeGen/AArch64/base-address-cse.ll b/llvm/test/CodeGen/AArch64/base-address-cse.ll
new file mode 100644
index 0000000000000..07b7495062a17
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/base-address-cse.ll
@@ -0,0 +1,207 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs < %s | FileCheck %s --check-prefix=ENABLED
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs -aarch64-base-address-cse=0 < %s | FileCheck %s --check-prefix=NOBASECSE
+;
+; End-to-end tests for the AArch64 base-address CSE peephole (item 8 in
+; AArch64MIPeepholeOpt). When ISel materializes a per-access SUBXri/ADDXri
+; base for far offsets it cannot fold into a single immediate, this pass
+; coalesces sibling materializations sharing a common source so that the
+; downstream load/store optimizer can form LDP/STP.
+;
+; The cases below use NEGATIVE far offsets, which (unlike positive far offsets)
+; cannot be expressed as a single unsigned scaled immediate and therefore
+; require base-address CSE to pair. With the pass disabled (-aarch64-base-address-cse=0,
+; NOBASECSE) the two accesses stay as separate sub+ldr/str with no LDP/STP.
+
+define void @ldp_neg_far_offset_i32(ptr %p) {
+; ENABLED-LABEL: ldp_neg_far_offset_i32:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #400
+; ENABLED-NEXT: ldp w9, w8, [x8]
+; ENABLED-NEXT: str w9, [x8]
+; ENABLED-NEXT: str w8, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: ldp_neg_far_offset_i32:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #400
+; NOBASECSE-NEXT: sub x9, x0, #396
+; NOBASECSE-NEXT: ldr w8, [x8]
+; NOBASECSE-NEXT: ldr w9, [x9]
+; NOBASECSE-NEXT: str w8, [x8]
+; NOBASECSE-NEXT: str w9, [x8]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr i32, ptr %p, i64 -100
+ %gep1 = getelementptr i32, ptr %p, i64 -99
+ %v0 = load i32, ptr %gep0
+ %v1 = load i32, ptr %gep1
+ store volatile i32 %v0, ptr poison
+ store volatile i32 %v1, ptr poison
+ ret void
+}
+
+define void @ldp_neg_far_offset_i64(ptr %p) {
+; ENABLED-LABEL: ldp_neg_far_offset_i64:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #800
+; ENABLED-NEXT: ldp x9, x8, [x8]
+; ENABLED-NEXT: str x9, [x8]
+; ENABLED-NEXT: str x8, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: ldp_neg_far_offset_i64:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #800
+; NOBASECSE-NEXT: sub x9, x0, #792
+; NOBASECSE-NEXT: ldr x8, [x8]
+; NOBASECSE-NEXT: ldr x9, [x9]
+; NOBASECSE-NEXT: str x8, [x8]
+; NOBASECSE-NEXT: str x9, [x8]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr i64, ptr %p, i64 -100
+ %gep1 = getelementptr i64, ptr %p, i64 -99
+ %v0 = load i64, ptr %gep0
+ %v1 = load i64, ptr %gep1
+ store volatile i64 %v0, ptr poison
+ store volatile i64 %v1, ptr poison
+ ret void
+}
+
+define void @ldp_neg_far_offset_q(ptr %p) {
+; ENABLED-LABEL: ldp_neg_far_offset_q:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #1600
+; ENABLED-NEXT: ldp q0, q1, [x8]
+; ENABLED-NEXT: str q0, [x8]
+; ENABLED-NEXT: str q1, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: ldp_neg_far_offset_q:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #1600
+; NOBASECSE-NEXT: sub x9, x0, #1584
+; NOBASECSE-NEXT: ldr q0, [x8]
+; NOBASECSE-NEXT: ldr q1, [x9]
+; NOBASECSE-NEXT: str q0, [x8]
+; NOBASECSE-NEXT: str q1, [x8]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr <2 x i64>, ptr %p, i64 -100
+ %gep1 = getelementptr <2 x i64>, ptr %p, i64 -99
+ %v0 = load <2 x i64>, ptr %gep0
+ %v1 = load <2 x i64>, ptr %gep1
+ store volatile <2 x i64> %v0, ptr poison
+ store volatile <2 x i64> %v1, ptr poison
+ ret void
+}
+
+define void @ldp_neg_far_offset_large_i64(ptr %p) {
+; Offset = -500 * 8 = -4000 bytes (fits in shift=0 SUBXri, <= 4095).
+; ENABLED-LABEL: ldp_neg_far_offset_large_i64:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #4000
+; ENABLED-NEXT: ldp x9, x8, [x8]
+; ENABLED-NEXT: str x9, [x8]
+; ENABLED-NEXT: str x8, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: ldp_neg_far_offset_large_i64:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #4000
+; NOBASECSE-NEXT: sub x9, x0, #3992
+; NOBASECSE-NEXT: ldr x8, [x8]
+; NOBASECSE-NEXT: ldr x9, [x9]
+; NOBASECSE-NEXT: str x8, [x8]
+; NOBASECSE-NEXT: str x9, [x8]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr i64, ptr %p, i64 -500
+ %gep1 = getelementptr i64, ptr %p, i64 -499
+ %v0 = load i64, ptr %gep0
+ %v1 = load i64, ptr %gep1
+ store volatile i64 %v0, ptr poison
+ store volatile i64 %v1, ptr poison
+ ret void
+}
+
+define void @stp_neg_far_offset_i32(ptr %p, i32 %v0, i32 %v1) {
+; ENABLED-LABEL: stp_neg_far_offset_i32:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #400
+; ENABLED-NEXT: stp w1, w2, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: stp_neg_far_offset_i32:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #400
+; NOBASECSE-NEXT: sub x9, x0, #396
+; NOBASECSE-NEXT: str w1, [x8]
+; NOBASECSE-NEXT: str w2, [x9]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr i32, ptr %p, i64 -100
+ %gep1 = getelementptr i32, ptr %p, i64 -99
+ store i32 %v0, ptr %gep0
+ store i32 %v1, ptr %gep1
+ ret void
+}
+
+define void @stp_neg_far_offset_i64(ptr %p, i64 %v0, i64 %v1) {
+; ENABLED-LABEL: stp_neg_far_offset_i64:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #800
+; ENABLED-NEXT: stp x1, x2, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: stp_neg_far_offset_i64:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #800
+; NOBASECSE-NEXT: sub x9, x0, #792
+; NOBASECSE-NEXT: str x1, [x8]
+; NOBASECSE-NEXT: str x2, [x9]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr i64, ptr %p, i64 -100
+ %gep1 = getelementptr i64, ptr %p, i64 -99
+ store i64 %v0, ptr %gep0
+ store i64 %v1, ptr %gep1
+ ret void
+}
+
+define void @stp_neg_far_offset_q(ptr %p, <2 x i64> %v0, <2 x i64> %v1) {
+; ENABLED-LABEL: stp_neg_far_offset_q:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #1600
+; ENABLED-NEXT: stp q0, q1, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: stp_neg_far_offset_q:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #1600
+; NOBASECSE-NEXT: sub x9, x0, #1584
+; NOBASECSE-NEXT: str q0, [x8]
+; NOBASECSE-NEXT: str q1, [x9]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr <2 x i64>, ptr %p, i64 -100
+ %gep1 = getelementptr <2 x i64>, ptr %p, i64 -99
+ store <2 x i64> %v0, ptr %gep0
+ store <2 x i64> %v1, ptr %gep1
+ ret void
+}
+
+define void @stp_neg_far_offset_large_i64(ptr %p, i64 %v0, i64 %v1) {
+; ENABLED-LABEL: stp_neg_far_offset_large_i64:
+; ENABLED: // %bb.0:
+; ENABLED-NEXT: sub x8, x0, #4000
+; ENABLED-NEXT: stp x1, x2, [x8]
+; ENABLED-NEXT: ret
+;
+; NOBASECSE-LABEL: stp_neg_far_offset_large_i64:
+; NOBASECSE: // %bb.0:
+; NOBASECSE-NEXT: sub x8, x0, #4000
+; NOBASECSE-NEXT: sub x9, x0, #3992
+; NOBASECSE-NEXT: str x1, [x8]
+; NOBASECSE-NEXT: str x2, [x9]
+; NOBASECSE-NEXT: ret
+ %gep0 = getelementptr i64, ptr %p, i64 -500
+ %gep1 = getelementptr i64, ptr %p, i64 -499
+ store i64 %v0, ptr %gep0
+ store i64 %v1, ptr %gep1
+ ret void
+}
diff --git a/llvm/test/CodeGen/AArch64/base-address-cse.mir b/llvm/test/CodeGen/AArch64/base-address-cse.mir
new file mode 100644
index 0000000000000..0c0d90d3a2451
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/base-address-cse.mir
@@ -0,0 +1,101 @@
+# RUN: llc -mtriple=aarch64 -run-pass=aarch64-mi-peephole-opt \
+# RUN: -verify-machineinstrs -o - %s | FileCheck %s --check-prefix=SHARED
+# RUN: llc -mtriple=aarch64 -run-pass=aarch64-mi-peephole-opt \
+# RUN: -aarch64-base-address-cse=0 -o - %s | FileCheck %s --check-prefix=NOBASECSE
+
+--- |
+ define void @share_sub_i32(ptr %p) { ret void }
+ define void @share_sub_i32_3sibling(ptr %p) { ret void }
+ define void @share_add_i64(ptr %p) { ret void }
+...
+---
+name: share_sub_i32
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+ %0:gpr64common = COPY $x0
+ %1:gpr64common = SUBXri %0, 400, 0
+ %2:gpr64common = SUBXri %0, 396, 0
+ %3:gpr32 = LDRWui killed %1, 0
+ %4:gpr32 = LDRWui killed %2, 0
+ $w0 = COPY %3
+ $w1 = COPY %4
+ RET_ReallyLR
+
+# SHARED-LABEL: name: share_sub_i32
+# SHARED: %1:gpr64common = SUBXri %0, 400, 0
+# SHARED-NOT: SUBXri %0, 396, 0
+# SHARED: %3:gpr32 = LDRWui %1, 0
+# SHARED: %4:gpr32 = LDRWui %1, 1
+# SHARED-NOT: SUBXri
+
+# NOBASECSE-LABEL: name: share_sub_i32
+# NOBASECSE: %1:gpr64common = SUBXri %0, 400, 0
+# NOBASECSE: %2:gpr64common = SUBXri %0, 396, 0
+# NOBASECSE: %3:gpr32 = LDRWui killed %1, 0
+# NOBASECSE: %4:gpr32 = LDRWui killed %2, 0
+
+...
+---
+name: share_sub_i32_3sibling
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+ %0:gpr64common = COPY $x0
+ %1:gpr64common = SUBXri %0, 400, 0
+ %2:gpr64common = SUBXri %0, 396, 0
+ %3:gpr64common = SUBXri %0, 392, 0
+ %4:gpr32 = LDRWui killed %1, 0
+ %5:gpr32 = LDRWui killed %2, 0
+ %6:gpr32 = LDRWui killed %3, 0
+ $w0 = COPY %4
+ $w1 = COPY %5
+ $w2 = COPY %6
+ RET_ReallyLR
+
+# SHARED-LABEL: name: share_sub_i32_3sibling
+# SHARED: %1:gpr64common = SUBXri %0, 400, 0
+# SHARED: %4:gpr32 = LDRWui %1, 0
+# SHARED: %5:gpr32 = LDRWui %1, 1
+# SHARED: %6:gpr32 = LDRWui %1, 2
+# SHARED-NOT: SUBXri %0, 396, 0
+# SHARED-NOT: SUBXri %0, 392, 0
+
+# NOBASECSE-LABEL: name: share_sub_i32_3sibling
+# NOBASECSE: %1:gpr64common = SUBXri %0, 400, 0
+# NOBASECSE: %2:gpr64common = SUBXri %0, 396, 0
+# NOBASECSE: %3:gpr64common = SUBXri %0, 392, 0
+# NOBASECSE: %4:gpr32 = LDRWui killed %1, 0
+# NOBASECSE: %5:gpr32 = LDRWui killed %2, 0
+# NOBASECSE: %6:gpr32 = LDRWui killed %3, 0
+
+...
+---
+name: share_add_i64
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+ %0:gpr64common = COPY $x0
+ %1:gpr64common = ADDXri %0, 800, 0
+ %2:gpr64common = ADDXri %0, 808, 0
+ %3:gpr64 = LDRXui killed %1, 0
+ %4:gpr64 = LDRXui killed %2, 0
+ $x0 = COPY %3
+ $x1 = COPY %4
+ RET_ReallyLR
+
+# SHARED-LABEL: name: share_add_i64
+# SHARED: %1:gpr64common = ADDXri %0, 800, 0
+# SHARED-NOT: ADDXri %0, 808, 0
+# SHARED: %3:gpr64 = LDRXui %1, 0
+# SHARED: %4:gpr64 = LDRXui %1, 1
+# SHARED-NOT: ADDXri
+
+# NOBASECSE-LABEL: name: share_add_i64
+# NOBASECSE: %1:gpr64common = ADDXri %0, 800, 0
+# NOBASECSE: %2:gpr64common = ADDXri %0, 808, 0
+# NOBASECSE: %3:gpr64 = LDRXui killed %1, 0
+# NOBASECSE: %4:gpr64 = LDRXui killed %2, 0
More information about the llvm-commits
mailing list