[llvm-branch-commits] [llvm] [CodeGen] Fold every operand of a register into an inline asm (PR #235631)
Bill Wendling via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Oct 26 00:34:01 PDT 2026
https://github.com/isanbard created https://github.com/llvm/llvm-project/pull/235631
The spill weights took a register to be foldable into an asm if any one of its operands there was foldable, while the folder needs all of them to be. One value passed to an "rm" and an "r" operand could then get spilled, not folded, and the asm ran out of registers. Add MachineInstr::mayFoldInlineAsmReg(), true if every operand of a register in an asm can be folded, and use it in the folder and CalcSpillWeights.
The folder now folds every operand of the register, including an undef use that InlineSpiller leaves out of the operands it passes, which was left behind still referring to the spilled register.
Nothing in tree marks an inline asm operand foldable until #229632, so the tests set the "foldable" flag in MIR. Also define ALL_GPRS in greedy-inline-asm-fold.mir, and drop -verify-machineinstrs, which llc runs anyway.
Assisted-by: Claude Opus 5.5
>From 579870ae81f02fcc67c7bc998a486e03ab8307c4 Mon Sep 17 00:00:00 2001
From: Bill Wendling <isanbard at gmail.com>
Date: Mon, 26 Oct 2026 00:15:59 -0700
Subject: [PATCH] [CodeGen] Fold every operand of a register into an inline asm
The spill weights took a register to be foldable into an asm if any one
of its operands there was foldable, while the folder needs all of them
to be. One value passed to an "rm" and an "r" operand could then get
spilled, not folded, and the asm ran out of registers. Add
MachineInstr::mayFoldInlineAsmReg(), true if every operand of a register
in an asm can be folded, and use it in the folder and CalcSpillWeights.
The folder now folds every operand of the register, including an undef
use that InlineSpiller leaves out of the operands it passes, which was
left behind still referring to the spilled register.
Nothing in tree marks an inline asm operand foldable until #229632, so
the tests set the "foldable" flag in MIR. Also define ALL_GPRS in
greedy-inline-asm-fold.mir, and drop -verify-machineinstrs, which llc
runs anyway.
Assisted-by: Claude Opus 5.5
---
llvm/include/llvm/CodeGen/MachineInstr.h | 7 ++
llvm/lib/CodeGen/CalcSpillWeights.cpp | 12 ++-
llvm/lib/CodeGen/MachineInstr.cpp | 19 ++++
llvm/lib/CodeGen/TargetInstrInfo.cpp | 85 +++++++++-------
.../CodeGen/X86/greedy-inline-asm-fold.mir | 98 +++++++++++++++++--
5 files changed, 171 insertions(+), 50 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 731b92f555f4c8..dd689cf280f371 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1444,6 +1444,13 @@ class MachineInstr
/// beginning of the stack slot.
LLVM_ABI bool mayFoldInlineAsmRegOp(unsigned OpId) const;
+ /// Returns true if \p Reg can be folded to its stack slot in this inline
+ /// asm: the asm reads or writes Reg, and every operand of Reg can be folded
+ /// (see mayFoldInlineAsmRegOp()). A use tied to a def is folded along with
+ /// the def, so it isn't checked on its own. The register allocator then
+ /// needs no register for Reg here.
+ LLVM_ABI bool mayFoldInlineAsmReg(Register Reg) const;
+
LLVM_ABI bool isStackAligningInlineAsm() const;
LLVM_ABI InlineAsm::AsmDialect getInlineAsmDialect() const;
diff --git a/llvm/lib/CodeGen/CalcSpillWeights.cpp b/llvm/lib/CodeGen/CalcSpillWeights.cpp
index e958acdcb064ab..26d265c2a986e8 100644
--- a/llvm/lib/CodeGen/CalcSpillWeights.cpp
+++ b/llvm/lib/CodeGen/CalcSpillWeights.cpp
@@ -226,13 +226,17 @@ void VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &LI) {
LI.setWeight(Weight);
}
+/// Return true if the inline asm \p MI can access \p Reg in Reg's stack slot,
+/// which the register allocator would fold its operands to if it spills Reg.
+static bool canMemFoldInlineAsm(const MachineInstr &MI, Register Reg) {
+ return MI.isInlineAsm() && MI.mayFoldInlineAsmReg(Reg);
+}
+
static bool canMemFoldInlineAsm(LiveInterval &LI,
const MachineRegisterInfo &MRI) {
- for (const MachineOperand &MO : MRI.reg_operands(LI.reg())) {
- const MachineInstr *MI = MO.getParent();
- if (MI->isInlineAsm() && MI->mayFoldInlineAsmRegOp(MI->getOperandNo(&MO)))
+ for (const MachineInstr &MI : MRI.reg_nodbg_instructions(LI.reg()))
+ if (canMemFoldInlineAsm(MI, LI.reg()))
return true;
- }
return false;
}
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 08150b5f69b693..23f5170ea66d20 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2817,6 +2817,25 @@ bool MachineInstr::mayFoldInlineAsmRegOp(unsigned OpId) const {
return false;
}
+bool MachineInstr::mayFoldInlineAsmReg(Register Reg) const {
+ assert(isInlineAsm() && "should only be used on inline asm");
+
+ bool Accessed = false;
+ for (unsigned I = InlineAsm::MIOp_FirstOperand, E = getNumOperands(); I != E;
+ ++I) {
+ const MachineOperand &MO = getOperand(I);
+ if (!MO.isReg() || MO.getReg() != Reg || isRegTiedToDefOperand(I))
+ continue;
+
+ if (!mayFoldInlineAsmRegOp(I))
+ return false;
+
+ Accessed |= MO.isDef() || MO.readsReg();
+ }
+
+ return Accessed;
+}
+
unsigned MachineInstr::removePHIIncomingValueFor(const MachineBasicBlock &MBB) {
assert(isPHI());
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 08955eda50cb1e..47bfa9cdc94610 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -650,10 +650,9 @@ static MachineInstr *foldPatchpoint(MachineFunction &MF, MachineInstr &MI,
return NewMI;
}
-/// Rewrite the register operands \p Ops of the inline asm \p MI to refer to
-/// stack slot \p FI. The use tied to a folded def is folded along with it,
-/// since the two name a single location.
-static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<unsigned> Ops,
+/// Rewrite each register operand of the inline asm \p MI that's set in \p Fold
+/// (indexed by operand number) to refer to stack slot \p FI.
+static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<bool> Fold,
int FI, const TargetInstrInfo &TII) {
SmallVector<MachineOperand, 5> MemOps;
TII.getFrameIndexOperands(MemOps, FI);
@@ -661,12 +660,11 @@ static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<unsigned> Ops,
InlineAsm::Flag MemFlag(InlineAsm::Kind::Mem, MemOps.size());
MemFlag.setMemConstraint(InlineAsm::ConstraintCode::m);
- // Find the uses to fold along with their defs, and the ties to keep. A
- // folded operand becomes MemOps.size() operands, moving every later one, and
- // MachineInstr can't move a tied operand. So untie everything (untying a use
- // also unties its def), re-add the operands from the first folded one on,
- // and re-tie the pairs that are still registers at their new positions.
- SmallVector<unsigned, 4> FoldOps(Ops);
+ // A folded operand becomes the operands of a memory reference, moving every
+ // later one, and MachineInstr can't move a tied operand. So untie everything
+ // (untying a use also unties its def), re-add the operands from the first
+ // folded one on, and re-tie the pairs that are still registers at their new
+ // positions.
SmallVector<std::pair<unsigned, unsigned>, 4> Ties;
for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
I != E; ++I) {
@@ -675,13 +673,14 @@ static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<unsigned> Ops,
continue;
MI.untieRegOperand(I);
- if (is_contained(Ops, DefIdx))
- FoldOps.push_back(I);
- else
+ if (!Fold[I])
Ties.emplace_back(DefIdx, I);
}
- unsigned First = *llvm::min_element(FoldOps);
+ unsigned First = InlineAsm::MIOp_FirstOperand;
+ while (!Fold[First])
+ ++First;
+
SmallVector<MachineOperand, 16> Tail(MI.operands_begin() + First,
MI.operands_end());
while (MI.getNumOperands() > First)
@@ -690,7 +689,7 @@ static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<unsigned> Ops,
SmallVector<unsigned, 16> NewIdx;
for (auto [I, MO] : enumerate(Tail)) {
NewIdx.push_back(MI.getNumOperands());
- if (!is_contained(FoldOps, First + I)) {
+ if (!Fold[First + I]) {
MI.addOperand(MO);
continue;
}
@@ -717,40 +716,52 @@ static MachineInstr *foldInlineAsmMemOperand(MachineInstr &MI,
ArrayRef<unsigned> Ops, int FI,
const TargetInstrInfo &TII) {
assert(MI.isInlineAsm() && "wrong opcode");
-
- // Sanity check that there are operands to fold.
if (Ops.empty())
return nullptr;
- // Every operand in Ops holds the same register (e.g. one value passed to two
- // "rm" operands), so they all fold to the same stack slot. The asm reads
- // the slot through a use, and through a def tied to a use, which need not
- // be the same virtual register when the allocator lowers ties itself. In
- // that case the caller must store the tied use's value into the slot before
- // the asm.
- bool Reads = false;
- bool Writes = false;
+ // A tied use is only ever folded along with its def.
+ Register Reg = MI.getOperand(Ops[0]).getReg();
for (unsigned Op : Ops) {
assert(Op && "should never be first operand");
- const MachineOperand &MO = MI.getOperand(Op);
- assert(MO.isReg() && "shouldn't be folding non-reg operands");
- assert(MO.getReg() == MI.getOperand(Ops[0]).getReg() &&
+ assert(MI.getOperand(Op).isReg() && MI.getOperand(Op).getReg() == Reg &&
"folded operands must hold the same register");
-
- // A tied use is only ever folded along with its def.
- if (!MI.mayFoldInlineAsmRegOp(Op))
+ if (MI.isRegTiedToDefOperand(Op))
return nullptr;
+ }
+
+ // The asm can't refer to both Reg and its stack slot, so every operand of
+ // Reg is folded (e.g. one value passed to two "rm" operands), including any
+ // the caller left out, such as an undef use.
+ if (!MI.mayFoldInlineAsmReg(Reg))
+ return nullptr;
+
+ // Find the operands to fold. A use tied to another register's def keeps its
+ // register. The use tied to one of Reg's defs is folded along with the def,
+ // and reads the def's slot. That use need not hold Reg when the allocator
+ // lowers ties itself; the caller must then store the tied use's value into
+ // the slot before the asm.
+ SmallVector<bool, 16> Fold(MI.getNumOperands());
+ bool Reads = false;
+ bool Writes = false;
+ for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
+ I != E; ++I) {
+ const MachineOperand &MO = MI.getOperand(I);
+ if (!MO.isReg())
+ continue;
+ unsigned DefIdx;
+ const MachineOperand &SlotMO =
+ MI.isRegTiedToDefOperand(I, &DefIdx) ? MI.getOperand(DefIdx) : MO;
+ if (SlotMO.getReg() != Reg)
+ continue;
+
+ Fold[I] = true;
Reads |= MO.readsReg();
- if (MO.isDef()) {
- Writes = true;
- Reads |=
- MO.isTied() && MI.getOperand(MI.findTiedOperandIdx(Op)).readsReg();
- }
+ Writes |= MO.isDef();
}
MachineInstr &NewMI = TII.duplicate(*MI.getParent(), MI.getIterator(), MI);
- foldInlineAsmMemOperands(NewMI, Ops, FI, TII);
+ foldInlineAsmMemOperands(NewMI, Fold, FI, TII);
// Update mayload/maystore metadata, and memoperands.
MachineOperand &ExtraMO = NewMI.getOperand(InlineAsm::MIOp_ExtraInfo);
diff --git a/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir b/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir
index eceb4d4d4bc37c..deec6136d87a53 100644
--- a/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir
+++ b/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir
@@ -1,18 +1,17 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=greedy \
-# RUN: -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=greedy %s -o - \
+# RUN: | FileCheck %s
# The greedy register allocator spills a value used by a foldable ("rm")
-# inline asm operand by folding the operand to the value's stack slot. The
-# clobbers below leave six GPRs, and the asm needs seven registers, so one
-# value is spilled. Folding replaces an operand with the five operands of a
-# memory reference, moving every operand after it, which must keep any tied
-# operands tied.
+# inline asm operand by folding the operand to the value's stack slot.
+# Folding replaces an operand with the five operands of a memory reference,
+# moving every operand after it, which must keep any tied operands tied.
#
# Each test is derived from the C function and inline asm statement in its
-# comment, where CLOBBERS is:
+# comment, where CLOBBERS leaves six GPRs, and ALL_GPRS none:
#
-# "rax", "rbx", "rbp", "r10", "r11", "r12", "r13", "r14", "r15"
+# CLOBBERS: "rax", "rbx", "rbp", "r10", "r11", "r12", "r13", "r14", "r15"
+# ALL_GPRS: CLOBBERS, "rcx", "rdx", "rsi", "rdi", "r8", "r9"
---
# One value passed to two "rm" operands: both operands fold to the same stack
@@ -374,3 +373,84 @@ body: |
INLINEASM &"", sideeffect attdialect, reguse:GR64 foldable, %6, reguse:GR64 foldable, %6, reguse:GR64, %0, reguse:GR64, %1, reguse:GR64, %2, reguse:GR64, %3, reguse:GR64, %4, reguse:GR64, %5, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
RET 0
...
+---
+# One value passed to an "rm" and an "r" operand isn't folded, since the "r"
+# operand needs it in a register anyway, so the allocator must not count on
+# spilling it: %h, which only lives across the asm, is spilled instead.
+#
+# long rm_and_r_same_value(long a, long b, long c, long d, long e, long f,
+# long g) {
+# asm volatile("" : : : ALL_GPRS);
+# long h = f + 8;
+# asm volatile("" : : "rm"(g), "r"(g), "r"(a), "r"(b), "r"(c), "r"(d),
+# "r"(e) : CLOBBERS);
+# return h;
+# }
+name: rm_and_r_same_value
+tracksRegLiveness: true
+fixedStack:
+ - { id: 0, size: 8, alignment: 16, isImmutable: true }
+body: |
+ bb.0:
+ liveins: $rdi, $rsi, $rdx, $rcx, $r8, $r9
+ ; CHECK-LABEL: name: rm_and_r_same_value
+ ; CHECK: liveins: $rdi, $rsi, $rdx, $rcx, $r8, $r9
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rdi :: (store (s64) into %stack.0)
+ ; CHECK-NEXT: MOV64mr %stack.1, 1, $noreg, 0, $noreg, $rsi :: (store (s64) into %stack.1)
+ ; CHECK-NEXT: MOV64mr %stack.2, 1, $noreg, 0, $noreg, $rdx :: (store (s64) into %stack.2)
+ ; CHECK-NEXT: MOV64mr %stack.3, 1, $noreg, 0, $noreg, $rcx :: (store (s64) into %stack.3)
+ ; CHECK-NEXT: MOV64mr %stack.4, 1, $noreg, 0, $noreg, $r8 :: (store (s64) into %stack.4)
+ ; CHECK-NEXT: MOV64mr %stack.6, 1, $noreg, 0, $noreg, $r9 :: (store (s64) into %stack.6)
+ ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rcx, clobber, implicit-def dead early-clobber $rdx, clobber, implicit-def dead early-clobber $rsi, clobber, implicit-def dead early-clobber $rdi, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r8, clobber, implicit-def dead early-clobber $r9, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ ; CHECK-NEXT: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.6, 1, $noreg, 0, $noreg :: (load (s64) from %stack.6)
+ ; CHECK-NEXT: [[LEA64r:%[0-9]+]]:gr64 = LEA64r [[MOV64rm]], 1, $noreg, 8, $noreg
+ ; CHECK-NEXT: MOV64mr %stack.5, 1, $noreg, 0, $noreg, [[LEA64r]] :: (store (s64) into %stack.5)
+ ; CHECK-NEXT: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %fixed-stack.0, align 16)
+ ; CHECK-NEXT: [[MOV64rm2:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
+ ; CHECK-NEXT: [[MOV64rm3:%[0-9]+]]:gr64 = MOV64rm %stack.1, 1, $noreg, 0, $noreg :: (load (s64) from %stack.1)
+ ; CHECK-NEXT: [[MOV64rm4:%[0-9]+]]:gr64 = MOV64rm %stack.2, 1, $noreg, 0, $noreg :: (load (s64) from %stack.2)
+ ; CHECK-NEXT: [[MOV64rm5:%[0-9]+]]:gr64 = MOV64rm %stack.3, 1, $noreg, 0, $noreg :: (load (s64) from %stack.3)
+ ; CHECK-NEXT: [[MOV64rm6:%[0-9]+]]:gr64 = MOV64rm %stack.4, 1, $noreg, 0, $noreg :: (load (s64) from %stack.4)
+ ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, reguse:GR64 foldable, [[MOV64rm1]], reguse:GR64, [[MOV64rm1]], reguse:GR64, [[MOV64rm2]], reguse:GR64, [[MOV64rm3]], reguse:GR64, [[MOV64rm4]], reguse:GR64, [[MOV64rm5]], reguse:GR64, [[MOV64rm6]], clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ ; CHECK-NEXT: $rax = MOV64rm %stack.5, 1, $noreg, 0, $noreg :: (load (s64) from %stack.5)
+ ; CHECK-NEXT: RET 0, $rax
+ %0:gr64 = COPY $rdi
+ %1:gr64 = COPY $rsi
+ %2:gr64 = COPY $rdx
+ %3:gr64 = COPY $rcx
+ %4:gr64 = COPY $r8
+ %5:gr64 = COPY $r9
+ INLINEASM &"", sideeffect attdialect, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rcx, clobber, implicit-def dead early-clobber $rdx, clobber, implicit-def dead early-clobber $rsi, clobber, implicit-def dead early-clobber $rdi, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r8, clobber, implicit-def dead early-clobber $r9, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ %7:gr64 = LEA64r %5, 1, $noreg, 8, $noreg
+ %6:gr64 = MOV64rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %fixed-stack.0, align 16)
+ INLINEASM &"", sideeffect attdialect, reguse:GR64 foldable, %6, reguse:GR64, %6, reguse:GR64, %0, reguse:GR64, %1, reguse:GR64, %2, reguse:GR64, %3, reguse:GR64, %4, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ $rax = COPY %7
+ RET 0, $rax
+...
+---
+# An undef use of a folded register is folded along with its other operands,
+# so that none is left referring to the register. The second asm clobbers
+# every GPR, so its operands must be folded. The third asm's undef use can't
+# be folded, so nothing is, and it gets a reload. (There is no C source:
+# instruction selection doesn't emit undef inline asm operands.)
+name: rm_undef_use
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $rdi
+ ; CHECK-LABEL: name: rm_undef_use
+ ; CHECK: liveins: $rdi
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rdi :: (store (s64) into %stack.0)
+ ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rcx, clobber, implicit-def dead early-clobber $rdx, clobber, implicit-def dead early-clobber $rsi, clobber, implicit-def dead early-clobber $rdi, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r8, clobber, implicit-def dead early-clobber $r9, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, mem:m ops:5, %stack.0, 1, $noreg, 0, $noreg, mem:m ops:5, %stack.0, 1, $noreg, 0, $noreg, mem:m ops:5, %stack.0, 1, $noreg, 0, $noreg, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rcx, clobber, implicit-def dead early-clobber $rdx, clobber, implicit-def dead early-clobber $rsi, clobber, implicit-def dead early-clobber $rdi, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r8, clobber, implicit-def dead early-clobber $r9, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15 :: (load (s64) from %stack.0)
+ ; CHECK-NEXT: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
+ ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, reguse:GR64 foldable, [[MOV64rm]], reguse:GR64, undef [[MOV64rm]]
+ ; CHECK-NEXT: RET 0
+ %0:gr64 = COPY $rdi
+ INLINEASM &"", sideeffect attdialect, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rcx, clobber, implicit-def dead early-clobber $rdx, clobber, implicit-def dead early-clobber $rsi, clobber, implicit-def dead early-clobber $rdi, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r8, clobber, implicit-def dead early-clobber $r9, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ INLINEASM &"", sideeffect attdialect, reguse:GR64 foldable, %0, reguse:GR64 foldable, undef %0, reguse:GR64 foldable, %0, clobber, implicit-def dead early-clobber $rax, clobber, implicit-def dead early-clobber $rbx, clobber, implicit-def dead early-clobber $rcx, clobber, implicit-def dead early-clobber $rdx, clobber, implicit-def dead early-clobber $rsi, clobber, implicit-def dead early-clobber $rdi, clobber, implicit-def dead early-clobber $rbp, clobber, implicit-def dead early-clobber $r8, clobber, implicit-def dead early-clobber $r9, clobber, implicit-def dead early-clobber $r10, clobber, implicit-def dead early-clobber $r11, clobber, implicit-def dead early-clobber $r12, clobber, implicit-def dead early-clobber $r13, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15
+ INLINEASM &"", sideeffect attdialect, reguse:GR64 foldable, %0, reguse:GR64, undef %0
+ RET 0
+...
More information about the llvm-branch-commits
mailing list