[llvm] [RISCV] Introduce pass to promote double constants to a global array (PR #160536)

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 1 07:23:50 PDT 2025


================
@@ -0,0 +1,212 @@
+//==- RISCVPromoteConstant.cpp - Promote constant fp to global for RISC-V --==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "RISCVSubtarget.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-promote-const"
+
+STATISTIC(NumPromoted, "Number of promoted constants");
+STATISTIC(NumPromotedUses, "Number of promoted constants uses");
+
+namespace {
+
+class RISCVPromoteConstant : public ModulePass {
+public:
+  static char ID;
+  RISCVPromoteConstant() : ModulePass(ID) {}
+
+  StringRef getPassName() const override { return "RISC-V Promote Constant"; }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.addRequired<TargetPassConfig>();
+    AU.setPreservesCFG();
+  }
+
+  /// Iterate over the functions and promote the double fp constants that
+  /// would otherwise go into the constant pool to a constant array.
+  bool runOnModule(Module &M) override {
+    LLVM_DEBUG(dbgs() << getPassName() << '\n');
+    // TargetMachine and Subtarget are needed to query isFPImmlegal. Get them
+    // from TargetPassConfig.
+    const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
+    const TargetMachine &TM = TPC.getTM<TargetMachine>();
+    if (skipModule(M))
+      return false;
+    bool Changed = false;
+    for (auto &MF : M) {
+      const RISCVSubtarget &ST = TM.getSubtarget<RISCVSubtarget>(MF);
+      const RISCVTargetLowering *TLI = ST.getTargetLowering();
+      Changed |= runOnFunction(MF, TLI);
+    }
+    return Changed;
+  }
+
+private:
+  bool runOnFunction(Function &F, const RISCVTargetLowering *TLI);
+};
+} // end anonymous namespace
+
+char RISCVPromoteConstant::ID = 0;
+
+ModulePass *llvm::createRISCVPromoteConstantPass() {
+  return new RISCVPromoteConstant();
+}
+
+bool RISCVPromoteConstant::runOnFunction(Function &F,
+                                         const RISCVTargetLowering *TLI) {
+  // Bail out and make no transformation if the target doesn't support
+  // doubles, or if we're not targeting RV64 as we currently see some
+  // regressions for those targets.
+  if (!TLI->isTypeLegal(MVT::f64) || !TLI->isTypeLegal(MVT::i64))
+    return false;
+
+  // Collect all unique double constants used in the function, and track their
+  // offset within the newly created global array. Also track uses that will
+  // be replaced later.
+  DenseMap<ConstantFP *, unsigned> ConstantMap;
+  SmallVector<Constant *, 16> ConstantVector;
+  DenseMap<ConstantFP *, SmallVector<Use *, 8>> UsesInFunc;
+
+  for (Instruction &I : instructions(F)) {
+    // PHI nodes are handled specially in a second loop below.
+    if (isa<PHINode>(I))
+      continue;
+    for (Use &U : I.operands()) {
+      if (auto *C = dyn_cast<ConstantFP>(U.get())) {
----------------
asb wrote:

Just to confirm: Is this a concern about correctness or a suggestion for another profitable transform? Fully agreed it could be worthwhile doing promotion for vector constants and I'd like to return to that, but I'm trying to keep this very narrowly scoped initially.

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


More information about the llvm-commits mailing list