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
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:2909
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.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const
Returns true if the specified FP immediate can be materialized without a load from the constant pool.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
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