[llvm] [TargetInstrInfo] enable foldMemoryOperand for InlineAsm (PR #70743)

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 31 08:40:47 PDT 2023


================
@@ -565,6 +565,64 @@ static MachineInstr *foldPatchpoint(MachineFunction &MF, MachineInstr &MI,
   return NewMI;
 }
 
+static void foldInlineAsmMemOperand(MachineInstr *MI, unsigned OpNo, int FI,
+                                    const TargetInstrInfo &TII) {
+  MachineOperand &MO = MI->getOperand(OpNo);
+  const VirtRegInfo &RI = AnalyzeVirtRegInBundle(*MI, MO.getReg());
+
+  // If the machine operand is tied, untie it first.
+  if (MO.isTied()) {
+    unsigned TiedTo = MI->findTiedOperandIdx(OpNo);
+    MI->untieRegOperand(OpNo);
----------------
nickdesaulniers wrote:

Only registers may be tied.  Note how `MachineInstr::untieRegOperand()` does nothing if `!MachineOperand::isReg()` and calls `MachineOperand::isTied()` which asserts if `!isReg()`.

Because we are folding register `MachineOperand`s into Frame Indices, we must untie them, otherwise we will assert in `MachineOperand::ChangeToFrameIndex` (line 582).  Many of the `MachineOperand::ChangeTo*` methods assert if the input is a tied register and you try to change them (without manually untieing them first).

This is also the reason why I had to "remember" which operands were tied when splicing new ones in https://github.com/llvm/llvm-project/commit/a41b149f481e2bcba24e81f208a1938247f040e0 ; if you splice new operands in the middle, you need to remember the existing ties, untie them, move them, insert new operands, then manually retie them.

---
Additional context on what even is a tied operand in the context of inline asm.

For inline asm, you can have inputs, outputs, in/outs, or 2 variables where one is an input, one is an output, but for the sake of register allocation the location chosen for the inline asm is one and the same.

```c
asm ("# %0 %1":"=r"(x):"r"(y));
```
`x` is an output, `y` is an input.  But they will be allocated the same storage location for the duration of the inline asm; `%0` will be equivalent to `%1`.

I don't know when that's ever preferable to just using one variable.

```c
asm ("# %0":"+r"(x));
```

https://github.com/llvm/llvm-project/pull/70743


More information about the llvm-commits mailing list