[llvm] [X86] Fix FP `stackifier` crash on invalid `x87` inline `asm` constraints (PR #221881)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 06:23:34 PDT 2026


================
@@ -1715,6 +1705,62 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &Inst) {
         FPKills |= 1U << FPReg;
     }
 
+    auto RewriteFPRegs = [&]() {
+      for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
+        MachineOperand &Op = MI.getOperand(i);
+        if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
+          continue;
+
+        unsigned FPReg = getFPReg(Op);
+
+        if (FRegIdx.count(i))
+          // Operand with constraint "f".
+          Op.setReg(getSTReg(FPReg));
+        else
+          // Operand with a single register class constraint ("t" or "u").
+          Op.setReg(X86::ST0 + FPReg);
+      }
+    };
+
+    if (Malformed) {
+      // Don't simulate a malformed asm. Just keep the stack model consistent:
+      // pop the killed inputs and push the outputs.
+      RewriteFPRegs();
+      while (FPKills) {
+        unsigned FPReg = llvm::countr_zero(FPKills);
+        if (isLive(FPReg))
+          freeStackSlotBefore(Inst, FPReg);
+        FPKills &= ~(1U << FPReg);
+      }
+      while (STDefs) {
+        unsigned FPReg = llvm::countr_zero(STDefs);
+        if (!isLive(FPReg)) {
+          BuildMI(*MBB, Inst, MI.getDebugLoc(), TII->get(X86::LD_F0));
+          pushReg(FPReg);
+        }
+        STDefs &= ~(1U << FPReg);
+      }
+      return;
+    }
+
+    unsigned NumSTUses = llvm::countr_one(STUses);
+    unsigned NumSTDefs = llvm::countr_one(STDefs);
+    unsigned NumSTPopped = llvm::countr_one(STPopped);
+
+    LLVM_DEBUG(dbgs() << "Asm uses " << NumSTUses << " fixed regs, pops "
+                      << NumSTPopped << ", and defines " << NumSTDefs
+                      << " regs.\n");
+
+#ifndef NDEBUG
+    // If any input operand uses constraint "f", all output register
+    // constraints must be early-clobber defs.
+    for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I)
+      if (FRegIdx.count(I)) {
+        assert((1 << getFPReg(MI.getOperand(I)) & STDefs) == 0 &&
+               "Operands with constraint \"f\" cannot overlap with defs");
+      }
----------------
RKSimon wrote:

can this loop be converted into an `assert(llvm::none_of())` pattern?

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


More information about the llvm-commits mailing list