[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