Skip to content

Conversation

@boomanaiden154
Copy link
Contributor

In preparation for porting to the NewPM.

Created using spr 1.3.7
@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-backend-x86

Author: Aiden Grossman (boomanaiden154)

Changes

In preparation for porting to the NewPM.


Patch is 53.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/167910.diff

1 Files Affected:

  • (modified) llvm/lib/Target/X86/X86FloatingPoint.cpp (+497-499)
diff --git a/llvm/lib/Target/X86/X86FloatingPoint.cpp b/llvm/lib/Target/X86/X86FloatingPoint.cpp
index 3f06d21a23b88..bc9d354cd8e1a 100644
--- a/llvm/lib/Target/X86/X86FloatingPoint.cpp
+++ b/llvm/lib/Target/X86/X86FloatingPoint.cpp
@@ -51,255 +51,254 @@ using namespace llvm;
 #define DEBUG_TYPE "x86-codegen"
 
 STATISTIC(NumFXCH, "Number of fxch instructions inserted");
-STATISTIC(NumFP  , "Number of floating point instructions");
+STATISTIC(NumFP, "Number of floating point instructions");
 
 namespace {
-  const unsigned ScratchFPReg = 7;
-
-  struct FPS : public MachineFunctionPass {
-    static char ID;
-    FPS() : MachineFunctionPass(ID) {}
-
-    void getAnalysisUsage(AnalysisUsage &AU) const override {
-      AU.setPreservesCFG();
-      AU.addRequired<EdgeBundlesWrapperLegacy>();
-      AU.addPreservedID(MachineLoopInfoID);
-      AU.addPreservedID(MachineDominatorsID);
-      MachineFunctionPass::getAnalysisUsage(AU);
-    }
+const unsigned ScratchFPReg = 7;
+
+struct FPS : public MachineFunctionPass {
+  static char ID;
+  FPS() : MachineFunctionPass(ID) {}
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+    AU.addRequired<EdgeBundlesWrapperLegacy>();
+    AU.addPreservedID(MachineLoopInfoID);
+    AU.addPreservedID(MachineDominatorsID);
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
 
-    bool runOnMachineFunction(MachineFunction &MF) override;
+  bool runOnMachineFunction(MachineFunction &MF) override;
 
-    MachineFunctionProperties getRequiredProperties() const override {
-      return MachineFunctionProperties().setNoVRegs();
-    }
+  MachineFunctionProperties getRequiredProperties() const override {
+    return MachineFunctionProperties().setNoVRegs();
+  }
 
-    StringRef getPassName() const override { return "X86 FP Stackifier"; }
+  StringRef getPassName() const override { return "X86 FP Stackifier"; }
 
-  private:
-    const TargetInstrInfo *TII = nullptr; // Machine instruction info.
+private:
+  const TargetInstrInfo *TII = nullptr; // Machine instruction info.
 
-    // Two CFG edges are related if they leave the same block, or enter the same
-    // block. The transitive closure of an edge under this relation is a
-    // LiveBundle. It represents a set of CFG edges where the live FP stack
-    // registers must be allocated identically in the x87 stack.
-    //
-    // A LiveBundle is usually all the edges leaving a block, or all the edges
-    // entering a block, but it can contain more edges if critical edges are
-    // present.
-    //
-    // The set of live FP registers in a LiveBundle is calculated by bundleCFG,
-    // but the exact mapping of FP registers to stack slots is fixed later.
-    struct LiveBundle {
-      // Bit mask of live FP registers. Bit 0 = FP0, bit 1 = FP1, &c.
-      unsigned Mask = 0;
-
-      // Number of pre-assigned live registers in FixStack. This is 0 when the
-      // stack order has not yet been fixed.
-      unsigned FixCount = 0;
-
-      // Assigned stack order for live-in registers.
-      // FixStack[i] == getStackEntry(i) for all i < FixCount.
-      unsigned char FixStack[8];
-
-      LiveBundle() = default;
-
-      // Have the live registers been assigned a stack order yet?
-      bool isFixed() const { return !Mask || FixCount; }
-    };
-
-    // Numbered LiveBundle structs. LiveBundles[0] is used for all CFG edges
-    // with no live FP registers.
-    SmallVector<LiveBundle, 8> LiveBundles;
-
-    // The edge bundle analysis provides indices into the LiveBundles vector.
-    EdgeBundles *Bundles = nullptr;
-
-    // Return a bitmask of FP registers in block's live-in list.
-    static unsigned calcLiveInMask(MachineBasicBlock *MBB, bool RemoveFPs) {
-      unsigned Mask = 0;
-      for (MachineBasicBlock::livein_iterator I = MBB->livein_begin();
-           I != MBB->livein_end(); ) {
-        MCPhysReg Reg = I->PhysReg;
-        static_assert(X86::FP6 - X86::FP0 == 6, "sequential regnums");
-        if (Reg >= X86::FP0 && Reg <= X86::FP6) {
-          Mask |= 1 << (Reg - X86::FP0);
-          if (RemoveFPs) {
-            I = MBB->removeLiveIn(I);
-            continue;
-          }
+  // Two CFG edges are related if they leave the same block, or enter the same
+  // block. The transitive closure of an edge under this relation is a
+  // LiveBundle. It represents a set of CFG edges where the live FP stack
+  // registers must be allocated identically in the x87 stack.
+  //
+  // A LiveBundle is usually all the edges leaving a block, or all the edges
+  // entering a block, but it can contain more edges if critical edges are
+  // present.
+  //
+  // The set of live FP registers in a LiveBundle is calculated by bundleCFG,
+  // but the exact mapping of FP registers to stack slots is fixed later.
+  struct LiveBundle {
+    // Bit mask of live FP registers. Bit 0 = FP0, bit 1 = FP1, &c.
+    unsigned Mask = 0;
+
+    // Number of pre-assigned live registers in FixStack. This is 0 when the
+    // stack order has not yet been fixed.
+    unsigned FixCount = 0;
+
+    // Assigned stack order for live-in registers.
+    // FixStack[i] == getStackEntry(i) for all i < FixCount.
+    unsigned char FixStack[8];
+
+    LiveBundle() = default;
+
+    // Have the live registers been assigned a stack order yet?
+    bool isFixed() const { return !Mask || FixCount; }
+  };
+
+  // Numbered LiveBundle structs. LiveBundles[0] is used for all CFG edges
+  // with no live FP registers.
+  SmallVector<LiveBundle, 8> LiveBundles;
+
+  // The edge bundle analysis provides indices into the LiveBundles vector.
+  EdgeBundles *Bundles = nullptr;
+
+  // Return a bitmask of FP registers in block's live-in list.
+  static unsigned calcLiveInMask(MachineBasicBlock *MBB, bool RemoveFPs) {
+    unsigned Mask = 0;
+    for (MachineBasicBlock::livein_iterator I = MBB->livein_begin();
+         I != MBB->livein_end();) {
+      MCPhysReg Reg = I->PhysReg;
+      static_assert(X86::FP6 - X86::FP0 == 6, "sequential regnums");
+      if (Reg >= X86::FP0 && Reg <= X86::FP6) {
+        Mask |= 1 << (Reg - X86::FP0);
+        if (RemoveFPs) {
+          I = MBB->removeLiveIn(I);
+          continue;
         }
-        ++I;
       }
-      return Mask;
+      ++I;
     }
+    return Mask;
+  }
 
-    // Partition all the CFG edges into LiveBundles.
-    void bundleCFGRecomputeKillFlags(MachineFunction &MF);
+  // Partition all the CFG edges into LiveBundles.
+  void bundleCFGRecomputeKillFlags(MachineFunction &MF);
 
-    MachineBasicBlock *MBB = nullptr;     // Current basic block
+  MachineBasicBlock *MBB = nullptr; // Current basic block
 
-    // The hardware keeps track of how many FP registers are live, so we have
-    // to model that exactly. Usually, each live register corresponds to an
-    // FP<n> register, but when dealing with calls, returns, and inline
-    // assembly, it is sometimes necessary to have live scratch registers.
-    unsigned Stack[8] = {};     // FP<n> Registers in each stack slot...
-    unsigned StackTop = 0;      // The current top of the FP stack.
+  // The hardware keeps track of how many FP registers are live, so we have
+  // to model that exactly. Usually, each live register corresponds to an
+  // FP<n> register, but when dealing with calls, returns, and inline
+  // assembly, it is sometimes necessary to have live scratch registers.
+  unsigned Stack[8] = {}; // FP<n> Registers in each stack slot...
+  unsigned StackTop = 0;  // The current top of the FP stack.
 
-    enum {
-      NumFPRegs = 8             // Including scratch pseudo-registers.
-    };
+  enum {
+    NumFPRegs = 8 // Including scratch pseudo-registers.
+  };
 
-    // For each live FP<n> register, point to its Stack[] entry.
-    // The first entries correspond to FP0-FP6, the rest are scratch registers
-    // used when we need slightly different live registers than what the
-    // register allocator thinks.
-    unsigned RegMap[NumFPRegs] = {};
+  // For each live FP<n> register, point to its Stack[] entry.
+  // The first entries correspond to FP0-FP6, the rest are scratch registers
+  // used when we need slightly different live registers than what the
+  // register allocator thinks.
+  unsigned RegMap[NumFPRegs] = {};
 
-    // Set up our stack model to match the incoming registers to MBB.
-    void setupBlockStack();
+  // Set up our stack model to match the incoming registers to MBB.
+  void setupBlockStack();
 
-    // Shuffle live registers to match the expectations of successor blocks.
-    void finishBlockStack();
+  // Shuffle live registers to match the expectations of successor blocks.
+  void finishBlockStack();
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-    void dumpStack() const {
-      dbgs() << "Stack contents:";
-      for (unsigned i = 0; i != StackTop; ++i) {
-        dbgs() << " FP" << Stack[i];
-        assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!");
-      }
+  void dumpStack() const {
+    dbgs() << "Stack contents:";
+    for (unsigned i = 0; i != StackTop; ++i) {
+      dbgs() << " FP" << Stack[i];
+      assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!");
     }
+  }
 #endif
 
-    /// getSlot - Return the stack slot number a particular register number is
-    /// in.
-    unsigned getSlot(unsigned RegNo) const {
-      assert(RegNo < NumFPRegs && "Regno out of range!");
-      return RegMap[RegNo];
-    }
+  /// getSlot - Return the stack slot number a particular register number is
+  /// in.
+  unsigned getSlot(unsigned RegNo) const {
+    assert(RegNo < NumFPRegs && "Regno out of range!");
+    return RegMap[RegNo];
+  }
 
-    /// isLive - Is RegNo currently live in the stack?
-    bool isLive(unsigned RegNo) const {
-      unsigned Slot = getSlot(RegNo);
-      return Slot < StackTop && Stack[Slot] == RegNo;
-    }
+  /// isLive - Is RegNo currently live in the stack?
+  bool isLive(unsigned RegNo) const {
+    unsigned Slot = getSlot(RegNo);
+    return Slot < StackTop && Stack[Slot] == RegNo;
+  }
 
-    /// getStackEntry - Return the X86::FP<n> register in register ST(i).
-    unsigned getStackEntry(unsigned STi) const {
-      if (STi >= StackTop)
-        report_fatal_error("Access past stack top!");
-      return Stack[StackTop-1-STi];
-    }
+  /// getStackEntry - Return the X86::FP<n> register in register ST(i).
+  unsigned getStackEntry(unsigned STi) const {
+    if (STi >= StackTop)
+      report_fatal_error("Access past stack top!");
+    return Stack[StackTop - 1 - STi];
+  }
 
-    /// getSTReg - Return the X86::ST(i) register which contains the specified
-    /// FP<RegNo> register.
-    unsigned getSTReg(unsigned RegNo) const {
-      return StackTop - 1 - getSlot(RegNo) + X86::ST0;
-    }
+  /// getSTReg - Return the X86::ST(i) register which contains the specified
+  /// FP<RegNo> register.
+  unsigned getSTReg(unsigned RegNo) const {
+    return StackTop - 1 - getSlot(RegNo) + X86::ST0;
+  }
 
-    // pushReg - Push the specified FP<n> register onto the stack.
-    void pushReg(unsigned Reg) {
-      assert(Reg < NumFPRegs && "Register number out of range!");
-      if (StackTop >= 8)
-        report_fatal_error("Stack overflow!");
-      Stack[StackTop] = Reg;
-      RegMap[Reg] = StackTop++;
-    }
+  // pushReg - Push the specified FP<n> register onto the stack.
+  void pushReg(unsigned Reg) {
+    assert(Reg < NumFPRegs && "Register number out of range!");
+    if (StackTop >= 8)
+      report_fatal_error("Stack overflow!");
+    Stack[StackTop] = Reg;
+    RegMap[Reg] = StackTop++;
+  }
 
-    // popReg - Pop a register from the stack.
-    void popReg() {
-      if (StackTop == 0)
-        report_fatal_error("Cannot pop empty stack!");
-      RegMap[Stack[--StackTop]] = ~0;     // Update state
-    }
+  // popReg - Pop a register from the stack.
+  void popReg() {
+    if (StackTop == 0)
+      report_fatal_error("Cannot pop empty stack!");
+    RegMap[Stack[--StackTop]] = ~0; // Update state
+  }
 
-    bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop-1; }
-    void moveToTop(unsigned RegNo, MachineBasicBlock::iterator I) {
-      DebugLoc dl = I == MBB->end() ? DebugLoc() : I->getDebugLoc();
-      if (isAtTop(RegNo)) return;
+  bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop - 1; }
+  void moveToTop(unsigned RegNo, MachineBasicBlock::iterator I) {
+    DebugLoc dl = I == MBB->end() ? DebugLoc() : I->getDebugLoc();
+    if (isAtTop(RegNo))
+      return;
 
-      unsigned STReg = getSTReg(RegNo);
-      unsigned RegOnTop = getStackEntry(0);
+    unsigned STReg = getSTReg(RegNo);
+    unsigned RegOnTop = getStackEntry(0);
 
-      // Swap the slots the regs are in.
-      std::swap(RegMap[RegNo], RegMap[RegOnTop]);
+    // Swap the slots the regs are in.
+    std::swap(RegMap[RegNo], RegMap[RegOnTop]);
 
-      // Swap stack slot contents.
-      if (RegMap[RegOnTop] >= StackTop)
-        report_fatal_error("Access past stack top!");
-      std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
+    // Swap stack slot contents.
+    if (RegMap[RegOnTop] >= StackTop)
+      report_fatal_error("Access past stack top!");
+    std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop - 1]);
 
-      // Emit an fxch to update the runtime processors version of the state.
-      BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(STReg);
-      ++NumFXCH;
-    }
+    // Emit an fxch to update the runtime processors version of the state.
+    BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(STReg);
+    ++NumFXCH;
+  }
 
-    void duplicateToTop(unsigned RegNo, unsigned AsReg,
-                        MachineBasicBlock::iterator I) {
-      DebugLoc dl = I == MBB->end() ? DebugLoc() : I->getDebugLoc();
-      unsigned STReg = getSTReg(RegNo);
-      pushReg(AsReg);   // New register on top of stack
+  void duplicateToTop(unsigned RegNo, unsigned AsReg,
+                      MachineBasicBlock::iterator I) {
+    DebugLoc dl = I == MBB->end() ? DebugLoc() : I->getDebugLoc();
+    unsigned STReg = getSTReg(RegNo);
+    pushReg(AsReg); // New register on top of stack
 
-      BuildMI(*MBB, I, dl, TII->get(X86::LD_Frr)).addReg(STReg);
-    }
+    BuildMI(*MBB, I, dl, TII->get(X86::LD_Frr)).addReg(STReg);
+  }
 
-    /// popStackAfter - Pop the current value off of the top of the FP stack
-    /// after the specified instruction.
-    void popStackAfter(MachineBasicBlock::iterator &I);
-
-    /// freeStackSlotAfter - Free the specified register from the register
-    /// stack, so that it is no longer in a register.  If the register is
-    /// currently at the top of the stack, we just pop the current instruction,
-    /// otherwise we store the current top-of-stack into the specified slot,
-    /// then pop the top of stack.
-    void freeStackSlotAfter(MachineBasicBlock::iterator &I, unsigned Reg);
-
-    /// freeStackSlotBefore - Just the pop, no folding. Return the inserted
-    /// instruction.
-    MachineBasicBlock::iterator
-    freeStackSlotBefore(MachineBasicBlock::iterator I, unsigned FPRegNo);
-
-    /// Adjust the live registers to be the set in Mask.
-    void adjustLiveRegs(unsigned Mask, MachineBasicBlock::iterator I);
-
-    /// Shuffle the top FixCount stack entries such that FP reg FixStack[0] is
-    /// st(0), FP reg FixStack[1] is st(1) etc.
-    void shuffleStackTop(const unsigned char *FixStack, unsigned FixCount,
-                         MachineBasicBlock::iterator I);
-
-    bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
-
-    void handleCall(MachineBasicBlock::iterator &I);
-    void handleReturn(MachineBasicBlock::iterator &I);
-    void handleZeroArgFP(MachineBasicBlock::iterator &I);
-    void handleOneArgFP(MachineBasicBlock::iterator &I);
-    void handleOneArgFPRW(MachineBasicBlock::iterator &I);
-    void handleTwoArgFP(MachineBasicBlock::iterator &I);
-    void handleCompareFP(MachineBasicBlock::iterator &I);
-    void handleCondMovFP(MachineBasicBlock::iterator &I);
-    void handleSpecialFP(MachineBasicBlock::iterator &I);
-
-    // Check if a COPY instruction is using FP registers.
-    static bool isFPCopy(MachineInstr &MI) {
-      Register DstReg = MI.getOperand(0).getReg();
-      Register SrcReg = MI.getOperand(1).getReg();
-
-      return X86::RFP80RegClass.contains(DstReg) ||
-        X86::RFP80RegClass.contains(SrcReg);
-    }
+  /// popStackAfter - Pop the current value off of the top of the FP stack
+  /// after the specified instruction.
+  void popStackAfter(MachineBasicBlock::iterator &I);
+
+  /// freeStackSlotAfter - Free the specified register from the register
+  /// stack, so that it is no longer in a register.  If the register is
+  /// currently at the top of the stack, we just pop the current instruction,
+  /// otherwise we store the current top-of-stack into the specified slot,
+  /// then pop the top of stack.
+  void freeStackSlotAfter(MachineBasicBlock::iterator &I, unsigned Reg);
+
+  /// freeStackSlotBefore - Just the pop, no folding. Return the inserted
+  /// instruction.
+  MachineBasicBlock::iterator freeStackSlotBefore(MachineBasicBlock::iterator I,
+                                                  unsigned FPRegNo);
+
+  /// Adjust the live registers to be the set in Mask.
+  void adjustLiveRegs(unsigned Mask, MachineBasicBlock::iterator I);
+
+  /// Shuffle the top FixCount stack entries such that FP reg FixStack[0] is
+  /// st(0), FP reg FixStack[1] is st(1) etc.
+  void shuffleStackTop(const unsigned char *FixStack, unsigned FixCount,
+                       MachineBasicBlock::iterator I);
+
+  bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
+
+  void handleCall(MachineBasicBlock::iterator &I);
+  void handleReturn(MachineBasicBlock::iterator &I);
+  void handleZeroArgFP(MachineBasicBlock::iterator &I);
+  void handleOneArgFP(MachineBasicBlock::iterator &I);
+  void handleOneArgFPRW(MachineBasicBlock::iterator &I);
+  void handleTwoArgFP(MachineBasicBlock::iterator &I);
+  void handleCompareFP(MachineBasicBlock::iterator &I);
+  void handleCondMovFP(MachineBasicBlock::iterator &I);
+  void handleSpecialFP(MachineBasicBlock::iterator &I);
+
+  // Check if a COPY instruction is using FP registers.
+  static bool isFPCopy(MachineInstr &MI) {
+    Register DstReg = MI.getOperand(0).getReg();
+    Register SrcReg = MI.getOperand(1).getReg();
+
+    return X86::RFP80RegClass.contains(DstReg) ||
+           X86::RFP80RegClass.contains(SrcReg);
+  }
 
-    void setKillFlags(MachineBasicBlock &MBB) const;
-  };
-}
+  void setKillFlags(MachineBasicBlock &MBB) const;
+};
+} // namespace
 
 char FPS::ID = 0;
 
-INITIALIZE_PASS_BEGIN(FPS, DEBUG_TYPE, "X86 FP Stackifier",
-                      false, false)
+INITIALIZE_PASS_BEGIN(FPS, DEBUG_TYPE, "X86 FP Stackifier", false, false)
 INITIALIZE_PASS_DEPENDENCY(EdgeBundlesWrapperLegacy)
-INITIALIZE_PASS_END(FPS, DEBUG_TYPE, "X86 FP Stackifier",
-                    false, false)
+INITIALIZE_PASS_END(FPS, DEBUG_TYPE, "X86 FP Stackifier", false, false)
 
 FunctionPass *llvm::createX86FloatingPointStackifierPass() { return new FPS(); }
 
@@ -320,7 +319,8 @@ bool FPS::runOnMachineFunction(MachineFunction &MF) {
   // function.  If it is all integer, there is nothing for us to do!
   bool FPIsUsed = false;
 
-  static_assert(X86::FP6 == X86::FP0+6, "Register enums aren't sorted right!");
+  static_assert(X86::FP6 == X86::FP0 + 6,
+                "Register enums aren't sorted right!");
   const MachineRegisterInfo &MRI = MF.getRegInfo();
   for (unsigned i = 0; i <= 6; ++i)
     if (!MRI.reg_nodbg_empty(X86::FP0 + i)) {
@@ -329,7 +329,8 @@ bool FPS::runOnMachineFunction(MachineFunction &MF) {
     }
 
   // Early exit.
-  if (!FPIsUsed) return false;
+  if (!FPIsUsed)
+    return false;
 
   Bundles = &getAnalysis<EdgeBundlesWrapperLegacy>().getEdgeBundles();
   TII = MF.getSubtarget().getInstrInfo();
@@ -341,16 +342,17 @@ bool FPS::runOnMachineFunction(MachineFunction &MF) {
 
   // Process the function in depth first order so that we process at least one
   // of the predecessors for every reachable block in the function.
-  df_iterator_default_set<MachineBasicBlock*> Processed;
+  df_iterator_default_set<MachineBasicBlock *> Processed;
   MachineBasicBlock *Entry = &MF.front();
 
   LiveBundle &Bundle =
-    LiveBundles[Bundles->getBundle(Entry->getNumber(), false)];
+      LiveBundles[Bundles->ge...
[truncated]

Copy link
Contributor

@kazutakahirata kazutakahirata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

boomanaiden154 added a commit to boomanaiden154/llvm-project that referenced this pull request Nov 13, 2025
In preparation for porting to the NewPM.

Pull Request: llvm#167910
@boomanaiden154 boomanaiden154 merged commit 7aa60b6 into main Nov 13, 2025
12 checks passed
@boomanaiden154 boomanaiden154 deleted the users/boomanaiden154/nfcx86-format-floating-point-stackifier-pass branch November 13, 2025 18:52
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Nov 13, 2025
In preparation for porting to the NewPM.

Reviewers: kazutakahirata, arsenm

Reviewed By: kazutakahirata, arsenm

Pull Request: llvm/llvm-project#167910
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants