[llvm-branch-commits] [llvm] [CodeGen] Fold an inline asm subregister operand at its slot offset (PR #235632)
Bill Wendling via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Oct 26 00:34:05 PDT 2026
https://github.com/isanbard created https://github.com/llvm/llvm-project/pull/235632
A stack slot holds the whole register, and a folded operand referred to the start of the slot, so a subregister was folded only if it was at offset 0, and other subregisters got a reload into a register the asm may not have. Coalescing can turn an i686 "rm" byte operand into sub_8bit_hi of a GR32, which is at byte 1. Fold a subregister at its offset in the slot, from getStackSlotRange(), so getFrameIndexOperands() now takes an offset.
Also add a third asm to qm_tied_high_byte, which clobbers every GPR, so that it reaches the folder. Without it, the value is reloaded into a register that's free at the second asm.
Assisted-by: Claude Opus 5.5
>From 1bc587dfe5def971b7b52f3818a4b76b2560e55f Mon Sep 17 00:00:00 2001
From: Bill Wendling <isanbard at gmail.com>
Date: Mon, 26 Oct 2026 00:18:20 -0700
Subject: [PATCH] [CodeGen] Fold an inline asm subregister operand at its slot
offset
A stack slot holds the whole register, and a folded operand referred to
the start of the slot, so a subregister was folded only if it was at
offset 0, and other subregisters got a reload into a register the asm
may not have. Coalescing can turn an i686 "rm" byte operand into
sub_8bit_hi of a GR32, which is at byte 1. Fold a subregister at its
offset in the slot, from getStackSlotRange(), so
getFrameIndexOperands() now takes an offset.
Also add a third asm to qm_tied_high_byte, which clobbers every GPR, so
that it reaches the folder. Without it, the value is reloaded into a
register that's free at the second asm.
Assisted-by: Claude Opus 5.5
---
llvm/include/llvm/CodeGen/MachineInstr.h | 4 +-
llvm/include/llvm/CodeGen/TargetInstrInfo.h | 5 +-
llvm/lib/CodeGen/MachineInstr.cpp | 39 ++++++-----
llvm/lib/CodeGen/TargetInstrInfo.cpp | 65 +++++++++++--------
llvm/lib/Target/X86/X86InstrInfo.cpp | 3 +-
llvm/lib/Target/X86/X86InstrInfo.h | 4 +-
.../CodeGen/X86/greedy-inline-asm-fold.mir | 36 +++++-----
7 files changed, 84 insertions(+), 72 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index dd689cf280f371..4185e8739d659b 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1440,8 +1440,8 @@ class MachineInstr
}
/// Returns true if the register operand can be folded with a load or store
/// into a frame index. Does so by checking the InlineAsm::Flag immediate
- /// operand at OpId - 1, and that the register (or subregister) starts at the
- /// beginning of the stack slot.
+ /// operand at OpId - 1, and that the register (or subregister) has a place
+ /// in the register's stack slot.
LLVM_ABI bool mayFoldInlineAsmRegOp(unsigned OpId) const;
/// Returns true if \p Reg can be folded to its stack slot in this inline
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 97baf780275ee3..9bd88d716f4175 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2418,13 +2418,14 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
// Get the call frame size just before MI.
unsigned getCallFrameSizeAt(MachineInstr &MI) const;
- /// Fills in the necessary MachineOperands to refer to a frame index.
+ /// Fills in the necessary MachineOperands to refer to a frame index, plus
+ /// \p Offset bytes.
/// The best way to understand this is to print `asm(""::"m"(x));` after
/// finalize-isel. Example:
/// INLINEASM ... 262190 /* mem:m */, %stack.0.x.addr, 1, $noreg, 0, $noreg
/// we would add placeholders for: ^ ^ ^ ^
virtual void getFrameIndexOperands(SmallVectorImpl<MachineOperand> &Ops,
- int FI) const {
+ int FI, int64_t Offset) const {
llvm_unreachable("unknown number of operands necessary");
}
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 23f5170ea66d20..ed7d88c9935b25 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -2784,37 +2784,36 @@ bool MachineInstr::mayFoldInlineAsmRegOp(unsigned OpId) const {
assert(OpId && "expected non-zero operand id");
assert(isInlineAsm() && "should only be used on inline asm");
- if (!getOperand(OpId).isReg())
- return false;
-
- if (isRegTiedToDefOperand(OpId))
+ const MachineOperand &MO = getOperand(OpId);
+ const MachineOperand &MD = getOperand(OpId - 1);
+ if (!MO.isReg() || !MD.isImm())
return false;
- const MachineOperand &MD = getOperand(OpId - 1);
- if (!MD.isImm())
+ InlineAsm::Flag F(MD.getImm());
+ if (!F.isRegUseKind() && !F.isRegDefKind() && !F.isRegDefEarlyClobberKind())
return false;
// A memory operand replaces exactly one register, so one register of a
// multi-register operand (e.g. an i128 in two GR64s) can't be folded.
- InlineAsm::Flag F(MD.getImm());
- if (F.getNumOperandRegisters() != 1)
+ if (!F.getRegMayBeFolded() || F.getNumOperandRegisters() != 1)
return false;
- // A memory operand refers to the start of the stack slot, which holds the
- // whole register. A subregister is found there only if it's at bit offset 0
- // on a little-endian target; e.g. x86's sub_8bit_hi is at byte 1. (The use
- // tied to a def, which is folded along with it, has the def's subregister.)
- if (unsigned SubReg = getOperand(OpId).getSubReg()) {
+ // A use tied to a def is folded along with the def, not on its own.
+ if (isRegTiedToDefOperand(OpId))
+ return false;
+
+ // The stack slot holds the whole register, so a subregister is folded at
+ // its offset in the slot, if it has one.
+ if (unsigned SubReg = MO.getSubReg()) {
const MachineFunction &MF = *getMF();
- if (!MF.getDataLayout().isLittleEndian() ||
- MF.getSubtarget().getRegisterInfo()->getSubRegIdxOffset(SubReg) != 0)
- return false;
+ unsigned Size, Offset;
+ return MO.getReg().isVirtual() &&
+ MF.getSubtarget().getInstrInfo()->getStackSlotRange(
+ MF.getRegInfo().getRegClass(MO.getReg()), SubReg, Size, Offset,
+ MF);
}
- if (F.isRegUseKind() || F.isRegDefKind() || F.isRegDefEarlyClobberKind())
- return F.getRegMayBeFolded();
-
- return false;
+ return true;
}
bool MachineInstr::mayFoldInlineAsmReg(Register Reg) const {
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 47bfa9cdc94610..5de5fac41b0005 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -650,16 +650,12 @@ static MachineInstr *foldPatchpoint(MachineFunction &MF, MachineInstr &MI,
return NewMI;
}
-/// 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,
+/// Rewrite each register operand of the inline asm \p MI that has an entry in
+/// \p Offsets (indexed by operand number) to refer to stack slot \p FI at
+/// that byte offset.
+static void foldInlineAsmMemOperands(MachineInstr &MI,
+ ArrayRef<std::optional<unsigned>> Offsets,
int FI, const TargetInstrInfo &TII) {
- SmallVector<MachineOperand, 5> MemOps;
- TII.getFrameIndexOperands(MemOps, FI);
- assert(!MemOps.empty() && "getFrameIndexOperands didn't create any operands");
- InlineAsm::Flag MemFlag(InlineAsm::Kind::Mem, MemOps.size());
- MemFlag.setMemConstraint(InlineAsm::ConstraintCode::m);
-
// 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
@@ -673,12 +669,12 @@ static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<bool> Fold,
continue;
MI.untieRegOperand(I);
- if (!Fold[I])
+ if (!Offsets[I])
Ties.emplace_back(DefIdx, I);
}
unsigned First = InlineAsm::MIOp_FirstOperand;
- while (!Fold[First])
+ while (!Offsets[First])
++First;
SmallVector<MachineOperand, 16> Tail(MI.operands_begin() + First,
@@ -689,7 +685,8 @@ static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<bool> Fold,
SmallVector<unsigned, 16> NewIdx;
for (auto [I, MO] : enumerate(Tail)) {
NewIdx.push_back(MI.getNumOperands());
- if (!Fold[First + I]) {
+ std::optional<unsigned> Offset = Offsets[First + I];
+ if (!Offset) {
MI.addOperand(MO);
continue;
}
@@ -699,6 +696,12 @@ static void foldInlineAsmMemOperands(MachineInstr &MI, ArrayRef<bool> Fold,
MachineOperand &FlagMO = MI.getOperand(MI.getNumOperands() - 1);
assert(InlineAsm::Flag(FlagMO.getImm()).getNumOperandRegisters() == 1 &&
"cannot fold one register of a multi-register operand");
+ SmallVector<MachineOperand, 5> MemOps;
+ TII.getFrameIndexOperands(MemOps, FI, *Offset);
+ assert(!MemOps.empty() &&
+ "getFrameIndexOperands didn't create any operands");
+ InlineAsm::Flag MemFlag(InlineAsm::Kind::Mem, MemOps.size());
+ MemFlag.setMemConstraint(InlineAsm::ConstraintCode::m);
FlagMO.setImm(MemFlag);
for (const MachineOperand &MemOp : MemOps)
MI.addOperand(MemOp);
@@ -735,12 +738,14 @@ static MachineInstr *foldInlineAsmMemOperand(MachineInstr &MI,
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());
+ // Find the operands to fold and where each refers to in the slot, which
+ // holds the whole register: a subregister is at its offset in it. 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.
+ MachineFunction &MF = *MI.getMF();
+ SmallVector<std::optional<unsigned>, 16> Offsets(MI.getNumOperands());
bool Reads = false;
bool Writes = false;
for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
@@ -755,13 +760,21 @@ static MachineInstr *foldInlineAsmMemOperand(MachineInstr &MI,
if (SlotMO.getReg() != Reg)
continue;
- Fold[I] = true;
+ unsigned Offset = 0;
+ if (unsigned SubReg = SlotMO.getSubReg()) {
+ unsigned Size;
+ [[maybe_unused]] bool InSlot = TII.getStackSlotRange(
+ MF.getRegInfo().getRegClass(Reg), SubReg, Size, Offset, MF);
+ assert(InSlot && "foldable subregister isn't in the stack slot");
+ }
+
+ Offsets[I] = Offset;
Reads |= MO.readsReg();
Writes |= MO.isDef();
}
MachineInstr &NewMI = TII.duplicate(*MI.getParent(), MI.getIterator(), MI);
- foldInlineAsmMemOperands(NewMI, Fold, FI, TII);
+ foldInlineAsmMemOperands(NewMI, Offsets, FI, TII);
// Update mayload/maystore metadata, and memoperands.
MachineOperand &ExtraMO = NewMI.getOperand(InlineAsm::MIOp_ExtraInfo);
@@ -774,12 +787,12 @@ static MachineInstr *foldInlineAsmMemOperand(MachineInstr &MI,
ExtraMO.setImm(ExtraMO.getImm() | InlineAsm::Extra_MayStore);
Flags |= MachineMemOperand::MOStore;
}
- MachineFunction *MF = NewMI.getMF();
- const MachineFrameInfo &MFI = MF->getFrameInfo();
- MachineMemOperand *MMO = MF->getMachineMemOperand(
- MachinePointerInfo::getFixedStack(*MF, FI), Flags, MFI.getObjectSize(FI),
- MFI.getObjectAlign(FI));
- NewMI.addMemOperand(*MF, MMO);
+
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ MachineMemOperand *MMO =
+ MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI), Flags,
+ MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
+ NewMI.addMemOperand(MF, MMO);
return &NewMI;
}
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 251fb43e56000b..a38d1b36576205 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -11031,10 +11031,11 @@ void X86InstrInfo::genAlternativeCodeSequence(
// See also: X86DAGToDAGISel::SelectInlineAsmMemoryOperand().
void X86InstrInfo::getFrameIndexOperands(SmallVectorImpl<MachineOperand> &Ops,
- int FI) const {
+ int FI, int64_t Offset) const {
X86AddressMode M;
M.BaseType = X86AddressMode::FrameIndexBase;
M.Base.FrameIndex = FI;
+ M.Disp = Offset;
M.getFullAddress(Ops);
}
diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h
index b8c1aa6b296905..cb2706ce47d59d 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.h
+++ b/llvm/lib/Target/X86/X86InstrInfo.h
@@ -703,8 +703,8 @@ class X86InstrInfo final : public X86GenInstrInfo {
return false;
}
- void getFrameIndexOperands(SmallVectorImpl<MachineOperand> &Ops,
- int FI) const override;
+ void getFrameIndexOperands(SmallVectorImpl<MachineOperand> &Ops, int FI,
+ int64_t Offset) const override;
private:
/// This is a helper for convertToThreeAddress for 8 and 16-bit instructions.
diff --git a/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir b/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir
index deec6136d87a53..311b969a71a3c9 100644
--- a/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir
+++ b/llvm/test/CodeGen/X86/greedy-inline-asm-fold.mir
@@ -224,13 +224,12 @@ body: |
RET 0
...
---
-# A stack slot holds the whole register, so a subregister operand can be
-# folded only if the subregister starts at the beginning of the slot. Each of
-# these tests spills a value across an asm that clobbers every GPR, as above,
-# and passes its low byte, its second byte, or both to a "Qm" operand of a
-# second asm.
+# A stack slot holds the whole register, so a subregister operand is folded
+# at the subregister's offset in the slot. Each of these tests spills a value
+# across an asm that clobbers every GPR, as above, and passes its low byte,
+# its second byte, or both to a "Qm" operand of a second asm.
#
-# The low byte (sub_8bit) is at the start of the slot, so it's folded.
+# The low byte (sub_8bit) is at offset 0.
#
# void qm_low_byte(unsigned long a) {
# asm volatile("" : : : ALL_GPRS);
@@ -254,8 +253,7 @@ body: |
RET 0
...
---
-# The second byte (sub_8bit_hi) is at byte 1 of the slot, so it gets a reload
-# instead of a fold to the start of the slot.
+# The second byte (sub_8bit_hi) is at offset 1.
#
# void qm_high_byte(unsigned long a) {
# asm volatile("" : : : ALL_GPRS);
@@ -271,8 +269,7 @@ body: |
; 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: [[MOV64rm:%[0-9]+]]:gr64_abcd = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
- ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, reguse:GR8_ABCD_H foldable, [[MOV64rm]].sub_8bit_hi
+ ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, mem:m ops:5, %stack.0, 1, $noreg, 1, $noreg :: (load (s64) from %stack.0)
; CHECK-NEXT: RET 0
%0:gr64_abcd = 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
@@ -280,8 +277,7 @@ body: |
RET 0
...
---
-# Both bytes are subregisters of one value. Folding both operands would read
-# byte 0 for each, so neither is folded.
+# Both bytes are subregisters of one value, each folded at its own offset.
#
# void qm_both_bytes(unsigned long a) {
# asm volatile("" : : : ALL_GPRS);
@@ -298,8 +294,7 @@ body: |
; 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: [[MOV64rm:%[0-9]+]]:gr64_abcd = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
- ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, reguse:GR8_ABCD_L foldable, [[MOV64rm]].sub_8bit, reguse:GR8_ABCD_H foldable, [[MOV64rm]].sub_8bit_hi
+ ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, mem:m ops:5, %stack.0, 1, $noreg, 0, $noreg, mem:m ops:5, %stack.0, 1, $noreg, 1, $noreg :: (load (s64) from %stack.0)
; CHECK-NEXT: RET 0
%0:gr64_abcd = 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
@@ -307,12 +302,14 @@ body: |
RET 0
...
---
-# A def is folded along with the use tied to it, so neither is folded when the
-# tied use is the second byte.
+# A def is folded along with the use tied to it, both at the offset of the
+# def's subregister. The third asm keeps the value in its slot after the
+# second.
#
# unsigned long qm_tied_high_byte(unsigned long a) {
# asm volatile("" : : : ALL_GPRS);
# asm volatile("" : "+Qm"(((unsigned char *)&a)[1]));
+# asm volatile("" : : : ALL_GPRS);
# return a;
# }
name: qm_tied_high_byte
@@ -325,13 +322,14 @@ body: |
; 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: [[MOV64rm:%[0-9]+]]:gr64_abcd = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
- ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, regdef:GR8_ABCD_H foldable, def [[MOV64rm]].sub_8bit_hi, reguse tiedto:$0, [[MOV64rm]].sub_8bit_hi(tied-def 3)
- ; CHECK-NEXT: $rax = COPY [[MOV64rm]]
+ ; CHECK-NEXT: INLINEASM &"", sideeffect mayload maystore attdialect, mem:m ops:5, %stack.0, 1, $noreg, 1, $noreg, mem:m ops:5, %stack.0, 1, $noreg, 1, $noreg :: (load store (s64) on %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: $rax = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
; CHECK-NEXT: RET 0, $rax
%0:gr64_abcd = 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, regdef:GR8_ABCD_H foldable, def %0.sub_8bit_hi, reguse tiedto:$0, %0.sub_8bit_hi(tied-def 3)
+ 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
$rax = COPY %0
RET 0, $rax
...
More information about the llvm-branch-commits
mailing list