LLVM 24.0.0git
RISCVPromoteConstant.cpp
Go to the documentation of this file.
1//==- RISCVPromoteConstant.cpp - Promote constant fp to global for RISC-V --==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "RISCV.h"
10#include "RISCVSubtarget.h"
11#include "RISCVTargetMachine.h"
12#include "llvm/ADT/DenseMap.h"
14#include "llvm/ADT/Statistic.h"
17#include "llvm/IR/Analysis.h"
18#include "llvm/IR/BasicBlock.h"
19#include "llvm/IR/Constant.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/GlobalValue.h"
24#include "llvm/IR/IRBuilder.h"
26#include "llvm/IR/Instruction.h"
29#include "llvm/IR/Module.h"
30#include "llvm/IR/PassManager.h"
31#include "llvm/IR/Type.h"
32#include "llvm/Pass.h"
34#include "llvm/Support/Debug.h"
35
36using namespace llvm;
37
38#define DEBUG_TYPE "riscv-promote-constant"
39#define RISCV_PROMOTE_CONSTANT_NAME "RISC-V Promote Constants"
40
41STATISTIC(NumPromoted, "Number of constant literals promoted to globals");
42STATISTIC(NumPromotedUses, "Number of uses of promoted literal constants");
43
44namespace {
45
46class RISCVPromoteConstantLegacy : public ModulePass {
47public:
48 static char ID;
49 RISCVPromoteConstantLegacy() : ModulePass(ID) {}
50
51 StringRef getPassName() const override { return RISCV_PROMOTE_CONSTANT_NAME; }
52
53 void getAnalysisUsage(AnalysisUsage &AU) const override {
54 AU.addRequired<TargetPassConfig>();
55 AU.setPreservesCFG();
56 }
57
58 bool runOnModule(Module &M) override;
59};
60} // end anonymous namespace
61
62char RISCVPromoteConstantLegacy::ID = 0;
63
64INITIALIZE_PASS(RISCVPromoteConstantLegacy, DEBUG_TYPE,
65 RISCV_PROMOTE_CONSTANT_NAME, false, false)
66
68 return new RISCVPromoteConstantLegacy();
69}
70
72 const RISCVTargetLowering *TLI) {
73 if (F.hasOptNone() || F.hasOptSize())
74 return false;
75
76 // Bail out and make no transformation if the target doesn't support
77 // doubles, or if we're not targeting RV64 as we currently see some
78 // regressions for those targets.
79 if (!TLI->isTypeLegal(MVT::f64) || !TLI->isTypeLegal(MVT::i64))
80 return false;
81
82 // Collect all unique double constants and their uses in the function. Use
83 // MapVector to preserve insertion order.
85
86 for (Instruction &I : instructions(F)) {
87 for (Use &U : I.operands()) {
88 auto *C = dyn_cast<ConstantFP>(U.get());
89 if (!C || !C->getType()->isDoubleTy())
90 continue;
91 // Do not promote if it wouldn't be loaded from the constant pool.
92 if (TLI->isFPImmLegal(C->getValueAPF(), MVT::f64,
93 /*ForCodeSize=*/false))
94 continue;
95 // Do not promote a constant if it is used as an immediate argument
96 // for an intrinsic.
97 if (auto *II = dyn_cast<IntrinsicInst>(U.getUser())) {
98 Function *IntrinsicFunc = II->getFunction();
99 unsigned OperandIdx = U.getOperandNo();
100 if (IntrinsicFunc && IntrinsicFunc->getAttributes().hasParamAttr(
101 OperandIdx, Attribute::ImmArg)) {
102 LLVM_DEBUG(dbgs() << "Skipping promotion of constant in: " << *II
103 << " because operand " << OperandIdx
104 << " must be an immediate.\n");
105 continue;
106 }
107 }
108 // Note: FP args to inline asm would be problematic if we had a
109 // constraint that required an immediate floating point operand. At the
110 // time of writing LLVM doesn't recognise such a constraint.
111 ConstUsesMap[C].push_back(&U);
112 }
113 }
114
115 int PromotableConstants = ConstUsesMap.size();
116 LLVM_DEBUG(dbgs() << "Found " << PromotableConstants
117 << " promotable constants in " << F.getName() << "\n");
118 // Bail out if no promotable constants found, or if only one is found.
119 if (PromotableConstants < 2) {
120 LLVM_DEBUG(dbgs() << "Performing no promotions as insufficient promotable "
121 "constants found\n");
122 return false;
123 }
124
125 NumPromoted += PromotableConstants;
126
127 // Create a global array containing the promoted constants.
128 Module *M = F.getParent();
129 Type *DoubleTy = Type::getDoubleTy(M->getContext());
130
132 for (auto const &Pair : ConstUsesMap)
133 ConstantVector.push_back(Pair.first);
134
135 ArrayType *ArrayTy = ArrayType::get(DoubleTy, ConstantVector.size());
136 Constant *GlobalArrayInitializer =
138
139 auto *GlobalArray = new GlobalVariable(
140 *M, ArrayTy,
141 /*isConstant=*/true, GlobalValue::InternalLinkage, GlobalArrayInitializer,
142 ".promoted_doubles." + F.getName());
143
144 // A cache to hold the loaded value for a given constant within a basic block.
146
147 // Replace all uses with the loaded value.
148 unsigned Idx = 0;
149 for (auto const &Pair : ConstUsesMap) {
150 ConstantFP *Const = Pair.first;
151 const SmallVector<Use *, 8> &Uses = Pair.second;
152
153 for (Use *U : Uses) {
154 Instruction *UserInst = cast<Instruction>(U->getUser());
155 BasicBlock *InsertionBB;
156
157 // If the user is a PHI node, we must insert the load in the
158 // corresponding predecessor basic block. Otherwise, it's inserted into
159 // the same block as the use.
160 if (auto *PN = dyn_cast<PHINode>(UserInst))
161 InsertionBB = PN->getIncomingBlock(*U);
162 else
163 InsertionBB = UserInst->getParent();
164
165 if (isa<CatchSwitchInst>(InsertionBB->getTerminator())) {
166 LLVM_DEBUG(dbgs() << "Bailing out: catchswitch means thre is no valid "
167 "insertion point.\n");
168 return false;
169 }
170
171 auto CacheKey = std::make_pair(Const, InsertionBB);
172 Value *LoadedVal = nullptr;
173
174 // Re-use a load if it exists in the insertion block.
175 if (LocalLoads.count(CacheKey)) {
176 LoadedVal = LocalLoads.at(CacheKey);
177 } else {
178 // Otherwise, create a new GEP and Load at the correct insertion point.
179 // It is always safe to insert in the first insertion point in the BB,
180 // so do that and let other passes reorder.
181 IRBuilder<> Builder(InsertionBB->getFirstInsertionPt());
182 Value *ElementPtr = Builder.CreateConstInBoundsGEP2_64(
183 GlobalArray->getValueType(), GlobalArray, 0, Idx, "double.addr");
184 LoadedVal = Builder.CreateLoad(DoubleTy, ElementPtr, "double.val");
185
186 // Cache the newly created load for this block.
187 LocalLoads[CacheKey] = LoadedVal;
188 }
189
190 U->set(LoadedVal);
191 ++NumPromotedUses;
192 }
193 ++Idx;
194 }
195
196 return true;
197}
198
199/// Iterate over the functions and promote the double fp constants that
200/// would otherwise go into the constant pool to a constant array.
202 bool Changed = false;
203 for (Function &F : M) {
204 if (F.isDeclaration())
205 continue;
207 const RISCVTargetLowering *TLI = ST.getTargetLowering();
209 }
210 return Changed;
211}
212
213bool RISCVPromoteConstantLegacy::runOnModule(Module &M) {
214 if (skipModule(M))
215 return false;
216 // TargetMachine and Subtarget are needed to query isFPImmlegal.
217 const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
218 const TargetMachine &TM = TPC.getTM<TargetMachine>();
219 return promoteConstantsInModule(M, TM);
220}
221
const TargetLowering & TLI
Expand Atomic instructions
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool promoteConstantsInModule(Module &M, const TargetMachine &TM)
Iterate over the functions and promote the double fp constants that would otherwise go into the const...
static bool promotConstantsInFunction(Function &F, const RISCVTargetLowering *TLI)
#define RISCV_PROMOTE_CONSTANT_NAME
Remove Loads Into Fake Uses
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:280
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
Constant Vector Declarations.
Definition Constants.h:674
This is an important base class in LLVM.
Definition Constant.h:44
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:762
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:811
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:329
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2947
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
size_type size() const
Definition MapVector.h:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
TMC & getTM() const
Get the right type of TargetMachine for this target.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:277
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
const ParentTy * getParent() const
Definition ilist_node.h:34
Pass manager infrastructure for declaring and invalidating analyses.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
ModulePass * createRISCVPromoteConstantLegacyPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39