Bug Summary

File:build/source/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp
Warning:line 204, column 39
The result of the left shift is undefined due to shifting by '128', which is greater or equal to the width of type 'unsigned long long'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name MVEGatherScatterLowering.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Target/ARM -I /build/source/llvm/lib/Target/ARM -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp

/build/source/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp

1//===- MVEGatherScatterLowering.cpp - Gather/Scatter lowering -------------===//
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/// This pass custom lowers llvm.gather and llvm.scatter instructions to
10/// arm.mve.gather and arm.mve.scatter intrinsics, optimising the code to
11/// produce a better final result as we go.
12//
13//===----------------------------------------------------------------------===//
14
15#include "ARM.h"
16#include "ARMBaseInstrInfo.h"
17#include "ARMSubtarget.h"
18#include "llvm/Analysis/LoopInfo.h"
19#include "llvm/Analysis/TargetTransformInfo.h"
20#include "llvm/Analysis/ValueTracking.h"
21#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/CodeGen/TargetPassConfig.h"
23#include "llvm/CodeGen/TargetSubtargetInfo.h"
24#include "llvm/InitializePasses.h"
25#include "llvm/IR/BasicBlock.h"
26#include "llvm/IR/Constant.h"
27#include "llvm/IR/Constants.h"
28#include "llvm/IR/DerivedTypes.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/InstrTypes.h"
31#include "llvm/IR/Instruction.h"
32#include "llvm/IR/Instructions.h"
33#include "llvm/IR/IntrinsicInst.h"
34#include "llvm/IR/Intrinsics.h"
35#include "llvm/IR/IntrinsicsARM.h"
36#include "llvm/IR/IRBuilder.h"
37#include "llvm/IR/PatternMatch.h"
38#include "llvm/IR/Type.h"
39#include "llvm/IR/Value.h"
40#include "llvm/Pass.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Transforms/Utils/Local.h"
43#include <algorithm>
44#include <cassert>
45
46using namespace llvm;
47
48#define DEBUG_TYPE"arm-mve-gather-scatter-lowering" "arm-mve-gather-scatter-lowering"
49
50cl::opt<bool> EnableMaskedGatherScatters(
51 "enable-arm-maskedgatscat", cl::Hidden, cl::init(true),
52 cl::desc("Enable the generation of masked gathers and scatters"));
53
54namespace {
55
56class MVEGatherScatterLowering : public FunctionPass {
57public:
58 static char ID; // Pass identification, replacement for typeid
59
60 explicit MVEGatherScatterLowering() : FunctionPass(ID) {
61 initializeMVEGatherScatterLoweringPass(*PassRegistry::getPassRegistry());
62 }
63
64 bool runOnFunction(Function &F) override;
65
66 StringRef getPassName() const override {
67 return "MVE gather/scatter lowering";
68 }
69
70 void getAnalysisUsage(AnalysisUsage &AU) const override {
71 AU.setPreservesCFG();
72 AU.addRequired<TargetPassConfig>();
73 AU.addRequired<LoopInfoWrapperPass>();
74 FunctionPass::getAnalysisUsage(AU);
75 }
76
77private:
78 LoopInfo *LI = nullptr;
79 const DataLayout *DL;
80
81 // Check this is a valid gather with correct alignment
82 bool isLegalTypeAndAlignment(unsigned NumElements, unsigned ElemSize,
83 Align Alignment);
84 // Check whether Ptr is hidden behind a bitcast and look through it
85 void lookThroughBitcast(Value *&Ptr);
86 // Decompose a ptr into Base and Offsets, potentially using a GEP to return a
87 // scalar base and vector offsets, or else fallback to using a base of 0 and
88 // offset of Ptr where possible.
89 Value *decomposePtr(Value *Ptr, Value *&Offsets, int &Scale,
90 FixedVectorType *Ty, Type *MemoryTy,
91 IRBuilder<> &Builder);
92 // Check for a getelementptr and deduce base and offsets from it, on success
93 // returning the base directly and the offsets indirectly using the Offsets
94 // argument
95 Value *decomposeGEP(Value *&Offsets, FixedVectorType *Ty,
96 GetElementPtrInst *GEP, IRBuilder<> &Builder);
97 // Compute the scale of this gather/scatter instruction
98 int computeScale(unsigned GEPElemSize, unsigned MemoryElemSize);
99 // If the value is a constant, or derived from constants via additions
100 // and multilications, return its numeric value
101 std::optional<int64_t> getIfConst(const Value *V);
102 // If Inst is an add instruction, check whether one summand is a
103 // constant. If so, scale this constant and return it together with
104 // the other summand.
105 std::pair<Value *, int64_t> getVarAndConst(Value *Inst, int TypeScale);
106
107 Instruction *lowerGather(IntrinsicInst *I);
108 // Create a gather from a base + vector of offsets
109 Instruction *tryCreateMaskedGatherOffset(IntrinsicInst *I, Value *Ptr,
110 Instruction *&Root,
111 IRBuilder<> &Builder);
112 // Create a gather from a vector of pointers
113 Instruction *tryCreateMaskedGatherBase(IntrinsicInst *I, Value *Ptr,
114 IRBuilder<> &Builder,
115 int64_t Increment = 0);
116 // Create an incrementing gather from a vector of pointers
117 Instruction *tryCreateMaskedGatherBaseWB(IntrinsicInst *I, Value *Ptr,
118 IRBuilder<> &Builder,
119 int64_t Increment = 0);
120
121 Instruction *lowerScatter(IntrinsicInst *I);
122 // Create a scatter to a base + vector of offsets
123 Instruction *tryCreateMaskedScatterOffset(IntrinsicInst *I, Value *Offsets,
124 IRBuilder<> &Builder);
125 // Create a scatter to a vector of pointers
126 Instruction *tryCreateMaskedScatterBase(IntrinsicInst *I, Value *Ptr,
127 IRBuilder<> &Builder,
128 int64_t Increment = 0);
129 // Create an incrementing scatter from a vector of pointers
130 Instruction *tryCreateMaskedScatterBaseWB(IntrinsicInst *I, Value *Ptr,
131 IRBuilder<> &Builder,
132 int64_t Increment = 0);
133
134 // QI gathers and scatters can increment their offsets on their own if
135 // the increment is a constant value (digit)
136 Instruction *tryCreateIncrementingGatScat(IntrinsicInst *I, Value *Ptr,
137 IRBuilder<> &Builder);
138 // QI gathers/scatters can increment their offsets on their own if the
139 // increment is a constant value (digit) - this creates a writeback QI
140 // gather/scatter
141 Instruction *tryCreateIncrementingWBGatScat(IntrinsicInst *I, Value *BasePtr,
142 Value *Ptr, unsigned TypeScale,
143 IRBuilder<> &Builder);
144
145 // Optimise the base and offsets of the given address
146 bool optimiseAddress(Value *Address, BasicBlock *BB, LoopInfo *LI);
147 // Try to fold consecutive geps together into one
148 Value *foldGEP(GetElementPtrInst *GEP, Value *&Offsets, unsigned &Scale,
149 IRBuilder<> &Builder);
150 // Check whether these offsets could be moved out of the loop they're in
151 bool optimiseOffsets(Value *Offsets, BasicBlock *BB, LoopInfo *LI);
152 // Pushes the given add out of the loop
153 void pushOutAdd(PHINode *&Phi, Value *OffsSecondOperand, unsigned StartIndex);
154 // Pushes the given mul or shl out of the loop
155 void pushOutMulShl(unsigned Opc, PHINode *&Phi, Value *IncrementPerRound,
156 Value *OffsSecondOperand, unsigned LoopIncrement,
157 IRBuilder<> &Builder);
158};
159
160} // end anonymous namespace
161
162char MVEGatherScatterLowering::ID = 0;
163
164INITIALIZE_PASS(MVEGatherScatterLowering, DEBUG_TYPE,static void *initializeMVEGatherScatterLoweringPassOnce(PassRegistry
&Registry) { PassInfo *PI = new PassInfo( "MVE gather/scattering lowering pass"
, "arm-mve-gather-scatter-lowering", &MVEGatherScatterLowering
::ID, PassInfo::NormalCtor_t(callDefaultCtor<MVEGatherScatterLowering
>), false, false); Registry.registerPass(*PI, true); return
PI; } static llvm::once_flag InitializeMVEGatherScatterLoweringPassFlag
; void llvm::initializeMVEGatherScatterLoweringPass(PassRegistry
&Registry) { llvm::call_once(InitializeMVEGatherScatterLoweringPassFlag
, initializeMVEGatherScatterLoweringPassOnce, std::ref(Registry
)); }
165 "MVE gather/scattering lowering pass", false, false)static void *initializeMVEGatherScatterLoweringPassOnce(PassRegistry
&Registry) { PassInfo *PI = new PassInfo( "MVE gather/scattering lowering pass"
, "arm-mve-gather-scatter-lowering", &MVEGatherScatterLowering
::ID, PassInfo::NormalCtor_t(callDefaultCtor<MVEGatherScatterLowering
>), false, false); Registry.registerPass(*PI, true); return
PI; } static llvm::once_flag InitializeMVEGatherScatterLoweringPassFlag
; void llvm::initializeMVEGatherScatterLoweringPass(PassRegistry
&Registry) { llvm::call_once(InitializeMVEGatherScatterLoweringPassFlag
, initializeMVEGatherScatterLoweringPassOnce, std::ref(Registry
)); }
166
167Pass *llvm::createMVEGatherScatterLoweringPass() {
168 return new MVEGatherScatterLowering();
169}
170
171bool MVEGatherScatterLowering::isLegalTypeAndAlignment(unsigned NumElements,
172 unsigned ElemSize,
173 Align Alignment) {
174 if (((NumElements == 4 &&
175 (ElemSize == 32 || ElemSize == 16 || ElemSize == 8)) ||
176 (NumElements == 8 && (ElemSize == 16 || ElemSize == 8)) ||
177 (NumElements == 16 && ElemSize == 8)) &&
178 Alignment >= ElemSize / 8)
179 return true;
180 LLVM_DEBUG(dbgs() << "masked gathers/scatters: instruction does not have "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: instruction does not have "
<< "valid alignment or vector type \n"; } } while (false
)
181 << "valid alignment or vector type \n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: instruction does not have "
<< "valid alignment or vector type \n"; } } while (false
)
;
182 return false;
183}
184
185static bool checkOffsetSize(Value *Offsets, unsigned TargetElemCount) {
186 // Offsets that are not of type <N x i32> are sign extended by the
187 // getelementptr instruction, and MVE gathers/scatters treat the offset as
188 // unsigned. Thus, if the element size is smaller than 32, we can only allow
189 // positive offsets - i.e., the offsets are not allowed to be variables we
190 // can't look into.
191 // Additionally, <N x i32> offsets have to either originate from a zext of a
192 // vector with element types smaller or equal the type of the gather we're
193 // looking at, or consist of constants that we can check are small enough
194 // to fit into the gather type.
195 // Thus we check that 0 < value < 2^TargetElemSize.
196 unsigned TargetElemSize = 128 / TargetElemCount;
38
'TargetElemSize' initialized to 128
197 unsigned OffsetElemSize = cast<FixedVectorType>(Offsets->getType())
39
The object is a 'CastReturnType'
198 ->getElementType()
199 ->getScalarSizeInBits();
200 if (OffsetElemSize != TargetElemSize || OffsetElemSize != 32) {
40
Assuming 'OffsetElemSize' is not equal to 'TargetElemSize'
201 Constant *ConstOff = dyn_cast<Constant>(Offsets);
41
Assuming 'Offsets' is a 'CastReturnType'
202 if (!ConstOff
41.1
'ConstOff' is non-null
41.1
'ConstOff' is non-null
)
42
Taking false branch
203 return false;
204 int64_t TargetElemMaxSize = (1ULL << TargetElemSize);
43
The result of the left shift is undefined due to shifting by '128', which is greater or equal to the width of type 'unsigned long long'
205 auto CheckValueSize = [TargetElemMaxSize](Value *OffsetElem) {
206 ConstantInt *OConst = dyn_cast<ConstantInt>(OffsetElem);
207 if (!OConst)
208 return false;
209 int SExtValue = OConst->getSExtValue();
210 if (SExtValue >= TargetElemMaxSize || SExtValue < 0)
211 return false;
212 return true;
213 };
214 if (isa<FixedVectorType>(ConstOff->getType())) {
215 for (unsigned i = 0; i < TargetElemCount; i++) {
216 if (!CheckValueSize(ConstOff->getAggregateElement(i)))
217 return false;
218 }
219 } else {
220 if (!CheckValueSize(ConstOff))
221 return false;
222 }
223 }
224 return true;
225}
226
227Value *MVEGatherScatterLowering::decomposePtr(Value *Ptr, Value *&Offsets,
228 int &Scale, FixedVectorType *Ty,
229 Type *MemoryTy,
230 IRBuilder<> &Builder) {
231 if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
232 if (Value *V = decomposeGEP(Offsets, Ty, GEP, Builder)) {
233 Scale =
234 computeScale(GEP->getSourceElementType()->getPrimitiveSizeInBits(),
235 MemoryTy->getScalarSizeInBits());
236 return Scale == -1 ? nullptr : V;
237 }
238 }
239
240 // If we couldn't use the GEP (or it doesn't exist), attempt to use a
241 // BasePtr of 0 with Ptr as the Offsets, so long as there are only 4
242 // elements.
243 FixedVectorType *PtrTy = cast<FixedVectorType>(Ptr->getType());
244 if (PtrTy->getNumElements() != 4 || MemoryTy->getScalarSizeInBits() == 32)
245 return nullptr;
246 Value *Zero = ConstantInt::get(Builder.getInt32Ty(), 0);
247 Value *BasePtr = Builder.CreateIntToPtr(Zero, Builder.getInt8PtrTy());
248 Offsets = Builder.CreatePtrToInt(
249 Ptr, FixedVectorType::get(Builder.getInt32Ty(), 4));
250 Scale = 0;
251 return BasePtr;
252}
253
254Value *MVEGatherScatterLowering::decomposeGEP(Value *&Offsets,
255 FixedVectorType *Ty,
256 GetElementPtrInst *GEP,
257 IRBuilder<> &Builder) {
258 if (!GEP) {
259 LLVM_DEBUG(dbgs() << "masked gathers/scatters: no getelementpointer "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: no getelementpointer "
<< "found\n"; } } while (false)
260 << "found\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: no getelementpointer "
<< "found\n"; } } while (false)
;
261 return nullptr;
262 }
263 LLVM_DEBUG(dbgs() << "masked gathers/scatters: getelementpointer found."do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: getelementpointer found."
<< " Looking at intrinsic for base + vector of offsets\n"
; } } while (false)
264 << " Looking at intrinsic for base + vector of offsets\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: getelementpointer found."
<< " Looking at intrinsic for base + vector of offsets\n"
; } } while (false)
;
265 Value *GEPPtr = GEP->getPointerOperand();
266 Offsets = GEP->getOperand(1);
267 if (GEPPtr->getType()->isVectorTy() ||
268 !isa<FixedVectorType>(Offsets->getType()))
269 return nullptr;
270
271 if (GEP->getNumOperands() != 2) {
272 LLVM_DEBUG(dbgs() << "masked gathers/scatters: getelementptr with too many"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: getelementptr with too many"
<< " operands. Expanding.\n"; } } while (false)
273 << " operands. Expanding.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: getelementptr with too many"
<< " operands. Expanding.\n"; } } while (false)
;
274 return nullptr;
275 }
276 Offsets = GEP->getOperand(1);
277 unsigned OffsetsElemCount =
278 cast<FixedVectorType>(Offsets->getType())->getNumElements();
279 // Paranoid check whether the number of parallel lanes is the same
280 assert(Ty->getNumElements() == OffsetsElemCount)(static_cast <bool> (Ty->getNumElements() == OffsetsElemCount
) ? void (0) : __assert_fail ("Ty->getNumElements() == OffsetsElemCount"
, "llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp", 280, __extension__
__PRETTY_FUNCTION__))
;
281
282 ZExtInst *ZextOffs = dyn_cast<ZExtInst>(Offsets);
283 if (ZextOffs)
284 Offsets = ZextOffs->getOperand(0);
285 FixedVectorType *OffsetType = cast<FixedVectorType>(Offsets->getType());
286
287 // If the offsets are already being zext-ed to <N x i32>, that relieves us of
288 // having to make sure that they won't overflow.
289 if (!ZextOffs || cast<FixedVectorType>(ZextOffs->getDestTy())
290 ->getElementType()
291 ->getScalarSizeInBits() != 32)
292 if (!checkOffsetSize(Offsets, OffsetsElemCount))
293 return nullptr;
294
295 // The offset sizes have been checked; if any truncating or zext-ing is
296 // required to fix them, do that now
297 if (Ty != Offsets->getType()) {
298 if ((Ty->getElementType()->getScalarSizeInBits() <
299 OffsetType->getElementType()->getScalarSizeInBits())) {
300 Offsets = Builder.CreateTrunc(Offsets, Ty);
301 } else {
302 Offsets = Builder.CreateZExt(Offsets, VectorType::getInteger(Ty));
303 }
304 }
305 // If none of the checks failed, return the gep's base pointer
306 LLVM_DEBUG(dbgs() << "masked gathers/scatters: found correct offsets\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: found correct offsets\n"
; } } while (false)
;
307 return GEPPtr;
308}
309
310void MVEGatherScatterLowering::lookThroughBitcast(Value *&Ptr) {
311 // Look through bitcast instruction if #elements is the same
312 if (auto *BitCast = dyn_cast<BitCastInst>(Ptr)) {
313 auto *BCTy = cast<FixedVectorType>(BitCast->getType());
314 auto *BCSrcTy = cast<FixedVectorType>(BitCast->getOperand(0)->getType());
315 if (BCTy->getNumElements() == BCSrcTy->getNumElements()) {
316 LLVM_DEBUG(dbgs() << "masked gathers/scatters: looking through "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: looking through "
<< "bitcast\n"; } } while (false)
317 << "bitcast\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: looking through "
<< "bitcast\n"; } } while (false)
;
318 Ptr = BitCast->getOperand(0);
319 }
320 }
321}
322
323int MVEGatherScatterLowering::computeScale(unsigned GEPElemSize,
324 unsigned MemoryElemSize) {
325 // This can be a 32bit load/store scaled by 4, a 16bit load/store scaled by 2,
326 // or a 8bit, 16bit or 32bit load/store scaled by 1
327 if (GEPElemSize == 32 && MemoryElemSize == 32)
328 return 2;
329 else if (GEPElemSize == 16 && MemoryElemSize == 16)
330 return 1;
331 else if (GEPElemSize == 8)
332 return 0;
333 LLVM_DEBUG(dbgs() << "masked gathers/scatters: incorrect scale. Can't "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: incorrect scale. Can't "
<< "create intrinsic\n"; } } while (false)
334 << "create intrinsic\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: incorrect scale. Can't "
<< "create intrinsic\n"; } } while (false)
;
335 return -1;
336}
337
338std::optional<int64_t> MVEGatherScatterLowering::getIfConst(const Value *V) {
339 const Constant *C = dyn_cast<Constant>(V);
340 if (C && C->getSplatValue())
341 return std::optional<int64_t>{C->getUniqueInteger().getSExtValue()};
342 if (!isa<Instruction>(V))
343 return std::optional<int64_t>{};
344
345 const Instruction *I = cast<Instruction>(V);
346 if (I->getOpcode() == Instruction::Add || I->getOpcode() == Instruction::Or ||
347 I->getOpcode() == Instruction::Mul ||
348 I->getOpcode() == Instruction::Shl) {
349 std::optional<int64_t> Op0 = getIfConst(I->getOperand(0));
350 std::optional<int64_t> Op1 = getIfConst(I->getOperand(1));
351 if (!Op0 || !Op1)
352 return std::optional<int64_t>{};
353 if (I->getOpcode() == Instruction::Add)
354 return std::optional<int64_t>{*Op0 + *Op1};
355 if (I->getOpcode() == Instruction::Mul)
356 return std::optional<int64_t>{*Op0 * *Op1};
357 if (I->getOpcode() == Instruction::Shl)
358 return std::optional<int64_t>{*Op0 << *Op1};
359 if (I->getOpcode() == Instruction::Or)
360 return std::optional<int64_t>{*Op0 | *Op1};
361 }
362 return std::optional<int64_t>{};
363}
364
365// Return true if I is an Or instruction that is equivalent to an add, due to
366// the operands having no common bits set.
367static bool isAddLikeOr(Instruction *I, const DataLayout &DL) {
368 return I->getOpcode() == Instruction::Or &&
369 haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1), DL);
370}
371
372std::pair<Value *, int64_t>
373MVEGatherScatterLowering::getVarAndConst(Value *Inst, int TypeScale) {
374 std::pair<Value *, int64_t> ReturnFalse =
375 std::pair<Value *, int64_t>(nullptr, 0);
376 // At this point, the instruction we're looking at must be an add or an
377 // add-like-or.
378 Instruction *Add = dyn_cast<Instruction>(Inst);
379 if (Add == nullptr ||
380 (Add->getOpcode() != Instruction::Add && !isAddLikeOr(Add, *DL)))
381 return ReturnFalse;
382
383 Value *Summand;
384 std::optional<int64_t> Const;
385 // Find out which operand the value that is increased is
386 if ((Const = getIfConst(Add->getOperand(0))))
387 Summand = Add->getOperand(1);
388 else if ((Const = getIfConst(Add->getOperand(1))))
389 Summand = Add->getOperand(0);
390 else
391 return ReturnFalse;
392
393 // Check that the constant is small enough for an incrementing gather
394 int64_t Immediate = *Const << TypeScale;
395 if (Immediate > 512 || Immediate < -512 || Immediate % 4 != 0)
396 return ReturnFalse;
397
398 return std::pair<Value *, int64_t>(Summand, Immediate);
399}
400
401Instruction *MVEGatherScatterLowering::lowerGather(IntrinsicInst *I) {
402 using namespace PatternMatch;
403 LLVM_DEBUG(dbgs() << "masked gathers: checking transform preconditions\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: checking transform preconditions\n"
<< *I << "\n"; } } while (false)
404 << *I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: checking transform preconditions\n"
<< *I << "\n"; } } while (false)
;
405
406 // @llvm.masked.gather.*(Ptrs, alignment, Mask, Src0)
407 // Attempt to turn the masked gather in I into a MVE intrinsic
408 // Potentially optimising the addressing modes as we do so.
409 auto *Ty = cast<FixedVectorType>(I->getType());
410 Value *Ptr = I->getArgOperand(0);
411 Align Alignment = cast<ConstantInt>(I->getArgOperand(1))->getAlignValue();
412 Value *Mask = I->getArgOperand(2);
413 Value *PassThru = I->getArgOperand(3);
414
415 if (!isLegalTypeAndAlignment(Ty->getNumElements(), Ty->getScalarSizeInBits(),
416 Alignment))
417 return nullptr;
418 lookThroughBitcast(Ptr);
419 assert(Ptr->getType()->isVectorTy() && "Unexpected pointer type")(static_cast <bool> (Ptr->getType()->isVectorTy()
&& "Unexpected pointer type") ? void (0) : __assert_fail
("Ptr->getType()->isVectorTy() && \"Unexpected pointer type\""
, "llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp", 419, __extension__
__PRETTY_FUNCTION__))
;
420
421 IRBuilder<> Builder(I->getContext());
422 Builder.SetInsertPoint(I);
423 Builder.SetCurrentDebugLocation(I->getDebugLoc());
424
425 Instruction *Root = I;
426
427 Instruction *Load = tryCreateIncrementingGatScat(I, Ptr, Builder);
428 if (!Load)
429 Load = tryCreateMaskedGatherOffset(I, Ptr, Root, Builder);
430 if (!Load)
431 Load = tryCreateMaskedGatherBase(I, Ptr, Builder);
432 if (!Load)
433 return nullptr;
434
435 if (!isa<UndefValue>(PassThru) && !match(PassThru, m_Zero())) {
436 LLVM_DEBUG(dbgs() << "masked gathers: found non-trivial passthru - "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: found non-trivial passthru - "
<< "creating select\n"; } } while (false)
437 << "creating select\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: found non-trivial passthru - "
<< "creating select\n"; } } while (false)
;
438 Load = SelectInst::Create(Mask, Load, PassThru);
439 Builder.Insert(Load);
440 }
441
442 Root->replaceAllUsesWith(Load);
443 Root->eraseFromParent();
444 if (Root != I)
445 // If this was an extending gather, we need to get rid of the sext/zext
446 // sext/zext as well as of the gather itself
447 I->eraseFromParent();
448
449 LLVM_DEBUG(dbgs() << "masked gathers: successfully built masked gather\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: successfully built masked gather\n"
<< *Load << "\n"; } } while (false)
450 << *Load << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: successfully built masked gather\n"
<< *Load << "\n"; } } while (false)
;
451 return Load;
452}
453
454Instruction *MVEGatherScatterLowering::tryCreateMaskedGatherBase(
455 IntrinsicInst *I, Value *Ptr, IRBuilder<> &Builder, int64_t Increment) {
456 using namespace PatternMatch;
457 auto *Ty = cast<FixedVectorType>(I->getType());
458 LLVM_DEBUG(dbgs() << "masked gathers: loading from vector of pointers\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: loading from vector of pointers\n"
; } } while (false)
;
459 if (Ty->getNumElements() != 4 || Ty->getScalarSizeInBits() != 32)
460 // Can't build an intrinsic for this
461 return nullptr;
462 Value *Mask = I->getArgOperand(2);
463 if (match(Mask, m_One()))
464 return Builder.CreateIntrinsic(Intrinsic::arm_mve_vldr_gather_base,
465 {Ty, Ptr->getType()},
466 {Ptr, Builder.getInt32(Increment)});
467 else
468 return Builder.CreateIntrinsic(
469 Intrinsic::arm_mve_vldr_gather_base_predicated,
470 {Ty, Ptr->getType(), Mask->getType()},
471 {Ptr, Builder.getInt32(Increment), Mask});
472}
473
474Instruction *MVEGatherScatterLowering::tryCreateMaskedGatherBaseWB(
475 IntrinsicInst *I, Value *Ptr, IRBuilder<> &Builder, int64_t Increment) {
476 using namespace PatternMatch;
477 auto *Ty = cast<FixedVectorType>(I->getType());
478 LLVM_DEBUG(dbgs() << "masked gathers: loading from vector of pointers with "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: loading from vector of pointers with "
<< "writeback\n"; } } while (false)
479 << "writeback\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: loading from vector of pointers with "
<< "writeback\n"; } } while (false)
;
480 if (Ty->getNumElements() != 4 || Ty->getScalarSizeInBits() != 32)
481 // Can't build an intrinsic for this
482 return nullptr;
483 Value *Mask = I->getArgOperand(2);
484 if (match(Mask, m_One()))
485 return Builder.CreateIntrinsic(Intrinsic::arm_mve_vldr_gather_base_wb,
486 {Ty, Ptr->getType()},
487 {Ptr, Builder.getInt32(Increment)});
488 else
489 return Builder.CreateIntrinsic(
490 Intrinsic::arm_mve_vldr_gather_base_wb_predicated,
491 {Ty, Ptr->getType(), Mask->getType()},
492 {Ptr, Builder.getInt32(Increment), Mask});
493}
494
495Instruction *MVEGatherScatterLowering::tryCreateMaskedGatherOffset(
496 IntrinsicInst *I, Value *Ptr, Instruction *&Root, IRBuilder<> &Builder) {
497 using namespace PatternMatch;
498
499 Type *MemoryTy = I->getType();
500 Type *ResultTy = MemoryTy;
501
502 unsigned Unsigned = 1;
503 // The size of the gather was already checked in isLegalTypeAndAlignment;
504 // if it was not a full vector width an appropriate extend should follow.
505 auto *Extend = Root;
506 bool TruncResult = false;
507 if (MemoryTy->getPrimitiveSizeInBits() < 128) {
508 if (I->hasOneUse()) {
509 // If the gather has a single extend of the correct type, use an extending
510 // gather and replace the ext. In which case the correct root to replace
511 // is not the CallInst itself, but the instruction which extends it.
512 Instruction* User = cast<Instruction>(*I->users().begin());
513 if (isa<SExtInst>(User) &&
514 User->getType()->getPrimitiveSizeInBits() == 128) {
515 LLVM_DEBUG(dbgs() << "masked gathers: Incorporating extend: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Incorporating extend: "
<< *User << "\n"; } } while (false)
516 << *User << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Incorporating extend: "
<< *User << "\n"; } } while (false)
;
517 Extend = User;
518 ResultTy = User->getType();
519 Unsigned = 0;
520 } else if (isa<ZExtInst>(User) &&
521 User->getType()->getPrimitiveSizeInBits() == 128) {
522 LLVM_DEBUG(dbgs() << "masked gathers: Incorporating extend: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Incorporating extend: "
<< *ResultTy << "\n"; } } while (false)
523 << *ResultTy << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Incorporating extend: "
<< *ResultTy << "\n"; } } while (false)
;
524 Extend = User;
525 ResultTy = User->getType();
526 }
527 }
528
529 // If an extend hasn't been found and the type is an integer, create an
530 // extending gather and truncate back to the original type.
531 if (ResultTy->getPrimitiveSizeInBits() < 128 &&
532 ResultTy->isIntOrIntVectorTy()) {
533 ResultTy = ResultTy->getWithNewBitWidth(
534 128 / cast<FixedVectorType>(ResultTy)->getNumElements());
535 TruncResult = true;
536 LLVM_DEBUG(dbgs() << "masked gathers: Small input type, truncing to: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Small input type, truncing to: "
<< *ResultTy << "\n"; } } while (false)
537 << *ResultTy << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Small input type, truncing to: "
<< *ResultTy << "\n"; } } while (false)
;
538 }
539
540 // The final size of the gather must be a full vector width
541 if (ResultTy->getPrimitiveSizeInBits() != 128) {
542 LLVM_DEBUG(dbgs() << "masked gathers: Extend needed but not provided "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Extend needed but not provided "
"from the correct type. Expanding\n"; } } while (false)
543 "from the correct type. Expanding\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers: Extend needed but not provided "
"from the correct type. Expanding\n"; } } while (false)
;
544 return nullptr;
545 }
546 }
547
548 Value *Offsets;
549 int Scale;
550 Value *BasePtr = decomposePtr(
551 Ptr, Offsets, Scale, cast<FixedVectorType>(ResultTy), MemoryTy, Builder);
552 if (!BasePtr)
553 return nullptr;
554
555 Root = Extend;
556 Value *Mask = I->getArgOperand(2);
557 Instruction *Load = nullptr;
558 if (!match(Mask, m_One()))
559 Load = Builder.CreateIntrinsic(
560 Intrinsic::arm_mve_vldr_gather_offset_predicated,
561 {ResultTy, BasePtr->getType(), Offsets->getType(), Mask->getType()},
562 {BasePtr, Offsets, Builder.getInt32(MemoryTy->getScalarSizeInBits()),
563 Builder.getInt32(Scale), Builder.getInt32(Unsigned), Mask});
564 else
565 Load = Builder.CreateIntrinsic(
566 Intrinsic::arm_mve_vldr_gather_offset,
567 {ResultTy, BasePtr->getType(), Offsets->getType()},
568 {BasePtr, Offsets, Builder.getInt32(MemoryTy->getScalarSizeInBits()),
569 Builder.getInt32(Scale), Builder.getInt32(Unsigned)});
570
571 if (TruncResult) {
572 Load = TruncInst::Create(Instruction::Trunc, Load, MemoryTy);
573 Builder.Insert(Load);
574 }
575 return Load;
576}
577
578Instruction *MVEGatherScatterLowering::lowerScatter(IntrinsicInst *I) {
579 using namespace PatternMatch;
580 LLVM_DEBUG(dbgs() << "masked scatters: checking transform preconditions\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: checking transform preconditions\n"
<< *I << "\n"; } } while (false)
581 << *I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: checking transform preconditions\n"
<< *I << "\n"; } } while (false)
;
582
583 // @llvm.masked.scatter.*(data, ptrs, alignment, mask)
584 // Attempt to turn the masked scatter in I into a MVE intrinsic
585 // Potentially optimising the addressing modes as we do so.
586 Value *Input = I->getArgOperand(0);
587 Value *Ptr = I->getArgOperand(1);
588 Align Alignment = cast<ConstantInt>(I->getArgOperand(2))->getAlignValue();
589 auto *Ty = cast<FixedVectorType>(Input->getType());
590
591 if (!isLegalTypeAndAlignment(Ty->getNumElements(), Ty->getScalarSizeInBits(),
592 Alignment))
593 return nullptr;
594
595 lookThroughBitcast(Ptr);
596 assert(Ptr->getType()->isVectorTy() && "Unexpected pointer type")(static_cast <bool> (Ptr->getType()->isVectorTy()
&& "Unexpected pointer type") ? void (0) : __assert_fail
("Ptr->getType()->isVectorTy() && \"Unexpected pointer type\""
, "llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp", 596, __extension__
__PRETTY_FUNCTION__))
;
597
598 IRBuilder<> Builder(I->getContext());
599 Builder.SetInsertPoint(I);
600 Builder.SetCurrentDebugLocation(I->getDebugLoc());
601
602 Instruction *Store = tryCreateIncrementingGatScat(I, Ptr, Builder);
603 if (!Store)
604 Store = tryCreateMaskedScatterOffset(I, Ptr, Builder);
605 if (!Store)
606 Store = tryCreateMaskedScatterBase(I, Ptr, Builder);
607 if (!Store)
608 return nullptr;
609
610 LLVM_DEBUG(dbgs() << "masked scatters: successfully built masked scatter\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: successfully built masked scatter\n"
<< *Store << "\n"; } } while (false)
611 << *Store << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: successfully built masked scatter\n"
<< *Store << "\n"; } } while (false)
;
612 I->eraseFromParent();
613 return Store;
614}
615
616Instruction *MVEGatherScatterLowering::tryCreateMaskedScatterBase(
617 IntrinsicInst *I, Value *Ptr, IRBuilder<> &Builder, int64_t Increment) {
618 using namespace PatternMatch;
619 Value *Input = I->getArgOperand(0);
620 auto *Ty = cast<FixedVectorType>(Input->getType());
621 // Only QR variants allow truncating
622 if (!(Ty->getNumElements() == 4 && Ty->getScalarSizeInBits() == 32)) {
623 // Can't build an intrinsic for this
624 return nullptr;
625 }
626 Value *Mask = I->getArgOperand(3);
627 // int_arm_mve_vstr_scatter_base(_predicated) addr, offset, data(, mask)
628 LLVM_DEBUG(dbgs() << "masked scatters: storing to a vector of pointers\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: storing to a vector of pointers\n"
; } } while (false)
;
629 if (match(Mask, m_One()))
630 return Builder.CreateIntrinsic(Intrinsic::arm_mve_vstr_scatter_base,
631 {Ptr->getType(), Input->getType()},
632 {Ptr, Builder.getInt32(Increment), Input});
633 else
634 return Builder.CreateIntrinsic(
635 Intrinsic::arm_mve_vstr_scatter_base_predicated,
636 {Ptr->getType(), Input->getType(), Mask->getType()},
637 {Ptr, Builder.getInt32(Increment), Input, Mask});
638}
639
640Instruction *MVEGatherScatterLowering::tryCreateMaskedScatterBaseWB(
641 IntrinsicInst *I, Value *Ptr, IRBuilder<> &Builder, int64_t Increment) {
642 using namespace PatternMatch;
643 Value *Input = I->getArgOperand(0);
644 auto *Ty = cast<FixedVectorType>(Input->getType());
645 LLVM_DEBUG(dbgs() << "masked scatters: storing to a vector of pointers "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: storing to a vector of pointers "
<< "with writeback\n"; } } while (false)
646 << "with writeback\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: storing to a vector of pointers "
<< "with writeback\n"; } } while (false)
;
647 if (Ty->getNumElements() != 4 || Ty->getScalarSizeInBits() != 32)
648 // Can't build an intrinsic for this
649 return nullptr;
650 Value *Mask = I->getArgOperand(3);
651 if (match(Mask, m_One()))
652 return Builder.CreateIntrinsic(Intrinsic::arm_mve_vstr_scatter_base_wb,
653 {Ptr->getType(), Input->getType()},
654 {Ptr, Builder.getInt32(Increment), Input});
655 else
656 return Builder.CreateIntrinsic(
657 Intrinsic::arm_mve_vstr_scatter_base_wb_predicated,
658 {Ptr->getType(), Input->getType(), Mask->getType()},
659 {Ptr, Builder.getInt32(Increment), Input, Mask});
660}
661
662Instruction *MVEGatherScatterLowering::tryCreateMaskedScatterOffset(
663 IntrinsicInst *I, Value *Ptr, IRBuilder<> &Builder) {
664 using namespace PatternMatch;
665 Value *Input = I->getArgOperand(0);
666 Value *Mask = I->getArgOperand(3);
667 Type *InputTy = Input->getType();
668 Type *MemoryTy = InputTy;
669
670 LLVM_DEBUG(dbgs() << "masked scatters: getelementpointer found. Storing"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: getelementpointer found. Storing"
<< " to base + vector of offsets\n"; } } while (false)
671 << " to base + vector of offsets\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: getelementpointer found. Storing"
<< " to base + vector of offsets\n"; } } while (false)
;
672 // If the input has been truncated, try to integrate that trunc into the
673 // scatter instruction (we don't care about alignment here)
674 if (TruncInst *Trunc = dyn_cast<TruncInst>(Input)) {
675 Value *PreTrunc = Trunc->getOperand(0);
676 Type *PreTruncTy = PreTrunc->getType();
677 if (PreTruncTy->getPrimitiveSizeInBits() == 128) {
678 Input = PreTrunc;
679 InputTy = PreTruncTy;
680 }
681 }
682 bool ExtendInput = false;
683 if (InputTy->getPrimitiveSizeInBits() < 128 &&
684 InputTy->isIntOrIntVectorTy()) {
685 // If we can't find a trunc to incorporate into the instruction, create an
686 // implicit one with a zext, so that we can still create a scatter. We know
687 // that the input type is 4x/8x/16x and of type i8/i16/i32, so any type
688 // smaller than 128 bits will divide evenly into a 128bit vector.
689 InputTy = InputTy->getWithNewBitWidth(
690 128 / cast<FixedVectorType>(InputTy)->getNumElements());
691 ExtendInput = true;
692 LLVM_DEBUG(dbgs() << "masked scatters: Small input type, will extend:\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: Small input type, will extend:\n"
<< *Input << "\n"; } } while (false)
693 << *Input << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: Small input type, will extend:\n"
<< *Input << "\n"; } } while (false)
;
694 }
695 if (InputTy->getPrimitiveSizeInBits() != 128) {
696 LLVM_DEBUG(dbgs() << "masked scatters: cannot create scatters for "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: cannot create scatters for "
"non-standard input types. Expanding.\n"; } } while (false)
697 "non-standard input types. Expanding.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked scatters: cannot create scatters for "
"non-standard input types. Expanding.\n"; } } while (false)
;
698 return nullptr;
699 }
700
701 Value *Offsets;
702 int Scale;
703 Value *BasePtr = decomposePtr(
704 Ptr, Offsets, Scale, cast<FixedVectorType>(InputTy), MemoryTy, Builder);
705 if (!BasePtr)
706 return nullptr;
707
708 if (ExtendInput)
709 Input = Builder.CreateZExt(Input, InputTy);
710 if (!match(Mask, m_One()))
711 return Builder.CreateIntrinsic(
712 Intrinsic::arm_mve_vstr_scatter_offset_predicated,
713 {BasePtr->getType(), Offsets->getType(), Input->getType(),
714 Mask->getType()},
715 {BasePtr, Offsets, Input,
716 Builder.getInt32(MemoryTy->getScalarSizeInBits()),
717 Builder.getInt32(Scale), Mask});
718 else
719 return Builder.CreateIntrinsic(
720 Intrinsic::arm_mve_vstr_scatter_offset,
721 {BasePtr->getType(), Offsets->getType(), Input->getType()},
722 {BasePtr, Offsets, Input,
723 Builder.getInt32(MemoryTy->getScalarSizeInBits()),
724 Builder.getInt32(Scale)});
725}
726
727Instruction *MVEGatherScatterLowering::tryCreateIncrementingGatScat(
728 IntrinsicInst *I, Value *Ptr, IRBuilder<> &Builder) {
729 FixedVectorType *Ty;
730 if (I->getIntrinsicID() == Intrinsic::masked_gather)
731 Ty = cast<FixedVectorType>(I->getType());
732 else
733 Ty = cast<FixedVectorType>(I->getArgOperand(0)->getType());
734
735 // Incrementing gathers only exist for v4i32
736 if (Ty->getNumElements() != 4 || Ty->getScalarSizeInBits() != 32)
737 return nullptr;
738 // Incrementing gathers are not beneficial outside of a loop
739 Loop *L = LI->getLoopFor(I->getParent());
740 if (L == nullptr)
741 return nullptr;
742
743 // Decompose the GEP into Base and Offsets
744 GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
745 Value *Offsets;
746 Value *BasePtr = decomposeGEP(Offsets, Ty, GEP, Builder);
747 if (!BasePtr)
748 return nullptr;
749
750 LLVM_DEBUG(dbgs() << "masked gathers/scatters: trying to build incrementing "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: trying to build incrementing "
"wb gather/scatter\n"; } } while (false)
751 "wb gather/scatter\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: trying to build incrementing "
"wb gather/scatter\n"; } } while (false)
;
752
753 // The gep was in charge of making sure the offsets are scaled correctly
754 // - calculate that factor so it can be applied by hand
755 int TypeScale =
756 computeScale(DL->getTypeSizeInBits(GEP->getOperand(0)->getType()),
757 DL->getTypeSizeInBits(GEP->getType()) /
758 cast<FixedVectorType>(GEP->getType())->getNumElements());
759 if (TypeScale == -1)
760 return nullptr;
761
762 if (GEP->hasOneUse()) {
763 // Only in this case do we want to build a wb gather, because the wb will
764 // change the phi which does affect other users of the gep (which will still
765 // be using the phi in the old way)
766 if (auto *Load = tryCreateIncrementingWBGatScat(I, BasePtr, Offsets,
767 TypeScale, Builder))
768 return Load;
769 }
770
771 LLVM_DEBUG(dbgs() << "masked gathers/scatters: trying to build incrementing "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: trying to build incrementing "
"non-wb gather/scatter\n"; } } while (false)
772 "non-wb gather/scatter\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: trying to build incrementing "
"non-wb gather/scatter\n"; } } while (false)
;
773
774 std::pair<Value *, int64_t> Add = getVarAndConst(Offsets, TypeScale);
775 if (Add.first == nullptr)
776 return nullptr;
777 Value *OffsetsIncoming = Add.first;
778 int64_t Immediate = Add.second;
779
780 // Make sure the offsets are scaled correctly
781 Instruction *ScaledOffsets = BinaryOperator::Create(
782 Instruction::Shl, OffsetsIncoming,
783 Builder.CreateVectorSplat(Ty->getNumElements(), Builder.getInt32(TypeScale)),
784 "ScaledIndex", I);
785 // Add the base to the offsets
786 OffsetsIncoming = BinaryOperator::Create(
787 Instruction::Add, ScaledOffsets,
788 Builder.CreateVectorSplat(
789 Ty->getNumElements(),
790 Builder.CreatePtrToInt(
791 BasePtr,
792 cast<VectorType>(ScaledOffsets->getType())->getElementType())),
793 "StartIndex", I);
794
795 if (I->getIntrinsicID() == Intrinsic::masked_gather)
796 return tryCreateMaskedGatherBase(I, OffsetsIncoming, Builder, Immediate);
797 else
798 return tryCreateMaskedScatterBase(I, OffsetsIncoming, Builder, Immediate);
799}
800
801Instruction *MVEGatherScatterLowering::tryCreateIncrementingWBGatScat(
802 IntrinsicInst *I, Value *BasePtr, Value *Offsets, unsigned TypeScale,
803 IRBuilder<> &Builder) {
804 // Check whether this gather's offset is incremented by a constant - if so,
805 // and the load is of the right type, we can merge this into a QI gather
806 Loop *L = LI->getLoopFor(I->getParent());
807 // Offsets that are worth merging into this instruction will be incremented
808 // by a constant, thus we're looking for an add of a phi and a constant
809 PHINode *Phi = dyn_cast<PHINode>(Offsets);
810 if (Phi == nullptr || Phi->getNumIncomingValues() != 2 ||
811 Phi->getParent() != L->getHeader() || Phi->getNumUses() != 2)
812 // No phi means no IV to write back to; if there is a phi, we expect it
813 // to have exactly two incoming values; the only phis we are interested in
814 // will be loop IV's and have exactly two uses, one in their increment and
815 // one in the gather's gep
816 return nullptr;
817
818 unsigned IncrementIndex =
819 Phi->getIncomingBlock(0) == L->getLoopLatch() ? 0 : 1;
820 // Look through the phi to the phi increment
821 Offsets = Phi->getIncomingValue(IncrementIndex);
822
823 std::pair<Value *, int64_t> Add = getVarAndConst(Offsets, TypeScale);
824 if (Add.first == nullptr)
825 return nullptr;
826 Value *OffsetsIncoming = Add.first;
827 int64_t Immediate = Add.second;
828 if (OffsetsIncoming != Phi)
829 // Then the increment we are looking at is not an increment of the
830 // induction variable, and we don't want to do a writeback
831 return nullptr;
832
833 Builder.SetInsertPoint(&Phi->getIncomingBlock(1 - IncrementIndex)->back());
834 unsigned NumElems =
835 cast<FixedVectorType>(OffsetsIncoming->getType())->getNumElements();
836
837 // Make sure the offsets are scaled correctly
838 Instruction *ScaledOffsets = BinaryOperator::Create(
839 Instruction::Shl, Phi->getIncomingValue(1 - IncrementIndex),
840 Builder.CreateVectorSplat(NumElems, Builder.getInt32(TypeScale)),
841 "ScaledIndex", &Phi->getIncomingBlock(1 - IncrementIndex)->back());
842 // Add the base to the offsets
843 OffsetsIncoming = BinaryOperator::Create(
844 Instruction::Add, ScaledOffsets,
845 Builder.CreateVectorSplat(
846 NumElems,
847 Builder.CreatePtrToInt(
848 BasePtr,
849 cast<VectorType>(ScaledOffsets->getType())->getElementType())),
850 "StartIndex", &Phi->getIncomingBlock(1 - IncrementIndex)->back());
851 // The gather is pre-incrementing
852 OffsetsIncoming = BinaryOperator::Create(
853 Instruction::Sub, OffsetsIncoming,
854 Builder.CreateVectorSplat(NumElems, Builder.getInt32(Immediate)),
855 "PreIncrementStartIndex",
856 &Phi->getIncomingBlock(1 - IncrementIndex)->back());
857 Phi->setIncomingValue(1 - IncrementIndex, OffsetsIncoming);
858
859 Builder.SetInsertPoint(I);
860
861 Instruction *EndResult;
862 Instruction *NewInduction;
863 if (I->getIntrinsicID() == Intrinsic::masked_gather) {
864 // Build the incrementing gather
865 Value *Load = tryCreateMaskedGatherBaseWB(I, Phi, Builder, Immediate);
866 // One value to be handed to whoever uses the gather, one is the loop
867 // increment
868 EndResult = ExtractValueInst::Create(Load, 0, "Gather");
869 NewInduction = ExtractValueInst::Create(Load, 1, "GatherIncrement");
870 Builder.Insert(EndResult);
871 Builder.Insert(NewInduction);
872 } else {
873 // Build the incrementing scatter
874 EndResult = NewInduction =
875 tryCreateMaskedScatterBaseWB(I, Phi, Builder, Immediate);
876 }
877 Instruction *AddInst = cast<Instruction>(Offsets);
878 AddInst->replaceAllUsesWith(NewInduction);
879 AddInst->eraseFromParent();
880 Phi->setIncomingValue(IncrementIndex, NewInduction);
881
882 return EndResult;
883}
884
885void MVEGatherScatterLowering::pushOutAdd(PHINode *&Phi,
886 Value *OffsSecondOperand,
887 unsigned StartIndex) {
888 LLVM_DEBUG(dbgs() << "masked gathers/scatters: optimising add instruction\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: optimising add instruction\n"
; } } while (false)
;
889 Instruction *InsertionPoint =
890 &cast<Instruction>(Phi->getIncomingBlock(StartIndex)->back());
891 // Initialize the phi with a vector that contains a sum of the constants
892 Instruction *NewIndex = BinaryOperator::Create(
893 Instruction::Add, Phi->getIncomingValue(StartIndex), OffsSecondOperand,
894 "PushedOutAdd", InsertionPoint);
895 unsigned IncrementIndex = StartIndex == 0 ? 1 : 0;
896
897 // Order such that start index comes first (this reduces mov's)
898 Phi->addIncoming(NewIndex, Phi->getIncomingBlock(StartIndex));
899 Phi->addIncoming(Phi->getIncomingValue(IncrementIndex),
900 Phi->getIncomingBlock(IncrementIndex));
901 Phi->removeIncomingValue(IncrementIndex);
902 Phi->removeIncomingValue(StartIndex);
903}
904
905void MVEGatherScatterLowering::pushOutMulShl(unsigned Opcode, PHINode *&Phi,
906 Value *IncrementPerRound,
907 Value *OffsSecondOperand,
908 unsigned LoopIncrement,
909 IRBuilder<> &Builder) {
910 LLVM_DEBUG(dbgs() << "masked gathers/scatters: optimising mul instruction\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: optimising mul instruction\n"
; } } while (false)
;
911
912 // Create a new scalar add outside of the loop and transform it to a splat
913 // by which loop variable can be incremented
914 Instruction *InsertionPoint = &cast<Instruction>(
915 Phi->getIncomingBlock(LoopIncrement == 1 ? 0 : 1)->back());
916
917 // Create a new index
918 Value *StartIndex =
919 BinaryOperator::Create((Instruction::BinaryOps)Opcode,
920 Phi->getIncomingValue(LoopIncrement == 1 ? 0 : 1),
921 OffsSecondOperand, "PushedOutMul", InsertionPoint);
922
923 Instruction *Product =
924 BinaryOperator::Create((Instruction::BinaryOps)Opcode, IncrementPerRound,
925 OffsSecondOperand, "Product", InsertionPoint);
926 // Increment NewIndex by Product instead of the multiplication
927 Instruction *NewIncrement = BinaryOperator::Create(
928 Instruction::Add, Phi, Product, "IncrementPushedOutMul",
929 cast<Instruction>(Phi->getIncomingBlock(LoopIncrement)->back())
930 .getPrevNode());
931
932 Phi->addIncoming(StartIndex,
933 Phi->getIncomingBlock(LoopIncrement == 1 ? 0 : 1));
934 Phi->addIncoming(NewIncrement, Phi->getIncomingBlock(LoopIncrement));
935 Phi->removeIncomingValue((unsigned)0);
936 Phi->removeIncomingValue((unsigned)0);
937}
938
939// Check whether all usages of this instruction are as offsets of
940// gathers/scatters or simple arithmetics only used by gathers/scatters
941static bool hasAllGatScatUsers(Instruction *I, const DataLayout &DL) {
942 if (I->hasNUses(0)) {
943 return false;
944 }
945 bool Gatscat = true;
946 for (User *U : I->users()) {
947 if (!isa<Instruction>(U))
948 return false;
949 if (isa<GetElementPtrInst>(U) ||
950 isGatherScatter(dyn_cast<IntrinsicInst>(U))) {
951 return Gatscat;
952 } else {
953 unsigned OpCode = cast<Instruction>(U)->getOpcode();
954 if ((OpCode == Instruction::Add || OpCode == Instruction::Mul ||
955 OpCode == Instruction::Shl ||
956 isAddLikeOr(cast<Instruction>(U), DL)) &&
957 hasAllGatScatUsers(cast<Instruction>(U), DL)) {
958 continue;
959 }
960 return false;
961 }
962 }
963 return Gatscat;
964}
965
966bool MVEGatherScatterLowering::optimiseOffsets(Value *Offsets, BasicBlock *BB,
967 LoopInfo *LI) {
968 LLVM_DEBUG(dbgs() << "masked gathers/scatters: trying to optimize: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: trying to optimize: "
<< *Offsets << "\n"; } } while (false)
969 << *Offsets << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: trying to optimize: "
<< *Offsets << "\n"; } } while (false)
;
970 // Optimise the addresses of gathers/scatters by moving invariant
971 // calculations out of the loop
972 if (!isa<Instruction>(Offsets))
973 return false;
974 Instruction *Offs = cast<Instruction>(Offsets);
975 if (Offs->getOpcode() != Instruction::Add && !isAddLikeOr(Offs, *DL) &&
976 Offs->getOpcode() != Instruction::Mul &&
977 Offs->getOpcode() != Instruction::Shl)
978 return false;
979 Loop *L = LI->getLoopFor(BB);
980 if (L == nullptr)
981 return false;
982 if (!Offs->hasOneUse()) {
983 if (!hasAllGatScatUsers(Offs, *DL))
984 return false;
985 }
986
987 // Find out which, if any, operand of the instruction
988 // is a phi node
989 PHINode *Phi;
990 int OffsSecondOp;
991 if (isa<PHINode>(Offs->getOperand(0))) {
992 Phi = cast<PHINode>(Offs->getOperand(0));
993 OffsSecondOp = 1;
994 } else if (isa<PHINode>(Offs->getOperand(1))) {
995 Phi = cast<PHINode>(Offs->getOperand(1));
996 OffsSecondOp = 0;
997 } else {
998 bool Changed = false;
999 if (isa<Instruction>(Offs->getOperand(0)) &&
1000 L->contains(cast<Instruction>(Offs->getOperand(0))))
1001 Changed |= optimiseOffsets(Offs->getOperand(0), BB, LI);
1002 if (isa<Instruction>(Offs->getOperand(1)) &&
1003 L->contains(cast<Instruction>(Offs->getOperand(1))))
1004 Changed |= optimiseOffsets(Offs->getOperand(1), BB, LI);
1005 if (!Changed)
1006 return false;
1007 if (isa<PHINode>(Offs->getOperand(0))) {
1008 Phi = cast<PHINode>(Offs->getOperand(0));
1009 OffsSecondOp = 1;
1010 } else if (isa<PHINode>(Offs->getOperand(1))) {
1011 Phi = cast<PHINode>(Offs->getOperand(1));
1012 OffsSecondOp = 0;
1013 } else {
1014 return false;
1015 }
1016 }
1017 // A phi node we want to perform this function on should be from the
1018 // loop header.
1019 if (Phi->getParent() != L->getHeader())
1020 return false;
1021
1022 // We're looking for a simple add recurrence.
1023 BinaryOperator *IncInstruction;
1024 Value *Start, *IncrementPerRound;
1025 if (!matchSimpleRecurrence(Phi, IncInstruction, Start, IncrementPerRound) ||
1026 IncInstruction->getOpcode() != Instruction::Add)
1027 return false;
1028
1029 int IncrementingBlock = Phi->getIncomingValue(0) == IncInstruction ? 0 : 1;
1030
1031 // Get the value that is added to/multiplied with the phi
1032 Value *OffsSecondOperand = Offs->getOperand(OffsSecondOp);
1033
1034 if (IncrementPerRound->getType() != OffsSecondOperand->getType() ||
1035 !L->isLoopInvariant(OffsSecondOperand))
1036 // Something has gone wrong, abort
1037 return false;
1038
1039 // Only proceed if the increment per round is a constant or an instruction
1040 // which does not originate from within the loop
1041 if (!isa<Constant>(IncrementPerRound) &&
1042 !(isa<Instruction>(IncrementPerRound) &&
1043 !L->contains(cast<Instruction>(IncrementPerRound))))
1044 return false;
1045
1046 // If the phi is not used by anything else, we can just adapt it when
1047 // replacing the instruction; if it is, we'll have to duplicate it
1048 PHINode *NewPhi;
1049 if (Phi->getNumUses() == 2) {
1050 // No other users -> reuse existing phi (One user is the instruction
1051 // we're looking at, the other is the phi increment)
1052 if (IncInstruction->getNumUses() != 1) {
1053 // If the incrementing instruction does have more users than
1054 // our phi, we need to copy it
1055 IncInstruction = BinaryOperator::Create(
1056 Instruction::BinaryOps(IncInstruction->getOpcode()), Phi,
1057 IncrementPerRound, "LoopIncrement", IncInstruction);
1058 Phi->setIncomingValue(IncrementingBlock, IncInstruction);
1059 }
1060 NewPhi = Phi;
1061 } else {
1062 // There are other users -> create a new phi
1063 NewPhi = PHINode::Create(Phi->getType(), 2, "NewPhi", Phi);
1064 // Copy the incoming values of the old phi
1065 NewPhi->addIncoming(Phi->getIncomingValue(IncrementingBlock == 1 ? 0 : 1),
1066 Phi->getIncomingBlock(IncrementingBlock == 1 ? 0 : 1));
1067 IncInstruction = BinaryOperator::Create(
1068 Instruction::BinaryOps(IncInstruction->getOpcode()), NewPhi,
1069 IncrementPerRound, "LoopIncrement", IncInstruction);
1070 NewPhi->addIncoming(IncInstruction,
1071 Phi->getIncomingBlock(IncrementingBlock));
1072 IncrementingBlock = 1;
1073 }
1074
1075 IRBuilder<> Builder(BB->getContext());
1076 Builder.SetInsertPoint(Phi);
1077 Builder.SetCurrentDebugLocation(Offs->getDebugLoc());
1078
1079 switch (Offs->getOpcode()) {
1080 case Instruction::Add:
1081 case Instruction::Or:
1082 pushOutAdd(NewPhi, OffsSecondOperand, IncrementingBlock == 1 ? 0 : 1);
1083 break;
1084 case Instruction::Mul:
1085 case Instruction::Shl:
1086 pushOutMulShl(Offs->getOpcode(), NewPhi, IncrementPerRound,
1087 OffsSecondOperand, IncrementingBlock, Builder);
1088 break;
1089 default:
1090 return false;
1091 }
1092 LLVM_DEBUG(dbgs() << "masked gathers/scatters: simplified loop variable "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: simplified loop variable "
<< "add/mul\n"; } } while (false)
1093 << "add/mul\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: simplified loop variable "
<< "add/mul\n"; } } while (false)
;
1094
1095 // The instruction has now been "absorbed" into the phi value
1096 Offs->replaceAllUsesWith(NewPhi);
1097 if (Offs->hasNUses(0))
1098 Offs->eraseFromParent();
1099 // Clean up the old increment in case it's unused because we built a new
1100 // one
1101 if (IncInstruction->hasNUses(0))
1102 IncInstruction->eraseFromParent();
1103
1104 return true;
1105}
1106
1107static Value *CheckAndCreateOffsetAdd(Value *X, unsigned ScaleX, Value *Y,
1108 unsigned ScaleY, IRBuilder<> &Builder) {
1109 // Splat the non-vector value to a vector of the given type - if the value is
1110 // a constant (and its value isn't too big), we can even use this opportunity
1111 // to scale it to the size of the vector elements
1112 auto FixSummands = [&Builder](FixedVectorType *&VT, Value *&NonVectorVal) {
1113 ConstantInt *Const;
1114 if ((Const = dyn_cast<ConstantInt>(NonVectorVal)) &&
1115 VT->getElementType() != NonVectorVal->getType()) {
1116 unsigned TargetElemSize = VT->getElementType()->getPrimitiveSizeInBits();
1117 uint64_t N = Const->getZExtValue();
1118 if (N < (unsigned)(1 << (TargetElemSize - 1))) {
1119 NonVectorVal = Builder.CreateVectorSplat(
1120 VT->getNumElements(), Builder.getIntN(TargetElemSize, N));
1121 return;
1122 }
1123 }
1124 NonVectorVal =
1125 Builder.CreateVectorSplat(VT->getNumElements(), NonVectorVal);
1126 };
1127
1128 FixedVectorType *XElType = dyn_cast<FixedVectorType>(X->getType());
14
Assuming the object is a 'CastReturnType'
1129 FixedVectorType *YElType = dyn_cast<FixedVectorType>(Y->getType());
15
Assuming the object is not a 'CastReturnType'
1130 // If one of X, Y is not a vector, we have to splat it in order
1131 // to add the two of them.
1132 if (XElType
15.1
'XElType' is non-null
15.1
'XElType' is non-null
&& !YElType
15.2
'YElType' is null
15.2
'YElType' is null
) {
16
Taking true branch
1133 FixSummands(XElType, Y);
1134 YElType = cast<FixedVectorType>(Y->getType());
17
The object is a 'CastReturnType'
1135 } else if (YElType && !XElType) {
1136 FixSummands(YElType, X);
1137 XElType = cast<FixedVectorType>(X->getType());
1138 }
1139 assert(XElType && YElType && "Unknown vector types")(static_cast <bool> (XElType && YElType &&
"Unknown vector types") ? void (0) : __assert_fail ("XElType && YElType && \"Unknown vector types\""
, "llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp", 1139, __extension__
__PRETTY_FUNCTION__))
;
18
'?' condition is true
1140 // Check that the summands are of compatible types
1141 if (XElType != YElType) {
19
Assuming 'XElType' is equal to 'YElType'
20
Taking false branch
1142 LLVM_DEBUG(dbgs() << "masked gathers/scatters: incompatible gep offsets\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "masked gathers/scatters: incompatible gep offsets\n"
; } } while (false)
;
1143 return nullptr;
1144 }
1145
1146 if (XElType->getElementType()->getScalarSizeInBits() != 32) {
21
Assuming the condition is true
22
Taking true branch
1147 // Check that by adding the vectors we do not accidentally
1148 // create an overflow
1149 Constant *ConstX = dyn_cast<Constant>(X);
23
'X' is a 'Constant'
1150 Constant *ConstY = dyn_cast<Constant>(Y);
24
Assuming 'Y' is a 'CastReturnType'
1151 if (!ConstX
24.1
'ConstX' is non-null
24.1
'ConstX' is non-null
|| !ConstY
24.2
'ConstY' is non-null
24.2
'ConstY' is non-null
)
25
Taking false branch
1152 return nullptr;
1153 unsigned TargetElemSize = 128 / XElType->getNumElements();
1154 for (unsigned i = 0; i < XElType->getNumElements(); i++) {
26
Loop condition is true. Entering loop body
31
Assuming the condition is false
32
Loop condition is false. Execution continues on line 1167
1155 ConstantInt *ConstXEl =
1156 dyn_cast<ConstantInt>(ConstX->getAggregateElement(i));
27
Assuming the object is a 'CastReturnType'
1157 ConstantInt *ConstYEl =
1158 dyn_cast<ConstantInt>(ConstY->getAggregateElement(i));
28
Assuming the object is a 'CastReturnType'
1159 if (!ConstXEl
28.1
'ConstXEl' is non-null
28.1
'ConstXEl' is non-null
|| !ConstYEl
28.2
'ConstYEl' is non-null
28.2
'ConstYEl' is non-null
||
30
Taking false branch
1160 ConstXEl->getZExtValue() * ScaleX +
29
Assuming the condition is false
1161 ConstYEl->getZExtValue() * ScaleY >=
1162 (unsigned)(1 << (TargetElemSize - 1)))
1163 return nullptr;
1164 }
1165 }
1166
1167 Value *XScale = Builder.CreateVectorSplat(
1168 XElType->getNumElements(),
1169 Builder.getIntN(XElType->getScalarSizeInBits(), ScaleX));
1170 Value *YScale = Builder.CreateVectorSplat(
1171 YElType->getNumElements(),
1172 Builder.getIntN(YElType->getScalarSizeInBits(), ScaleY));
1173 Value *Add = Builder.CreateAdd(Builder.CreateMul(X, XScale),
33
Calling 'IRBuilderBase::CreateAdd'
36
Returning from 'IRBuilderBase::CreateAdd'
1174 Builder.CreateMul(Y, YScale));
1175
1176 if (checkOffsetSize(Add, XElType->getNumElements()))
37
Calling 'checkOffsetSize'
1177 return Add;
1178 else
1179 return nullptr;
1180}
1181
1182Value *MVEGatherScatterLowering::foldGEP(GetElementPtrInst *GEP,
1183 Value *&Offsets, unsigned &Scale,
1184 IRBuilder<> &Builder) {
1185 Value *GEPPtr = GEP->getPointerOperand();
1186 Offsets = GEP->getOperand(1);
1187 Scale = DL->getTypeAllocSize(GEP->getSourceElementType());
1188 // We only merge geps with constant offsets, because only for those
1189 // we can make sure that we do not cause an overflow
1190 if (GEP->getNumIndices() != 1 || !isa<Constant>(Offsets))
1
Assuming the condition is false
2
Assuming 'Offsets' is a 'class llvm::Constant &'
3
Taking false branch
7
Assuming the condition is false
8
Assuming 'Offsets' is a 'class llvm::Constant &'
9
Taking false branch
1191 return nullptr;
1192 if (GetElementPtrInst *BaseGEP = dyn_cast<GetElementPtrInst>(GEPPtr)) {
4
Assuming 'BaseGEP' is non-null
5
Taking true branch
10
Assuming 'BaseGEP' is non-null
11
Taking true branch
1193 // Merge the two geps into one
1194 Value *BaseBasePtr = foldGEP(BaseGEP, Offsets, Scale, Builder);
6
Calling 'MVEGatherScatterLowering::foldGEP'
1195 if (!BaseBasePtr
11.1
'BaseBasePtr' is non-null
11.1
'BaseBasePtr' is non-null
)
12
Taking false branch
1196 return nullptr;
1197 Offsets = CheckAndCreateOffsetAdd(
13
Calling 'CheckAndCreateOffsetAdd'
1198 Offsets, Scale, GEP->getOperand(1),
1199 DL->getTypeAllocSize(GEP->getSourceElementType()), Builder);
1200 if (Offsets == nullptr)
1201 return nullptr;
1202 Scale = 1; // Scale is always an i8 at this point.
1203 return BaseBasePtr;
1204 }
1205 return GEPPtr;
1206}
1207
1208bool MVEGatherScatterLowering::optimiseAddress(Value *Address, BasicBlock *BB,
1209 LoopInfo *LI) {
1210 GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Address);
1211 if (!GEP)
1212 return false;
1213 bool Changed = false;
1214 if (GEP->hasOneUse() && isa<GetElementPtrInst>(GEP->getPointerOperand())) {
1215 IRBuilder<> Builder(GEP->getContext());
1216 Builder.SetInsertPoint(GEP);
1217 Builder.SetCurrentDebugLocation(GEP->getDebugLoc());
1218 Value *Offsets;
1219 unsigned Scale;
1220 Value *Base = foldGEP(GEP, Offsets, Scale, Builder);
1221 // We only want to merge the geps if there is a real chance that they can be
1222 // used by an MVE gather; thus the offset has to have the correct size
1223 // (always i32 if it is not of vector type) and the base has to be a
1224 // pointer.
1225 if (Offsets && Base && Base != GEP) {
1226 assert(Scale == 1 && "Expected to fold GEP to a scale of 1")(static_cast <bool> (Scale == 1 && "Expected to fold GEP to a scale of 1"
) ? void (0) : __assert_fail ("Scale == 1 && \"Expected to fold GEP to a scale of 1\""
, "llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp", 1226, __extension__
__PRETTY_FUNCTION__))
;
1227 Type *BaseTy = Builder.getInt8PtrTy();
1228 if (auto *VecTy = dyn_cast<FixedVectorType>(Base->getType()))
1229 BaseTy = FixedVectorType::get(BaseTy, VecTy);
1230 GetElementPtrInst *NewAddress = GetElementPtrInst::Create(
1231 Builder.getInt8Ty(), Builder.CreateBitCast(Base, BaseTy), Offsets,
1232 "gep.merged", GEP);
1233 LLVM_DEBUG(dbgs() << "Folded GEP: " << *GEPdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "Folded GEP: "
<< *GEP << "\n new : " << *NewAddress
<< "\n"; } } while (false)
1234 << "\n new : " << *NewAddress << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("arm-mve-gather-scatter-lowering")) { dbgs() << "Folded GEP: "
<< *GEP << "\n new : " << *NewAddress
<< "\n"; } } while (false)
;
1235 GEP->replaceAllUsesWith(
1236 Builder.CreateBitCast(NewAddress, GEP->getType()));
1237 GEP = NewAddress;
1238 Changed = true;
1239 }
1240 }
1241 Changed |= optimiseOffsets(GEP->getOperand(1), GEP->getParent(), LI);
1242 return Changed;
1243}
1244
1245bool MVEGatherScatterLowering::runOnFunction(Function &F) {
1246 if (!EnableMaskedGatherScatters)
1247 return false;
1248 auto &TPC = getAnalysis<TargetPassConfig>();
1249 auto &TM = TPC.getTM<TargetMachine>();
1250 auto *ST = &TM.getSubtarget<ARMSubtarget>(F);
1251 if (!ST->hasMVEIntegerOps())
1252 return false;
1253 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1254 DL = &F.getParent()->getDataLayout();
1255 SmallVector<IntrinsicInst *, 4> Gathers;
1256 SmallVector<IntrinsicInst *, 4> Scatters;
1257
1258 bool Changed = false;
1259
1260 for (BasicBlock &BB : F) {
1261 Changed |= SimplifyInstructionsInBlock(&BB);
1262
1263 for (Instruction &I : BB) {
1264 IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
1265 if (II && II->getIntrinsicID() == Intrinsic::masked_gather &&
1266 isa<FixedVectorType>(II->getType())) {
1267 Gathers.push_back(II);
1268 Changed |= optimiseAddress(II->getArgOperand(0), II->getParent(), LI);
1269 } else if (II && II->getIntrinsicID() == Intrinsic::masked_scatter &&
1270 isa<FixedVectorType>(II->getArgOperand(0)->getType())) {
1271 Scatters.push_back(II);
1272 Changed |= optimiseAddress(II->getArgOperand(1), II->getParent(), LI);
1273 }
1274 }
1275 }
1276 for (unsigned i = 0; i < Gathers.size(); i++) {
1277 IntrinsicInst *I = Gathers[i];
1278 Instruction *L = lowerGather(I);
1279 if (L == nullptr)
1280 continue;
1281
1282 // Get rid of any now dead instructions
1283 SimplifyInstructionsInBlock(L->getParent());
1284 Changed = true;
1285 }
1286
1287 for (unsigned i = 0; i < Scatters.size(); i++) {
1288 IntrinsicInst *I = Scatters[i];
1289 Instruction *S = lowerScatter(I);
1290 if (S == nullptr)
1291 continue;
1292
1293 // Get rid of any now dead instructions
1294 SimplifyInstructionsInBlock(S->getParent());
1295 Changed = true;
1296 }
1297 return Changed;
1298}

/build/source/llvm/include/llvm/IR/IRBuilder.h

1//===- llvm/IRBuilder.h - Builder for LLVM Instructions ---------*- C++ -*-===//
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// This file defines the IRBuilder class, which is used as a convenient way
10// to create LLVM instructions with a consistent and simplified interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_IR_IRBUILDER_H
15#define LLVM_IR_IRBUILDER_H
16
17#include "llvm-c/Types.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/IR/BasicBlock.h"
23#include "llvm/IR/Constant.h"
24#include "llvm/IR/ConstantFolder.h"
25#include "llvm/IR/Constants.h"
26#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/DebugLoc.h"
28#include "llvm/IR/DerivedTypes.h"
29#include "llvm/IR/FPEnv.h"
30#include "llvm/IR/Function.h"
31#include "llvm/IR/GlobalVariable.h"
32#include "llvm/IR/InstrTypes.h"
33#include "llvm/IR/Instruction.h"
34#include "llvm/IR/Instructions.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/LLVMContext.h"
37#include "llvm/IR/Module.h"
38#include "llvm/IR/Operator.h"
39#include "llvm/IR/Type.h"
40#include "llvm/IR/Value.h"
41#include "llvm/IR/ValueHandle.h"
42#include "llvm/Support/AtomicOrdering.h"
43#include "llvm/Support/CBindingWrapping.h"
44#include "llvm/Support/Casting.h"
45#include <cassert>
46#include <cstdint>
47#include <functional>
48#include <optional>
49#include <utility>
50
51namespace llvm {
52
53class APInt;
54class Use;
55
56/// This provides the default implementation of the IRBuilder
57/// 'InsertHelper' method that is called whenever an instruction is created by
58/// IRBuilder and needs to be inserted.
59///
60/// By default, this inserts the instruction at the insertion point.
61class IRBuilderDefaultInserter {
62public:
63 virtual ~IRBuilderDefaultInserter();
64
65 virtual void InsertHelper(Instruction *I, const Twine &Name,
66 BasicBlock *BB,
67 BasicBlock::iterator InsertPt) const {
68 if (BB)
69 I->insertInto(BB, InsertPt);
70 I->setName(Name);
71 }
72};
73
74/// Provides an 'InsertHelper' that calls a user-provided callback after
75/// performing the default insertion.
76class IRBuilderCallbackInserter : public IRBuilderDefaultInserter {
77 std::function<void(Instruction *)> Callback;
78
79public:
80 ~IRBuilderCallbackInserter() override;
81
82 IRBuilderCallbackInserter(std::function<void(Instruction *)> Callback)
83 : Callback(std::move(Callback)) {}
84
85 void InsertHelper(Instruction *I, const Twine &Name,
86 BasicBlock *BB,
87 BasicBlock::iterator InsertPt) const override {
88 IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt);
89 Callback(I);
90 }
91};
92
93/// Common base class shared among various IRBuilders.
94class IRBuilderBase {
95 /// Pairs of (metadata kind, MDNode *) that should be added to all newly
96 /// created instructions, like !dbg metadata.
97 SmallVector<std::pair<unsigned, MDNode *>, 2> MetadataToCopy;
98
99 /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not
100 /// null. If \p MD is null, remove the entry with \p Kind.
101 void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) {
102 if (!MD) {
103 erase_if(MetadataToCopy, [Kind](const std::pair<unsigned, MDNode *> &KV) {
104 return KV.first == Kind;
105 });
106 return;
107 }
108
109 for (auto &KV : MetadataToCopy)
110 if (KV.first == Kind) {
111 KV.second = MD;
112 return;
113 }
114
115 MetadataToCopy.emplace_back(Kind, MD);
116 }
117
118protected:
119 BasicBlock *BB;
120 BasicBlock::iterator InsertPt;
121 LLVMContext &Context;
122 const IRBuilderFolder &Folder;
123 const IRBuilderDefaultInserter &Inserter;
124
125 MDNode *DefaultFPMathTag;
126 FastMathFlags FMF;
127
128 bool IsFPConstrained = false;
129 fp::ExceptionBehavior DefaultConstrainedExcept = fp::ebStrict;
130 RoundingMode DefaultConstrainedRounding = RoundingMode::Dynamic;
131
132 ArrayRef<OperandBundleDef> DefaultOperandBundles;
133
134public:
135 IRBuilderBase(LLVMContext &context, const IRBuilderFolder &Folder,
136 const IRBuilderDefaultInserter &Inserter, MDNode *FPMathTag,
137 ArrayRef<OperandBundleDef> OpBundles)
138 : Context(context), Folder(Folder), Inserter(Inserter),
139 DefaultFPMathTag(FPMathTag), DefaultOperandBundles(OpBundles) {
140 ClearInsertionPoint();
141 }
142
143 /// Insert and return the specified instruction.
144 template<typename InstTy>
145 InstTy *Insert(InstTy *I, const Twine &Name = "") const {
146 Inserter.InsertHelper(I, Name, BB, InsertPt);
147 AddMetadataToInst(I);
148 return I;
149 }
150
151 /// No-op overload to handle constants.
152 Constant *Insert(Constant *C, const Twine& = "") const {
153 return C;
154 }
155
156 Value *Insert(Value *V, const Twine &Name = "") const {
157 if (Instruction *I = dyn_cast<Instruction>(V))
158 return Insert(I, Name);
159 assert(isa<Constant>(V))(static_cast <bool> (isa<Constant>(V)) ? void (0)
: __assert_fail ("isa<Constant>(V)", "llvm/include/llvm/IR/IRBuilder.h"
, 159, __extension__ __PRETTY_FUNCTION__))
;
160 return V;
161 }
162
163 //===--------------------------------------------------------------------===//
164 // Builder configuration methods
165 //===--------------------------------------------------------------------===//
166
167 /// Clear the insertion point: created instructions will not be
168 /// inserted into a block.
169 void ClearInsertionPoint() {
170 BB = nullptr;
171 InsertPt = BasicBlock::iterator();
172 }
173
174 BasicBlock *GetInsertBlock() const { return BB; }
175 BasicBlock::iterator GetInsertPoint() const { return InsertPt; }
176 LLVMContext &getContext() const { return Context; }
177
178 /// This specifies that created instructions should be appended to the
179 /// end of the specified block.
180 void SetInsertPoint(BasicBlock *TheBB) {
181 BB = TheBB;
182 InsertPt = BB->end();
183 }
184
185 /// This specifies that created instructions should be inserted before
186 /// the specified instruction.
187 void SetInsertPoint(Instruction *I) {
188 BB = I->getParent();
189 InsertPt = I->getIterator();
190 assert(InsertPt != BB->end() && "Can't read debug loc from end()")(static_cast <bool> (InsertPt != BB->end() &&
"Can't read debug loc from end()") ? void (0) : __assert_fail
("InsertPt != BB->end() && \"Can't read debug loc from end()\""
, "llvm/include/llvm/IR/IRBuilder.h", 190, __extension__ __PRETTY_FUNCTION__
))
;
191 SetCurrentDebugLocation(I->getDebugLoc());
192 }
193
194 /// This specifies that created instructions should be inserted at the
195 /// specified point.
196 void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) {
197 BB = TheBB;
198 InsertPt = IP;
199 if (IP != TheBB->end())
200 SetCurrentDebugLocation(IP->getDebugLoc());
201 }
202
203 /// This specifies that created instructions should inserted at the beginning
204 /// end of the specified function, but after already existing static alloca
205 /// instructions that are at the start.
206 void SetInsertPointPastAllocas(Function *F) {
207 BB = &F->getEntryBlock();
208 InsertPt = BB->getFirstNonPHIOrDbgOrAlloca();
209 }
210
211 /// Set location information used by debugging information.
212 void SetCurrentDebugLocation(DebugLoc L) {
213 AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode());
214 }
215
216 /// Collect metadata with IDs \p MetadataKinds from \p Src which should be
217 /// added to all created instructions. Entries present in MedataDataToCopy but
218 /// not on \p Src will be dropped from MetadataToCopy.
219 void CollectMetadataToCopy(Instruction *Src,
220 ArrayRef<unsigned> MetadataKinds) {
221 for (unsigned K : MetadataKinds)
222 AddOrRemoveMetadataToCopy(K, Src->getMetadata(K));
223 }
224
225 /// Get location information used by debugging information.
226 DebugLoc getCurrentDebugLocation() const;
227
228 /// If this builder has a current debug location, set it on the
229 /// specified instruction.
230 void SetInstDebugLocation(Instruction *I) const;
231
232 /// Add all entries in MetadataToCopy to \p I.
233 void AddMetadataToInst(Instruction *I) const {
234 for (const auto &KV : MetadataToCopy)
235 I->setMetadata(KV.first, KV.second);
236 }
237
238 /// Get the return type of the current function that we're emitting
239 /// into.
240 Type *getCurrentFunctionReturnType() const;
241
242 /// InsertPoint - A saved insertion point.
243 class InsertPoint {
244 BasicBlock *Block = nullptr;
245 BasicBlock::iterator Point;
246
247 public:
248 /// Creates a new insertion point which doesn't point to anything.
249 InsertPoint() = default;
250
251 /// Creates a new insertion point at the given location.
252 InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint)
253 : Block(InsertBlock), Point(InsertPoint) {}
254
255 /// Returns true if this insert point is set.
256 bool isSet() const { return (Block != nullptr); }
257
258 BasicBlock *getBlock() const { return Block; }
259 BasicBlock::iterator getPoint() const { return Point; }
260 };
261
262 /// Returns the current insert point.
263 InsertPoint saveIP() const {
264 return InsertPoint(GetInsertBlock(), GetInsertPoint());
265 }
266
267 /// Returns the current insert point, clearing it in the process.
268 InsertPoint saveAndClearIP() {
269 InsertPoint IP(GetInsertBlock(), GetInsertPoint());
270 ClearInsertionPoint();
271 return IP;
272 }
273
274 /// Sets the current insert point to a previously-saved location.
275 void restoreIP(InsertPoint IP) {
276 if (IP.isSet())
277 SetInsertPoint(IP.getBlock(), IP.getPoint());
278 else
279 ClearInsertionPoint();
280 }
281
282 /// Get the floating point math metadata being used.
283 MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; }
284
285 /// Get the flags to be applied to created floating point ops
286 FastMathFlags getFastMathFlags() const { return FMF; }
287
288 FastMathFlags &getFastMathFlags() { return FMF; }
289
290 /// Clear the fast-math flags.
291 void clearFastMathFlags() { FMF.clear(); }
292
293 /// Set the floating point math metadata to be used.
294 void setDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; }
295
296 /// Set the fast-math flags to be used with generated fp-math operators
297 void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; }
298
299 /// Enable/Disable use of constrained floating point math. When
300 /// enabled the CreateF<op>() calls instead create constrained
301 /// floating point intrinsic calls. Fast math flags are unaffected
302 /// by this setting.
303 void setIsFPConstrained(bool IsCon) { IsFPConstrained = IsCon; }
304
305 /// Query for the use of constrained floating point math
306 bool getIsFPConstrained() { return IsFPConstrained; }
307
308 /// Set the exception handling to be used with constrained floating point
309 void setDefaultConstrainedExcept(fp::ExceptionBehavior NewExcept) {
310#ifndef NDEBUG
311 std::optional<StringRef> ExceptStr =
312 convertExceptionBehaviorToStr(NewExcept);
313 assert(ExceptStr && "Garbage strict exception behavior!")(static_cast <bool> (ExceptStr && "Garbage strict exception behavior!"
) ? void (0) : __assert_fail ("ExceptStr && \"Garbage strict exception behavior!\""
, "llvm/include/llvm/IR/IRBuilder.h", 313, __extension__ __PRETTY_FUNCTION__
))
;
314#endif
315 DefaultConstrainedExcept = NewExcept;
316 }
317
318 /// Set the rounding mode handling to be used with constrained floating point
319 void setDefaultConstrainedRounding(RoundingMode NewRounding) {
320#ifndef NDEBUG
321 std::optional<StringRef> RoundingStr =
322 convertRoundingModeToStr(NewRounding);
323 assert(RoundingStr && "Garbage strict rounding mode!")(static_cast <bool> (RoundingStr && "Garbage strict rounding mode!"
) ? void (0) : __assert_fail ("RoundingStr && \"Garbage strict rounding mode!\""
, "llvm/include/llvm/IR/IRBuilder.h", 323, __extension__ __PRETTY_FUNCTION__
))
;
324#endif
325 DefaultConstrainedRounding = NewRounding;
326 }
327
328 /// Get the exception handling used with constrained floating point
329 fp::ExceptionBehavior getDefaultConstrainedExcept() {
330 return DefaultConstrainedExcept;
331 }
332
333 /// Get the rounding mode handling used with constrained floating point
334 RoundingMode getDefaultConstrainedRounding() {
335 return DefaultConstrainedRounding;
336 }
337
338 void setConstrainedFPFunctionAttr() {
339 assert(BB && "Must have a basic block to set any function attributes!")(static_cast <bool> (BB && "Must have a basic block to set any function attributes!"
) ? void (0) : __assert_fail ("BB && \"Must have a basic block to set any function attributes!\""
, "llvm/include/llvm/IR/IRBuilder.h", 339, __extension__ __PRETTY_FUNCTION__
))
;
340
341 Function *F = BB->getParent();
342 if (!F->hasFnAttribute(Attribute::StrictFP)) {
343 F->addFnAttr(Attribute::StrictFP);
344 }
345 }
346
347 void setConstrainedFPCallAttr(CallBase *I) {
348 I->addFnAttr(Attribute::StrictFP);
349 }
350
351 void setDefaultOperandBundles(ArrayRef<OperandBundleDef> OpBundles) {
352 DefaultOperandBundles = OpBundles;
353 }
354
355 //===--------------------------------------------------------------------===//
356 // RAII helpers.
357 //===--------------------------------------------------------------------===//
358
359 // RAII object that stores the current insertion point and restores it
360 // when the object is destroyed. This includes the debug location.
361 class InsertPointGuard {
362 IRBuilderBase &Builder;
363 AssertingVH<BasicBlock> Block;
364 BasicBlock::iterator Point;
365 DebugLoc DbgLoc;
366
367 public:
368 InsertPointGuard(IRBuilderBase &B)
369 : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()),
370 DbgLoc(B.getCurrentDebugLocation()) {}
371
372 InsertPointGuard(const InsertPointGuard &) = delete;
373 InsertPointGuard &operator=(const InsertPointGuard &) = delete;
374
375 ~InsertPointGuard() {
376 Builder.restoreIP(InsertPoint(Block, Point));
377 Builder.SetCurrentDebugLocation(DbgLoc);
378 }
379 };
380
381 // RAII object that stores the current fast math settings and restores
382 // them when the object is destroyed.
383 class FastMathFlagGuard {
384 IRBuilderBase &Builder;
385 FastMathFlags FMF;
386 MDNode *FPMathTag;
387 bool IsFPConstrained;
388 fp::ExceptionBehavior DefaultConstrainedExcept;
389 RoundingMode DefaultConstrainedRounding;
390
391 public:
392 FastMathFlagGuard(IRBuilderBase &B)
393 : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag),
394 IsFPConstrained(B.IsFPConstrained),
395 DefaultConstrainedExcept(B.DefaultConstrainedExcept),
396 DefaultConstrainedRounding(B.DefaultConstrainedRounding) {}
397
398 FastMathFlagGuard(const FastMathFlagGuard &) = delete;
399 FastMathFlagGuard &operator=(const FastMathFlagGuard &) = delete;
400
401 ~FastMathFlagGuard() {
402 Builder.FMF = FMF;
403 Builder.DefaultFPMathTag = FPMathTag;
404 Builder.IsFPConstrained = IsFPConstrained;
405 Builder.DefaultConstrainedExcept = DefaultConstrainedExcept;
406 Builder.DefaultConstrainedRounding = DefaultConstrainedRounding;
407 }
408 };
409
410 // RAII object that stores the current default operand bundles and restores
411 // them when the object is destroyed.
412 class OperandBundlesGuard {
413 IRBuilderBase &Builder;
414 ArrayRef<OperandBundleDef> DefaultOperandBundles;
415
416 public:
417 OperandBundlesGuard(IRBuilderBase &B)
418 : Builder(B), DefaultOperandBundles(B.DefaultOperandBundles) {}
419
420 OperandBundlesGuard(const OperandBundlesGuard &) = delete;
421 OperandBundlesGuard &operator=(const OperandBundlesGuard &) = delete;
422
423 ~OperandBundlesGuard() {
424 Builder.DefaultOperandBundles = DefaultOperandBundles;
425 }
426 };
427
428
429 //===--------------------------------------------------------------------===//
430 // Miscellaneous creation methods.
431 //===--------------------------------------------------------------------===//
432
433 /// Make a new global variable with initializer type i8*
434 ///
435 /// Make a new global variable with an initializer that has array of i8 type
436 /// filled in with the null terminated string value specified. The new global
437 /// variable will be marked mergable with any others of the same contents. If
438 /// Name is specified, it is the name of the global variable created.
439 ///
440 /// If no module is given via \p M, it is take from the insertion point basic
441 /// block.
442 GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "",
443 unsigned AddressSpace = 0,
444 Module *M = nullptr);
445
446 /// Get a constant value representing either true or false.
447 ConstantInt *getInt1(bool V) {
448 return ConstantInt::get(getInt1Ty(), V);
449 }
450
451 /// Get the constant value for i1 true.
452 ConstantInt *getTrue() {
453 return ConstantInt::getTrue(Context);
454 }
455
456 /// Get the constant value for i1 false.
457 ConstantInt *getFalse() {
458 return ConstantInt::getFalse(Context);
459 }
460
461 /// Get a constant 8-bit value.
462 ConstantInt *getInt8(uint8_t C) {
463 return ConstantInt::get(getInt8Ty(), C);
464 }
465
466 /// Get a constant 16-bit value.
467 ConstantInt *getInt16(uint16_t C) {
468 return ConstantInt::get(getInt16Ty(), C);
469 }
470
471 /// Get a constant 32-bit value.
472 ConstantInt *getInt32(uint32_t C) {
473 return ConstantInt::get(getInt32Ty(), C);
474 }
475
476 /// Get a constant 64-bit value.
477 ConstantInt *getInt64(uint64_t C) {
478 return ConstantInt::get(getInt64Ty(), C);
479 }
480
481 /// Get a constant N-bit value, zero extended or truncated from
482 /// a 64-bit value.
483 ConstantInt *getIntN(unsigned N, uint64_t C) {
484 return ConstantInt::get(getIntNTy(N), C);
485 }
486
487 /// Get a constant integer value.
488 ConstantInt *getInt(const APInt &AI) {
489 return ConstantInt::get(Context, AI);
490 }
491
492 //===--------------------------------------------------------------------===//
493 // Type creation methods
494 //===--------------------------------------------------------------------===//
495
496 /// Fetch the type representing a single bit
497 IntegerType *getInt1Ty() {
498 return Type::getInt1Ty(Context);
499 }
500
501 /// Fetch the type representing an 8-bit integer.
502 IntegerType *getInt8Ty() {
503 return Type::getInt8Ty(Context);
504 }
505
506 /// Fetch the type representing a 16-bit integer.
507 IntegerType *getInt16Ty() {
508 return Type::getInt16Ty(Context);
509 }
510
511 /// Fetch the type representing a 32-bit integer.
512 IntegerType *getInt32Ty() {
513 return Type::getInt32Ty(Context);
514 }
515
516 /// Fetch the type representing a 64-bit integer.
517 IntegerType *getInt64Ty() {
518 return Type::getInt64Ty(Context);
519 }
520
521 /// Fetch the type representing a 128-bit integer.
522 IntegerType *getInt128Ty() { return Type::getInt128Ty(Context); }
523
524 /// Fetch the type representing an N-bit integer.
525 IntegerType *getIntNTy(unsigned N) {
526 return Type::getIntNTy(Context, N);
527 }
528
529 /// Fetch the type representing a 16-bit floating point value.
530 Type *getHalfTy() {
531 return Type::getHalfTy(Context);
532 }
533
534 /// Fetch the type representing a 16-bit brain floating point value.
535 Type *getBFloatTy() {
536 return Type::getBFloatTy(Context);
537 }
538
539 /// Fetch the type representing a 32-bit floating point value.
540 Type *getFloatTy() {
541 return Type::getFloatTy(Context);
542 }
543
544 /// Fetch the type representing a 64-bit floating point value.
545 Type *getDoubleTy() {
546 return Type::getDoubleTy(Context);
547 }
548
549 /// Fetch the type representing void.
550 Type *getVoidTy() {
551 return Type::getVoidTy(Context);
552 }
553
554 /// Fetch the type representing a pointer.
555 PointerType *getPtrTy(unsigned AddrSpace = 0) {
556 return PointerType::get(Context, AddrSpace);
557 }
558
559 /// Fetch the type representing a pointer to an 8-bit integer value.
560 PointerType *getInt8PtrTy(unsigned AddrSpace = 0) {
561 return Type::getInt8PtrTy(Context, AddrSpace);
562 }
563
564 /// Fetch the type of an integer with size at least as big as that of a
565 /// pointer in the given address space.
566 IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) {
567 return DL.getIntPtrType(Context, AddrSpace);
568 }
569
570 /// Fetch the type of an integer that should be used to index GEP operations
571 /// within AddressSpace.
572 IntegerType *getIndexTy(const DataLayout &DL, unsigned AddrSpace) {
573 return DL.getIndexType(Context, AddrSpace);
574 }
575
576 //===--------------------------------------------------------------------===//
577 // Intrinsic creation methods
578 //===--------------------------------------------------------------------===//
579
580 /// Create and insert a memset to the specified pointer and the
581 /// specified value.
582 ///
583 /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
584 /// specified, it will be added to the instruction. Likewise with alias.scope
585 /// and noalias tags.
586 CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size,
587 MaybeAlign Align, bool isVolatile = false,
588 MDNode *TBAATag = nullptr, MDNode *ScopeTag = nullptr,
589 MDNode *NoAliasTag = nullptr) {
590 return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile,
591 TBAATag, ScopeTag, NoAliasTag);
592 }
593
594 CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, MaybeAlign Align,
595 bool isVolatile = false, MDNode *TBAATag = nullptr,
596 MDNode *ScopeTag = nullptr,
597 MDNode *NoAliasTag = nullptr);
598
599 CallInst *CreateMemSetInline(Value *Dst, MaybeAlign DstAlign, Value *Val,
600 Value *Size, bool IsVolatile = false,
601 MDNode *TBAATag = nullptr,
602 MDNode *ScopeTag = nullptr,
603 MDNode *NoAliasTag = nullptr);
604
605 /// Create and insert an element unordered-atomic memset of the region of
606 /// memory starting at the given pointer to the given value.
607 ///
608 /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
609 /// specified, it will be added to the instruction. Likewise with alias.scope
610 /// and noalias tags.
611 CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val,
612 uint64_t Size, Align Alignment,
613 uint32_t ElementSize,
614 MDNode *TBAATag = nullptr,
615 MDNode *ScopeTag = nullptr,
616 MDNode *NoAliasTag = nullptr) {
617 return CreateElementUnorderedAtomicMemSet(Ptr, Val, getInt64(Size),
618 Align(Alignment), ElementSize,
619 TBAATag, ScopeTag, NoAliasTag);
620 }
621
622 CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val,
623 Value *Size, Align Alignment,
624 uint32_t ElementSize,
625 MDNode *TBAATag = nullptr,
626 MDNode *ScopeTag = nullptr,
627 MDNode *NoAliasTag = nullptr);
628
629 /// Create and insert a memcpy between the specified pointers.
630 ///
631 /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
632 /// specified, it will be added to the instruction. Likewise with alias.scope
633 /// and noalias tags.
634 CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src,
635 MaybeAlign SrcAlign, uint64_t Size,
636 bool isVolatile = false, MDNode *TBAATag = nullptr,
637 MDNode *TBAAStructTag = nullptr,
638 MDNode *ScopeTag = nullptr,
639 MDNode *NoAliasTag = nullptr) {
640 return CreateMemCpy(Dst, DstAlign, Src, SrcAlign, getInt64(Size),
641 isVolatile, TBAATag, TBAAStructTag, ScopeTag,
642 NoAliasTag);
643 }
644
645 CallInst *CreateMemTransferInst(
646 Intrinsic::ID IntrID, Value *Dst, MaybeAlign DstAlign, Value *Src,
647 MaybeAlign SrcAlign, Value *Size, bool isVolatile = false,
648 MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
649 MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr);
650
651 CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src,
652 MaybeAlign SrcAlign, Value *Size,
653 bool isVolatile = false, MDNode *TBAATag = nullptr,
654 MDNode *TBAAStructTag = nullptr,
655 MDNode *ScopeTag = nullptr,
656 MDNode *NoAliasTag = nullptr) {
657 return CreateMemTransferInst(Intrinsic::memcpy, Dst, DstAlign, Src,
658 SrcAlign, Size, isVolatile, TBAATag,
659 TBAAStructTag, ScopeTag, NoAliasTag);
660 }
661
662 CallInst *
663 CreateMemCpyInline(Value *Dst, MaybeAlign DstAlign, Value *Src,
664 MaybeAlign SrcAlign, Value *Size, bool IsVolatile = false,
665 MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
666 MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr);
667
668 /// Create and insert an element unordered-atomic memcpy between the
669 /// specified pointers.
670 ///
671 /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, respectively.
672 ///
673 /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
674 /// specified, it will be added to the instruction. Likewise with alias.scope
675 /// and noalias tags.
676 CallInst *CreateElementUnorderedAtomicMemCpy(
677 Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size,
678 uint32_t ElementSize, MDNode *TBAATag = nullptr,
679 MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
680 MDNode *NoAliasTag = nullptr);
681
682 CallInst *CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src,
683 MaybeAlign SrcAlign, uint64_t Size,
684 bool isVolatile = false, MDNode *TBAATag = nullptr,
685 MDNode *ScopeTag = nullptr,
686 MDNode *NoAliasTag = nullptr) {
687 return CreateMemMove(Dst, DstAlign, Src, SrcAlign, getInt64(Size),
688 isVolatile, TBAATag, ScopeTag, NoAliasTag);
689 }
690
691 CallInst *CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src,
692 MaybeAlign SrcAlign, Value *Size,
693 bool isVolatile = false, MDNode *TBAATag = nullptr,
694 MDNode *ScopeTag = nullptr,
695 MDNode *NoAliasTag = nullptr);
696
697 /// \brief Create and insert an element unordered-atomic memmove between the
698 /// specified pointers.
699 ///
700 /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers,
701 /// respectively.
702 ///
703 /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
704 /// specified, it will be added to the instruction. Likewise with alias.scope
705 /// and noalias tags.
706 CallInst *CreateElementUnorderedAtomicMemMove(
707 Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size,
708 uint32_t ElementSize, MDNode *TBAATag = nullptr,
709 MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
710 MDNode *NoAliasTag = nullptr);
711
712private:
713 CallInst *getReductionIntrinsic(Intrinsic::ID ID, Value *Src);
714
715public:
716 /// Create a sequential vector fadd reduction intrinsic of the source vector.
717 /// The first parameter is a scalar accumulator value. An unordered reduction
718 /// can be created by adding the reassoc fast-math flag to the resulting
719 /// sequential reduction.
720 CallInst *CreateFAddReduce(Value *Acc, Value *Src);
721
722 /// Create a sequential vector fmul reduction intrinsic of the source vector.
723 /// The first parameter is a scalar accumulator value. An unordered reduction
724 /// can be created by adding the reassoc fast-math flag to the resulting
725 /// sequential reduction.
726 CallInst *CreateFMulReduce(Value *Acc, Value *Src);
727
728 /// Create a vector int add reduction intrinsic of the source vector.
729 CallInst *CreateAddReduce(Value *Src);
730
731 /// Create a vector int mul reduction intrinsic of the source vector.
732 CallInst *CreateMulReduce(Value *Src);
733
734 /// Create a vector int AND reduction intrinsic of the source vector.
735 CallInst *CreateAndReduce(Value *Src);
736
737 /// Create a vector int OR reduction intrinsic of the source vector.
738 CallInst *CreateOrReduce(Value *Src);
739
740 /// Create a vector int XOR reduction intrinsic of the source vector.
741 CallInst *CreateXorReduce(Value *Src);
742
743 /// Create a vector integer max reduction intrinsic of the source
744 /// vector.
745 CallInst *CreateIntMaxReduce(Value *Src, bool IsSigned = false);
746
747 /// Create a vector integer min reduction intrinsic of the source
748 /// vector.
749 CallInst *CreateIntMinReduce(Value *Src, bool IsSigned = false);
750
751 /// Create a vector float max reduction intrinsic of the source
752 /// vector.
753 CallInst *CreateFPMaxReduce(Value *Src);
754
755 /// Create a vector float min reduction intrinsic of the source
756 /// vector.
757 CallInst *CreateFPMinReduce(Value *Src);
758
759 /// Create a lifetime.start intrinsic.
760 ///
761 /// If the pointer isn't i8* it will be converted.
762 CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr);
763
764 /// Create a lifetime.end intrinsic.
765 ///
766 /// If the pointer isn't i8* it will be converted.
767 CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr);
768
769 /// Create a call to invariant.start intrinsic.
770 ///
771 /// If the pointer isn't i8* it will be converted.
772 CallInst *CreateInvariantStart(Value *Ptr, ConstantInt *Size = nullptr);
773
774 /// Create a call to llvm.threadlocal.address intrinsic.
775 CallInst *CreateThreadLocalAddress(Value *Ptr);
776
777 /// Create a call to Masked Load intrinsic
778 CallInst *CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask,
779 Value *PassThru = nullptr, const Twine &Name = "");
780
781 /// Create a call to Masked Store intrinsic
782 CallInst *CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment,
783 Value *Mask);
784
785 /// Create a call to Masked Gather intrinsic
786 CallInst *CreateMaskedGather(Type *Ty, Value *Ptrs, Align Alignment,
787 Value *Mask = nullptr, Value *PassThru = nullptr,
788 const Twine &Name = "");
789
790 /// Create a call to Masked Scatter intrinsic
791 CallInst *CreateMaskedScatter(Value *Val, Value *Ptrs, Align Alignment,
792 Value *Mask = nullptr);
793
794 /// Create a call to Masked Expand Load intrinsic
795 CallInst *CreateMaskedExpandLoad(Type *Ty, Value *Ptr, Value *Mask = nullptr,
796 Value *PassThru = nullptr,
797 const Twine &Name = "");
798
799 /// Create a call to Masked Compress Store intrinsic
800 CallInst *CreateMaskedCompressStore(Value *Val, Value *Ptr,
801 Value *Mask = nullptr);
802
803 /// Create an assume intrinsic call that allows the optimizer to
804 /// assume that the provided condition will be true.
805 ///
806 /// The optional argument \p OpBundles specifies operand bundles that are
807 /// added to the call instruction.
808 CallInst *
809 CreateAssumption(Value *Cond,
810 ArrayRef<OperandBundleDef> OpBundles = std::nullopt);
811
812 /// Create a llvm.experimental.noalias.scope.decl intrinsic call.
813 Instruction *CreateNoAliasScopeDeclaration(Value *Scope);
814 Instruction *CreateNoAliasScopeDeclaration(MDNode *ScopeTag) {
815 return CreateNoAliasScopeDeclaration(
816 MetadataAsValue::get(Context, ScopeTag));
817 }
818
819 /// Create a call to the experimental.gc.statepoint intrinsic to
820 /// start a new statepoint sequence.
821 CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
822 FunctionCallee ActualCallee,
823 ArrayRef<Value *> CallArgs,
824 std::optional<ArrayRef<Value *>> DeoptArgs,
825 ArrayRef<Value *> GCArgs,
826 const Twine &Name = "");
827
828 /// Create a call to the experimental.gc.statepoint intrinsic to
829 /// start a new statepoint sequence.
830 CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
831 FunctionCallee ActualCallee, uint32_t Flags,
832 ArrayRef<Value *> CallArgs,
833 std::optional<ArrayRef<Use>> TransitionArgs,
834 std::optional<ArrayRef<Use>> DeoptArgs,
835 ArrayRef<Value *> GCArgs,
836 const Twine &Name = "");
837
838 /// Conveninence function for the common case when CallArgs are filled
839 /// in using ArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be
840 /// .get()'ed to get the Value pointer.
841 CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
842 FunctionCallee ActualCallee,
843 ArrayRef<Use> CallArgs,
844 std::optional<ArrayRef<Value *>> DeoptArgs,
845 ArrayRef<Value *> GCArgs,
846 const Twine &Name = "");
847
848 /// Create an invoke to the experimental.gc.statepoint intrinsic to
849 /// start a new statepoint sequence.
850 InvokeInst *
851 CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
852 FunctionCallee ActualInvokee, BasicBlock *NormalDest,
853 BasicBlock *UnwindDest, ArrayRef<Value *> InvokeArgs,
854 std::optional<ArrayRef<Value *>> DeoptArgs,
855 ArrayRef<Value *> GCArgs, const Twine &Name = "");
856
857 /// Create an invoke to the experimental.gc.statepoint intrinsic to
858 /// start a new statepoint sequence.
859 InvokeInst *CreateGCStatepointInvoke(
860 uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee,
861 BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags,
862 ArrayRef<Value *> InvokeArgs, std::optional<ArrayRef<Use>> TransitionArgs,
863 std::optional<ArrayRef<Use>> DeoptArgs, ArrayRef<Value *> GCArgs,
864 const Twine &Name = "");
865
866 // Convenience function for the common case when CallArgs are filled in using
867 // ArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to
868 // get the Value *.
869 InvokeInst *
870 CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
871 FunctionCallee ActualInvokee, BasicBlock *NormalDest,
872 BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs,
873 std::optional<ArrayRef<Value *>> DeoptArgs,
874 ArrayRef<Value *> GCArgs, const Twine &Name = "");
875
876 /// Create a call to the experimental.gc.result intrinsic to extract
877 /// the result from a call wrapped in a statepoint.
878 CallInst *CreateGCResult(Instruction *Statepoint,
879 Type *ResultType,
880 const Twine &Name = "");
881
882 /// Create a call to the experimental.gc.relocate intrinsics to
883 /// project the relocated value of one pointer from the statepoint.
884 CallInst *CreateGCRelocate(Instruction *Statepoint,
885 int BaseOffset,
886 int DerivedOffset,
887 Type *ResultType,
888 const Twine &Name = "");
889
890 /// Create a call to the experimental.gc.pointer.base intrinsic to get the
891 /// base pointer for the specified derived pointer.
892 CallInst *CreateGCGetPointerBase(Value *DerivedPtr, const Twine &Name = "");
893
894 /// Create a call to the experimental.gc.get.pointer.offset intrinsic to get
895 /// the offset of the specified derived pointer from its base.
896 CallInst *CreateGCGetPointerOffset(Value *DerivedPtr, const Twine &Name = "");
897
898 /// Create a call to llvm.vscale, multiplied by \p Scaling. The type of VScale
899 /// will be the same type as that of \p Scaling.
900 Value *CreateVScale(Constant *Scaling, const Twine &Name = "");
901
902 /// Create an expression which evaluates to the number of elements in \p EC
903 /// at runtime.
904 Value *CreateElementCount(Type *DstType, ElementCount EC);
905
906 /// Create an expression which evaluates to the number of units in \p Size
907 /// at runtime. This works for both units of bits and bytes.
908 Value *CreateTypeSize(Type *DstType, TypeSize Size);
909
910 /// Creates a vector of type \p DstType with the linear sequence <0, 1, ...>
911 Value *CreateStepVector(Type *DstType, const Twine &Name = "");
912
913 /// Create a call to intrinsic \p ID with 1 operand which is mangled on its
914 /// type.
915 CallInst *CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,
916 Instruction *FMFSource = nullptr,
917 const Twine &Name = "");
918
919 /// Create a call to intrinsic \p ID with 2 operands which is mangled on the
920 /// first type.
921 CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS,
922 Instruction *FMFSource = nullptr,
923 const Twine &Name = "");
924
925 /// Create a call to intrinsic \p ID with \p Args, mangled using \p Types. If
926 /// \p FMFSource is provided, copy fast-math-flags from that instruction to
927 /// the intrinsic.
928 CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef<Type *> Types,
929 ArrayRef<Value *> Args,
930 Instruction *FMFSource = nullptr,
931 const Twine &Name = "");
932
933 /// Create a call to intrinsic \p ID with \p RetTy and \p Args. If
934 /// \p FMFSource is provided, copy fast-math-flags from that instruction to
935 /// the intrinsic.
936 CallInst *CreateIntrinsic(Type *RetTy, Intrinsic::ID ID,
937 ArrayRef<Value *> Args,
938 Instruction *FMFSource = nullptr,
939 const Twine &Name = "");
940
941 /// Create call to the minnum intrinsic.
942 CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
943 return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, nullptr, Name);
944 }
945
946 /// Create call to the maxnum intrinsic.
947 CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
948 return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, nullptr, Name);
949 }
950
951 /// Create call to the minimum intrinsic.
952 CallInst *CreateMinimum(Value *LHS, Value *RHS, const Twine &Name = "") {
953 return CreateBinaryIntrinsic(Intrinsic::minimum, LHS, RHS, nullptr, Name);
954 }
955
956 /// Create call to the maximum intrinsic.
957 CallInst *CreateMaximum(Value *LHS, Value *RHS, const Twine &Name = "") {
958 return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name);
959 }
960
961 /// Create call to the copysign intrinsic.
962 CallInst *CreateCopySign(Value *LHS, Value *RHS,
963 Instruction *FMFSource = nullptr,
964 const Twine &Name = "") {
965 return CreateBinaryIntrinsic(Intrinsic::copysign, LHS, RHS, FMFSource,
966 Name);
967 }
968
969 /// Create a call to the arithmetic_fence intrinsic.
970 CallInst *CreateArithmeticFence(Value *Val, Type *DstType,
971 const Twine &Name = "") {
972 return CreateIntrinsic(Intrinsic::arithmetic_fence, DstType, Val, nullptr,
973 Name);
974 }
975
976 /// Create a call to the vector.extract intrinsic.
977 CallInst *CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx,
978 const Twine &Name = "") {
979 return CreateIntrinsic(Intrinsic::vector_extract,
980 {DstType, SrcVec->getType()}, {SrcVec, Idx}, nullptr,
981 Name);
982 }
983
984 /// Create a call to the vector.insert intrinsic.
985 CallInst *CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec,
986 Value *Idx, const Twine &Name = "") {
987 return CreateIntrinsic(Intrinsic::vector_insert,
988 {DstType, SubVec->getType()}, {SrcVec, SubVec, Idx},
989 nullptr, Name);
990 }
991
992private:
993 /// Create a call to a masked intrinsic with given Id.
994 CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
995 ArrayRef<Type *> OverloadedTypes,
996 const Twine &Name = "");
997
998 Value *getCastedInt8PtrValue(Value *Ptr);
999
1000 //===--------------------------------------------------------------------===//
1001 // Instruction creation methods: Terminators
1002 //===--------------------------------------------------------------------===//
1003
1004private:
1005 /// Helper to add branch weight and unpredictable metadata onto an
1006 /// instruction.
1007 /// \returns The annotated instruction.
1008 template <typename InstTy>
1009 InstTy *addBranchMetadata(InstTy *I, MDNode *Weights, MDNode *Unpredictable) {
1010 if (Weights)
1011 I->setMetadata(LLVMContext::MD_prof, Weights);
1012 if (Unpredictable)
1013 I->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);
1014 return I;
1015 }
1016
1017public:
1018 /// Create a 'ret void' instruction.
1019 ReturnInst *CreateRetVoid() {
1020 return Insert(ReturnInst::Create(Context));
1021 }
1022
1023 /// Create a 'ret <val>' instruction.
1024 ReturnInst *CreateRet(Value *V) {
1025 return Insert(ReturnInst::Create(Context, V));
1026 }
1027
1028 /// Create a sequence of N insertvalue instructions,
1029 /// with one Value from the retVals array each, that build a aggregate
1030 /// return value one value at a time, and a ret instruction to return
1031 /// the resulting aggregate value.
1032 ///
1033 /// This is a convenience function for code that uses aggregate return values
1034 /// as a vehicle for having multiple return values.
1035 ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) {
1036 Value *V = PoisonValue::get(getCurrentFunctionReturnType());
1037 for (unsigned i = 0; i != N; ++i)
1038 V = CreateInsertValue(V, retVals[i], i, "mrv");
1039 return Insert(ReturnInst::Create(Context, V));
1040 }
1041
1042 /// Create an unconditional 'br label X' instruction.
1043 BranchInst *CreateBr(BasicBlock *Dest) {
1044 return Insert(BranchInst::Create(Dest));
1045 }
1046
1047 /// Create a conditional 'br Cond, TrueDest, FalseDest'
1048 /// instruction.
1049 BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
1050 MDNode *BranchWeights = nullptr,
1051 MDNode *Unpredictable = nullptr) {
1052 return Insert(addBranchMetadata(BranchInst::Create(True, False, Cond),
1053 BranchWeights, Unpredictable));
1054 }
1055
1056 /// Create a conditional 'br Cond, TrueDest, FalseDest'
1057 /// instruction. Copy branch meta data if available.
1058 BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
1059 Instruction *MDSrc) {
1060 BranchInst *Br = BranchInst::Create(True, False, Cond);
1061 if (MDSrc) {
1062 unsigned WL[4] = {LLVMContext::MD_prof, LLVMContext::MD_unpredictable,
1063 LLVMContext::MD_make_implicit, LLVMContext::MD_dbg};
1064 Br->copyMetadata(*MDSrc, WL);
1065 }
1066 return Insert(Br);
1067 }
1068
1069 /// Create a switch instruction with the specified value, default dest,
1070 /// and with a hint for the number of cases that will be added (for efficient
1071 /// allocation).
1072 SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10,
1073 MDNode *BranchWeights = nullptr,
1074 MDNode *Unpredictable = nullptr) {
1075 return Insert(addBranchMetadata(SwitchInst::Create(V, Dest, NumCases),
1076 BranchWeights, Unpredictable));
1077 }
1078
1079 /// Create an indirect branch instruction with the specified address
1080 /// operand, with an optional hint for the number of destinations that will be
1081 /// added (for efficient allocation).
1082 IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) {
1083 return Insert(IndirectBrInst::Create(Addr, NumDests));
1084 }
1085
1086 /// Create an invoke instruction.
1087 InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee,
1088 BasicBlock *NormalDest, BasicBlock *UnwindDest,
1089 ArrayRef<Value *> Args,
1090 ArrayRef<OperandBundleDef> OpBundles,
1091 const Twine &Name = "") {
1092 InvokeInst *II =
1093 InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args, OpBundles);
1094 if (IsFPConstrained)
1095 setConstrainedFPCallAttr(II);
1096 return Insert(II, Name);
1097 }
1098 InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee,
1099 BasicBlock *NormalDest, BasicBlock *UnwindDest,
1100 ArrayRef<Value *> Args = std::nullopt,
1101 const Twine &Name = "") {
1102 InvokeInst *II =
1103 InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args);
1104 if (IsFPConstrained)
1105 setConstrainedFPCallAttr(II);
1106 return Insert(II, Name);
1107 }
1108
1109 InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest,
1110 BasicBlock *UnwindDest, ArrayRef<Value *> Args,
1111 ArrayRef<OperandBundleDef> OpBundles,
1112 const Twine &Name = "") {
1113 return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(),
1114 NormalDest, UnwindDest, Args, OpBundles, Name);
1115 }
1116
1117 InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest,
1118 BasicBlock *UnwindDest,
1119 ArrayRef<Value *> Args = std::nullopt,
1120 const Twine &Name = "") {
1121 return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(),
1122 NormalDest, UnwindDest, Args, Name);
1123 }
1124
1125 /// \brief Create a callbr instruction.
1126 CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee,
1127 BasicBlock *DefaultDest,
1128 ArrayRef<BasicBlock *> IndirectDests,
1129 ArrayRef<Value *> Args = std::nullopt,
1130 const Twine &Name = "") {
1131 return Insert(CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests,
1132 Args), Name);
1133 }
1134 CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee,
1135 BasicBlock *DefaultDest,
1136 ArrayRef<BasicBlock *> IndirectDests,
1137 ArrayRef<Value *> Args,
1138 ArrayRef<OperandBundleDef> OpBundles,
1139 const Twine &Name = "") {
1140 return Insert(
1141 CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, Args,
1142 OpBundles), Name);
1143 }
1144
1145 CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest,
1146 ArrayRef<BasicBlock *> IndirectDests,
1147 ArrayRef<Value *> Args = std::nullopt,
1148 const Twine &Name = "") {
1149 return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(),
1150 DefaultDest, IndirectDests, Args, Name);
1151 }
1152 CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest,
1153 ArrayRef<BasicBlock *> IndirectDests,
1154 ArrayRef<Value *> Args,
1155 ArrayRef<OperandBundleDef> OpBundles,
1156 const Twine &Name = "") {
1157 return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(),
1158 DefaultDest, IndirectDests, Args, Name);
1159 }
1160
1161 ResumeInst *CreateResume(Value *Exn) {
1162 return Insert(ResumeInst::Create(Exn));
1163 }
1164
1165 CleanupReturnInst *CreateCleanupRet(CleanupPadInst *CleanupPad,
1166 BasicBlock *UnwindBB = nullptr) {
1167 return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB));
1168 }
1169
1170 CatchSwitchInst *CreateCatchSwitch(Value *ParentPad, BasicBlock *UnwindBB,
1171 unsigned NumHandlers,
1172 const Twine &Name = "") {
1173 return Insert(CatchSwitchInst::Create(ParentPad, UnwindBB, NumHandlers),
1174 Name);
1175 }
1176
1177 CatchPadInst *CreateCatchPad(Value *ParentPad, ArrayRef<Value *> Args,
1178 const Twine &Name = "") {
1179 return Insert(CatchPadInst::Create(ParentPad, Args), Name);
1180 }
1181
1182 CleanupPadInst *CreateCleanupPad(Value *ParentPad,
1183 ArrayRef<Value *> Args = std::nullopt,
1184 const Twine &Name = "") {
1185 return Insert(CleanupPadInst::Create(ParentPad, Args), Name);
1186 }
1187
1188 CatchReturnInst *CreateCatchRet(CatchPadInst *CatchPad, BasicBlock *BB) {
1189 return Insert(CatchReturnInst::Create(CatchPad, BB));
1190 }
1191
1192 UnreachableInst *CreateUnreachable() {
1193 return Insert(new UnreachableInst(Context));
1194 }
1195
1196 //===--------------------------------------------------------------------===//
1197 // Instruction creation methods: Binary Operators
1198 //===--------------------------------------------------------------------===//
1199private:
1200 BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc,
1201 Value *LHS, Value *RHS,
1202 const Twine &Name,
1203 bool HasNUW, bool HasNSW) {
1204 BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name);
1205 if (HasNUW) BO->setHasNoUnsignedWrap();
1206 if (HasNSW) BO->setHasNoSignedWrap();
1207 return BO;
1208 }
1209
1210 Instruction *setFPAttrs(Instruction *I, MDNode *FPMD,
1211 FastMathFlags FMF) const {
1212 if (!FPMD)
1213 FPMD = DefaultFPMathTag;
1214 if (FPMD)
1215 I->setMetadata(LLVMContext::MD_fpmath, FPMD);
1216 I->setFastMathFlags(FMF);
1217 return I;
1218 }
1219
1220 Value *getConstrainedFPRounding(std::optional<RoundingMode> Rounding) {
1221 RoundingMode UseRounding = DefaultConstrainedRounding;
1222
1223 if (Rounding)
1224 UseRounding = *Rounding;
1225
1226 std::optional<StringRef> RoundingStr =
1227 convertRoundingModeToStr(UseRounding);
1228 assert(RoundingStr && "Garbage strict rounding mode!")(static_cast <bool> (RoundingStr && "Garbage strict rounding mode!"
) ? void (0) : __assert_fail ("RoundingStr && \"Garbage strict rounding mode!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1228, __extension__ __PRETTY_FUNCTION__
))
;
1229 auto *RoundingMDS = MDString::get(Context, *RoundingStr);
1230
1231 return MetadataAsValue::get(Context, RoundingMDS);
1232 }
1233
1234 Value *getConstrainedFPExcept(std::optional<fp::ExceptionBehavior> Except) {
1235 std::optional<StringRef> ExceptStr = convertExceptionBehaviorToStr(
1236 Except.value_or(DefaultConstrainedExcept));
1237 assert(ExceptStr && "Garbage strict exception behavior!")(static_cast <bool> (ExceptStr && "Garbage strict exception behavior!"
) ? void (0) : __assert_fail ("ExceptStr && \"Garbage strict exception behavior!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1237, __extension__ __PRETTY_FUNCTION__
))
;
1238 auto *ExceptMDS = MDString::get(Context, *ExceptStr);
1239
1240 return MetadataAsValue::get(Context, ExceptMDS);
1241 }
1242
1243 Value *getConstrainedFPPredicate(CmpInst::Predicate Predicate) {
1244 assert(CmpInst::isFPPredicate(Predicate) &&(static_cast <bool> (CmpInst::isFPPredicate(Predicate) &&
Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst
::FCMP_TRUE && "Invalid constrained FP comparison predicate!"
) ? void (0) : __assert_fail ("CmpInst::isFPPredicate(Predicate) && Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst::FCMP_TRUE && \"Invalid constrained FP comparison predicate!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1247, __extension__ __PRETTY_FUNCTION__
))
1245 Predicate != CmpInst::FCMP_FALSE &&(static_cast <bool> (CmpInst::isFPPredicate(Predicate) &&
Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst
::FCMP_TRUE && "Invalid constrained FP comparison predicate!"
) ? void (0) : __assert_fail ("CmpInst::isFPPredicate(Predicate) && Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst::FCMP_TRUE && \"Invalid constrained FP comparison predicate!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1247, __extension__ __PRETTY_FUNCTION__
))
1246 Predicate != CmpInst::FCMP_TRUE &&(static_cast <bool> (CmpInst::isFPPredicate(Predicate) &&
Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst
::FCMP_TRUE && "Invalid constrained FP comparison predicate!"
) ? void (0) : __assert_fail ("CmpInst::isFPPredicate(Predicate) && Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst::FCMP_TRUE && \"Invalid constrained FP comparison predicate!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1247, __extension__ __PRETTY_FUNCTION__
))
1247 "Invalid constrained FP comparison predicate!")(static_cast <bool> (CmpInst::isFPPredicate(Predicate) &&
Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst
::FCMP_TRUE && "Invalid constrained FP comparison predicate!"
) ? void (0) : __assert_fail ("CmpInst::isFPPredicate(Predicate) && Predicate != CmpInst::FCMP_FALSE && Predicate != CmpInst::FCMP_TRUE && \"Invalid constrained FP comparison predicate!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1247, __extension__ __PRETTY_FUNCTION__
))
;
1248
1249 StringRef PredicateStr = CmpInst::getPredicateName(Predicate);
1250 auto *PredicateMDS = MDString::get(Context, PredicateStr);
1251
1252 return MetadataAsValue::get(Context, PredicateMDS);
1253 }
1254
1255public:
1256 Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
1257 bool HasNUW = false, bool HasNSW = false) {
1258 if (Value *V =
34
Assuming 'V' is non-null
35
Taking true branch
1259 Folder.FoldNoWrapBinOp(Instruction::Add, LHS, RHS, HasNUW, HasNSW))
1260 return V;
1261 return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, HasNUW,
1262 HasNSW);
1263 }
1264
1265 Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
1266 return CreateAdd(LHS, RHS, Name, false, true);
1267 }
1268
1269 Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
1270 return CreateAdd(LHS, RHS, Name, true, false);
1271 }
1272
1273 Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "",
1274 bool HasNUW = false, bool HasNSW = false) {
1275 if (Value *V =
1276 Folder.FoldNoWrapBinOp(Instruction::Sub, LHS, RHS, HasNUW, HasNSW))
1277 return V;
1278 return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, HasNUW,
1279 HasNSW);
1280 }
1281
1282 Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
1283 return CreateSub(LHS, RHS, Name, false, true);
1284 }
1285
1286 Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
1287 return CreateSub(LHS, RHS, Name, true, false);
1288 }
1289
1290 Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "",
1291 bool HasNUW = false, bool HasNSW = false) {
1292 if (Value *V =
1293 Folder.FoldNoWrapBinOp(Instruction::Mul, LHS, RHS, HasNUW, HasNSW))
1294 return V;
1295 return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, HasNUW,
1296 HasNSW);
1297 }
1298
1299 Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
1300 return CreateMul(LHS, RHS, Name, false, true);
1301 }
1302
1303 Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
1304 return CreateMul(LHS, RHS, Name, true, false);
1305 }
1306
1307 Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "",
1308 bool isExact = false) {
1309 if (Value *V = Folder.FoldExactBinOp(Instruction::UDiv, LHS, RHS, isExact))
1310 return V;
1311 if (!isExact)
1312 return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name);
1313 return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name);
1314 }
1315
1316 Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
1317 return CreateUDiv(LHS, RHS, Name, true);
1318 }
1319
1320 Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "",
1321 bool isExact = false) {
1322 if (Value *V = Folder.FoldExactBinOp(Instruction::SDiv, LHS, RHS, isExact))
1323 return V;
1324 if (!isExact)
1325 return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name);
1326 return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name);
1327 }
1328
1329 Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
1330 return CreateSDiv(LHS, RHS, Name, true);
1331 }
1332
1333 Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") {
1334 if (Value *V = Folder.FoldBinOp(Instruction::URem, LHS, RHS))
1335 return V;
1336 return Insert(BinaryOperator::CreateURem(LHS, RHS), Name);
1337 }
1338
1339 Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") {
1340 if (Value *V = Folder.FoldBinOp(Instruction::SRem, LHS, RHS))
1341 return V;
1342 return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name);
1343 }
1344
1345 Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "",
1346 bool HasNUW = false, bool HasNSW = false) {
1347 if (Value *V =
1348 Folder.FoldNoWrapBinOp(Instruction::Shl, LHS, RHS, HasNUW, HasNSW))
1349 return V;
1350 return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name,
1351 HasNUW, HasNSW);
1352 }
1353
1354 Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "",
1355 bool HasNUW = false, bool HasNSW = false) {
1356 return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name,
1357 HasNUW, HasNSW);
1358 }
1359
1360 Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "",
1361 bool HasNUW = false, bool HasNSW = false) {
1362 return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name,
1363 HasNUW, HasNSW);
1364 }
1365
1366 Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "",
1367 bool isExact = false) {
1368 if (Value *V = Folder.FoldExactBinOp(Instruction::LShr, LHS, RHS, isExact))
1369 return V;
1370 if (!isExact)
1371 return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name);
1372 return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name);
1373 }
1374
1375 Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
1376 bool isExact = false) {
1377 return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1378 }
1379
1380 Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
1381 bool isExact = false) {
1382 return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1383 }
1384
1385 Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "",
1386 bool isExact = false) {
1387 if (Value *V = Folder.FoldExactBinOp(Instruction::AShr, LHS, RHS, isExact))
1388 return V;
1389 if (!isExact)
1390 return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name);
1391 return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name);
1392 }
1393
1394 Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
1395 bool isExact = false) {
1396 return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1397 }
1398
1399 Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
1400 bool isExact = false) {
1401 return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1402 }
1403
1404 Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
1405 if (auto *V = Folder.FoldBinOp(Instruction::And, LHS, RHS))
1406 return V;
1407 return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name);
1408 }
1409
1410 Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") {
1411 return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1412 }
1413
1414 Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") {
1415 return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1416 }
1417
1418 Value *CreateAnd(ArrayRef<Value*> Ops) {
1419 assert(!Ops.empty())(static_cast <bool> (!Ops.empty()) ? void (0) : __assert_fail
("!Ops.empty()", "llvm/include/llvm/IR/IRBuilder.h", 1419, __extension__
__PRETTY_FUNCTION__))
;
1420 Value *Accum = Ops[0];
1421 for (unsigned i = 1; i < Ops.size(); i++)
1422 Accum = CreateAnd(Accum, Ops[i]);
1423 return Accum;
1424 }
1425
1426 Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") {
1427 if (auto *V = Folder.FoldBinOp(Instruction::Or, LHS, RHS))
1428 return V;
1429 return Insert(BinaryOperator::CreateOr(LHS, RHS), Name);
1430 }
1431
1432 Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
1433 return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1434 }
1435
1436 Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
1437 return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1438 }
1439
1440 Value *CreateOr(ArrayRef<Value*> Ops) {
1441 assert(!Ops.empty())(static_cast <bool> (!Ops.empty()) ? void (0) : __assert_fail
("!Ops.empty()", "llvm/include/llvm/IR/IRBuilder.h", 1441, __extension__
__PRETTY_FUNCTION__))
;
1442 Value *Accum = Ops[0];
1443 for (unsigned i = 1; i < Ops.size(); i++)
1444 Accum = CreateOr(Accum, Ops[i]);
1445 return Accum;
1446 }
1447
1448 Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") {
1449 if (Value *V = Folder.FoldBinOp(Instruction::Xor, LHS, RHS))
1450 return V;
1451 return Insert(BinaryOperator::CreateXor(LHS, RHS), Name);
1452 }
1453
1454 Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") {
1455 return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1456 }
1457
1458 Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") {
1459 return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1460 }
1461
1462 Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
1463 MDNode *FPMD = nullptr) {
1464 if (IsFPConstrained)
1465 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
1466 L, R, nullptr, Name, FPMD);
1467
1468 if (Value *V = Folder.FoldBinOpFMF(Instruction::FAdd, L, R, FMF))
1469 return V;
1470 Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
1471 return Insert(I, Name);
1472 }
1473
1474 /// Copy fast-math-flags from an instruction rather than using the builder's
1475 /// default FMF.
1476 Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource,
1477 const Twine &Name = "") {
1478 if (IsFPConstrained)
1479 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
1480 L, R, FMFSource, Name);
1481
1482 FastMathFlags FMF = FMFSource->getFastMathFlags();
1483 if (Value *V = Folder.FoldBinOpFMF(Instruction::FAdd, L, R, FMF))
1484 return V;
1485 Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, FMF);
1486 return Insert(I, Name);
1487 }
1488
1489 Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
1490 MDNode *FPMD = nullptr) {
1491 if (IsFPConstrained)
1492 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
1493 L, R, nullptr, Name, FPMD);
1494
1495 if (Value *V = Folder.FoldBinOpFMF(Instruction::FSub, L, R, FMF))
1496 return V;
1497 Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
1498 return Insert(I, Name);
1499 }
1500
1501 /// Copy fast-math-flags from an instruction rather than using the builder's
1502 /// default FMF.
1503 Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource,
1504 const Twine &Name = "") {
1505 if (IsFPConstrained)
1506 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
1507 L, R, FMFSource, Name);
1508
1509 FastMathFlags FMF = FMFSource->getFastMathFlags();
1510 if (Value *V = Folder.FoldBinOpFMF(Instruction::FSub, L, R, FMF))
1511 return V;
1512 Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, FMF);
1513 return Insert(I, Name);
1514 }
1515
1516 Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
1517 MDNode *FPMD = nullptr) {
1518 if (IsFPConstrained)
1519 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
1520 L, R, nullptr, Name, FPMD);
1521
1522 if (Value *V = Folder.FoldBinOpFMF(Instruction::FMul, L, R, FMF))
1523 return V;
1524 Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
1525 return Insert(I, Name);
1526 }
1527
1528 /// Copy fast-math-flags from an instruction rather than using the builder's
1529 /// default FMF.
1530 Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource,
1531 const Twine &Name = "") {
1532 if (IsFPConstrained)
1533 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
1534 L, R, FMFSource, Name);
1535
1536 FastMathFlags FMF = FMFSource->getFastMathFlags();
1537 if (Value *V = Folder.FoldBinOpFMF(Instruction::FMul, L, R, FMF))
1538 return V;
1539 Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, FMF);
1540 return Insert(I, Name);
1541 }
1542
1543 Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
1544 MDNode *FPMD = nullptr) {
1545 if (IsFPConstrained)
1546 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
1547 L, R, nullptr, Name, FPMD);
1548
1549 if (Value *V = Folder.FoldBinOpFMF(Instruction::FDiv, L, R, FMF))
1550 return V;
1551 Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
1552 return Insert(I, Name);
1553 }
1554
1555 /// Copy fast-math-flags from an instruction rather than using the builder's
1556 /// default FMF.
1557 Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource,
1558 const Twine &Name = "") {
1559 if (IsFPConstrained)
1560 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
1561 L, R, FMFSource, Name);
1562
1563 FastMathFlags FMF = FMFSource->getFastMathFlags();
1564 if (Value *V = Folder.FoldBinOpFMF(Instruction::FDiv, L, R, FMF))
1565 return V;
1566 Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, FMF);
1567 return Insert(I, Name);
1568 }
1569
1570 Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
1571 MDNode *FPMD = nullptr) {
1572 if (IsFPConstrained)
1573 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
1574 L, R, nullptr, Name, FPMD);
1575
1576 if (Value *V = Folder.FoldBinOpFMF(Instruction::FRem, L, R, FMF)) return V;
1577 Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
1578 return Insert(I, Name);
1579 }
1580
1581 /// Copy fast-math-flags from an instruction rather than using the builder's
1582 /// default FMF.
1583 Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource,
1584 const Twine &Name = "") {
1585 if (IsFPConstrained)
1586 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
1587 L, R, FMFSource, Name);
1588
1589 FastMathFlags FMF = FMFSource->getFastMathFlags();
1590 if (Value *V = Folder.FoldBinOpFMF(Instruction::FRem, L, R, FMF)) return V;
1591 Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, FMF);
1592 return Insert(I, Name);
1593 }
1594
1595 Value *CreateBinOp(Instruction::BinaryOps Opc,
1596 Value *LHS, Value *RHS, const Twine &Name = "",
1597 MDNode *FPMathTag = nullptr) {
1598 if (Value *V = Folder.FoldBinOp(Opc, LHS, RHS)) return V;
1599 Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS);
1600 if (isa<FPMathOperator>(BinOp))
1601 setFPAttrs(BinOp, FPMathTag, FMF);
1602 return Insert(BinOp, Name);
1603 }
1604
1605 Value *CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name = "") {
1606 assert(Cond2->getType()->isIntOrIntVectorTy(1))(static_cast <bool> (Cond2->getType()->isIntOrIntVectorTy
(1)) ? void (0) : __assert_fail ("Cond2->getType()->isIntOrIntVectorTy(1)"
, "llvm/include/llvm/IR/IRBuilder.h", 1606, __extension__ __PRETTY_FUNCTION__
))
;
1607 return CreateSelect(Cond1, Cond2,
1608 ConstantInt::getNullValue(Cond2->getType()), Name);
1609 }
1610
1611 Value *CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name = "") {
1612 assert(Cond2->getType()->isIntOrIntVectorTy(1))(static_cast <bool> (Cond2->getType()->isIntOrIntVectorTy
(1)) ? void (0) : __assert_fail ("Cond2->getType()->isIntOrIntVectorTy(1)"
, "llvm/include/llvm/IR/IRBuilder.h", 1612, __extension__ __PRETTY_FUNCTION__
))
;
1613 return CreateSelect(Cond1, ConstantInt::getAllOnesValue(Cond2->getType()),
1614 Cond2, Name);
1615 }
1616
1617 Value *CreateLogicalOp(Instruction::BinaryOps Opc, Value *Cond1, Value *Cond2,
1618 const Twine &Name = "") {
1619 switch (Opc) {
1620 case Instruction::And:
1621 return CreateLogicalAnd(Cond1, Cond2, Name);
1622 case Instruction::Or:
1623 return CreateLogicalOr(Cond1, Cond2, Name);
1624 default:
1625 break;
1626 }
1627 llvm_unreachable("Not a logical operation.")::llvm::llvm_unreachable_internal("Not a logical operation.",
"llvm/include/llvm/IR/IRBuilder.h", 1627)
;
1628 }
1629
1630 // NOTE: this is sequential, non-commutative, ordered reduction!
1631 Value *CreateLogicalOr(ArrayRef<Value *> Ops) {
1632 assert(!Ops.empty())(static_cast <bool> (!Ops.empty()) ? void (0) : __assert_fail
("!Ops.empty()", "llvm/include/llvm/IR/IRBuilder.h", 1632, __extension__
__PRETTY_FUNCTION__))
;
1633 Value *Accum = Ops[0];
1634 for (unsigned i = 1; i < Ops.size(); i++)
1635 Accum = CreateLogicalOr(Accum, Ops[i]);
1636 return Accum;
1637 }
1638
1639 CallInst *CreateConstrainedFPBinOp(
1640 Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr,
1641 const Twine &Name = "", MDNode *FPMathTag = nullptr,
1642 std::optional<RoundingMode> Rounding = std::nullopt,
1643 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
1644
1645 Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNUW = false,
1646 bool HasNSW = false) {
1647 return CreateSub(Constant::getNullValue(V->getType()), V, Name, HasNUW,
1648 HasNSW);
1649 }
1650
1651 Value *CreateNSWNeg(Value *V, const Twine &Name = "") {
1652 return CreateNeg(V, Name, false, true);
1653 }
1654
1655 Value *CreateNUWNeg(Value *V, const Twine &Name = "") {
1656 return CreateNeg(V, Name, true, false);
1657 }
1658
1659 Value *CreateFNeg(Value *V, const Twine &Name = "",
1660 MDNode *FPMathTag = nullptr) {
1661 if (Value *Res = Folder.FoldUnOpFMF(Instruction::FNeg, V, FMF))
1662 return Res;
1663 return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), FPMathTag, FMF),
1664 Name);
1665 }
1666
1667 /// Copy fast-math-flags from an instruction rather than using the builder's
1668 /// default FMF.
1669 Value *CreateFNegFMF(Value *V, Instruction *FMFSource,
1670 const Twine &Name = "") {
1671 FastMathFlags FMF = FMFSource->getFastMathFlags();
1672 if (Value *Res = Folder.FoldUnOpFMF(Instruction::FNeg, V, FMF))
1673 return Res;
1674 return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), nullptr, FMF),
1675 Name);
1676 }
1677
1678 Value *CreateNot(Value *V, const Twine &Name = "") {
1679 return CreateXor(V, Constant::getAllOnesValue(V->getType()), Name);
1680 }
1681
1682 Value *CreateUnOp(Instruction::UnaryOps Opc,
1683 Value *V, const Twine &Name = "",
1684 MDNode *FPMathTag = nullptr) {
1685 if (Value *Res = Folder.FoldUnOpFMF(Opc, V, FMF))
1686 return Res;
1687 Instruction *UnOp = UnaryOperator::Create(Opc, V);
1688 if (isa<FPMathOperator>(UnOp))
1689 setFPAttrs(UnOp, FPMathTag, FMF);
1690 return Insert(UnOp, Name);
1691 }
1692
1693 /// Create either a UnaryOperator or BinaryOperator depending on \p Opc.
1694 /// Correct number of operands must be passed accordingly.
1695 Value *CreateNAryOp(unsigned Opc, ArrayRef<Value *> Ops,
1696 const Twine &Name = "", MDNode *FPMathTag = nullptr);
1697
1698 //===--------------------------------------------------------------------===//
1699 // Instruction creation methods: Memory Instructions
1700 //===--------------------------------------------------------------------===//
1701
1702 AllocaInst *CreateAlloca(Type *Ty, unsigned AddrSpace,
1703 Value *ArraySize = nullptr, const Twine &Name = "") {
1704 const DataLayout &DL = BB->getModule()->getDataLayout();
1705 Align AllocaAlign = DL.getPrefTypeAlign(Ty);
1706 return Insert(new AllocaInst(Ty, AddrSpace, ArraySize, AllocaAlign), Name);
1707 }
1708
1709 AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr,
1710 const Twine &Name = "") {
1711 const DataLayout &DL = BB->getModule()->getDataLayout();
1712 Align AllocaAlign = DL.getPrefTypeAlign(Ty);
1713 unsigned AddrSpace = DL.getAllocaAddrSpace();
1714 return Insert(new AllocaInst(Ty, AddrSpace, ArraySize, AllocaAlign), Name);
1715 }
1716
1717 /// Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of
1718 /// converting the string to 'bool' for the isVolatile parameter.
1719 LoadInst *CreateLoad(Type *Ty, Value *Ptr, const char *Name) {
1720 return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), Name);
1721 }
1722
1723 LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") {
1724 return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), Name);
1725 }
1726
1727 LoadInst *CreateLoad(Type *Ty, Value *Ptr, bool isVolatile,
1728 const Twine &Name = "") {
1729 return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), isVolatile, Name);
1730 }
1731
1732 StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) {
1733 return CreateAlignedStore(Val, Ptr, MaybeAlign(), isVolatile);
1734 }
1735
1736 LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align,
1737 const char *Name) {
1738 return CreateAlignedLoad(Ty, Ptr, Align, /*isVolatile*/false, Name);
1739 }
1740
1741 LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align,
1742 const Twine &Name = "") {
1743 return CreateAlignedLoad(Ty, Ptr, Align, /*isVolatile*/false, Name);
1744 }
1745
1746 LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align,
1747 bool isVolatile, const Twine &Name = "") {
1748 if (!Align) {
1749 const DataLayout &DL = BB->getModule()->getDataLayout();
1750 Align = DL.getABITypeAlign(Ty);
1751 }
1752 return Insert(new LoadInst(Ty, Ptr, Twine(), isVolatile, *Align), Name);
1753 }
1754
1755 StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align,
1756 bool isVolatile = false) {
1757 if (!Align) {
1758 const DataLayout &DL = BB->getModule()->getDataLayout();
1759 Align = DL.getABITypeAlign(Val->getType());
1760 }
1761 return Insert(new StoreInst(Val, Ptr, isVolatile, *Align));
1762 }
1763 FenceInst *CreateFence(AtomicOrdering Ordering,
1764 SyncScope::ID SSID = SyncScope::System,
1765 const Twine &Name = "") {
1766 return Insert(new FenceInst(Context, Ordering, SSID), Name);
1767 }
1768
1769 AtomicCmpXchgInst *
1770 CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
1771 AtomicOrdering SuccessOrdering,
1772 AtomicOrdering FailureOrdering,
1773 SyncScope::ID SSID = SyncScope::System) {
1774 if (!Align) {
1775 const DataLayout &DL = BB->getModule()->getDataLayout();
1776 Align = llvm::Align(DL.getTypeStoreSize(New->getType()));
1777 }
1778
1779 return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, *Align, SuccessOrdering,
1780 FailureOrdering, SSID));
1781 }
1782
1783 AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr,
1784 Value *Val, MaybeAlign Align,
1785 AtomicOrdering Ordering,
1786 SyncScope::ID SSID = SyncScope::System) {
1787 if (!Align) {
1788 const DataLayout &DL = BB->getModule()->getDataLayout();
1789 Align = llvm::Align(DL.getTypeStoreSize(Val->getType()));
1790 }
1791
1792 return Insert(new AtomicRMWInst(Op, Ptr, Val, *Align, Ordering, SSID));
1793 }
1794
1795 Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
1796 const Twine &Name = "", bool IsInBounds = false) {
1797 if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, IsInBounds))
1798 return V;
1799 return Insert(IsInBounds
1800 ? GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList)
1801 : GetElementPtrInst::Create(Ty, Ptr, IdxList),
1802 Name);
1803 }
1804
1805 Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
1806 const Twine &Name = "") {
1807 return CreateGEP(Ty, Ptr, IdxList, Name, /* IsInBounds */ true);
1808 }
1809
1810 Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
1811 const Twine &Name = "") {
1812 Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
1813
1814 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/false))
1815 return V;
1816
1817 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
1818 }
1819
1820 Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
1821 const Twine &Name = "") {
1822 Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
1823
1824 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/true))
1825 return V;
1826
1827 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
1828 }
1829
1830 Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1,
1831 const Twine &Name = "") {
1832 Value *Idxs[] = {
1833 ConstantInt::get(Type::getInt32Ty(Context), Idx0),
1834 ConstantInt::get(Type::getInt32Ty(Context), Idx1)
1835 };
1836
1837 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/false))
1838 return V;
1839
1840 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name);
1841 }
1842
1843 Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0,
1844 unsigned Idx1, const Twine &Name = "") {
1845 Value *Idxs[] = {
1846 ConstantInt::get(Type::getInt32Ty(Context), Idx0),
1847 ConstantInt::get(Type::getInt32Ty(Context), Idx1)
1848 };
1849
1850 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/true))
1851 return V;
1852
1853 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name);
1854 }
1855
1856 Value *CreateConstGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0,
1857 const Twine &Name = "") {
1858 Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
1859
1860 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/false))
1861 return V;
1862
1863 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
1864 }
1865
1866 Value *CreateConstInBoundsGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0,
1867 const Twine &Name = "") {
1868 Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
1869
1870 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/true))
1871 return V;
1872
1873 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
1874 }
1875
1876 Value *CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1,
1877 const Twine &Name = "") {
1878 Value *Idxs[] = {
1879 ConstantInt::get(Type::getInt64Ty(Context), Idx0),
1880 ConstantInt::get(Type::getInt64Ty(Context), Idx1)
1881 };
1882
1883 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/false))
1884 return V;
1885
1886 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name);
1887 }
1888
1889 Value *CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0,
1890 uint64_t Idx1, const Twine &Name = "") {
1891 Value *Idxs[] = {
1892 ConstantInt::get(Type::getInt64Ty(Context), Idx0),
1893 ConstantInt::get(Type::getInt64Ty(Context), Idx1)
1894 };
1895
1896 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/true))
1897 return V;
1898
1899 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name);
1900 }
1901
1902 Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx,
1903 const Twine &Name = "") {
1904 return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name);
1905 }
1906
1907 /// Same as CreateGlobalString, but return a pointer with "i8*" type
1908 /// instead of a pointer to array of i8.
1909 ///
1910 /// If no module is given via \p M, it is take from the insertion point basic
1911 /// block.
1912 Constant *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "",
1913 unsigned AddressSpace = 0,
1914 Module *M = nullptr) {
1915 GlobalVariable *GV = CreateGlobalString(Str, Name, AddressSpace, M);
1916 Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0);
1917 Constant *Indices[] = {Zero, Zero};
1918 return ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV,
1919 Indices);
1920 }
1921
1922 //===--------------------------------------------------------------------===//
1923 // Instruction creation methods: Cast/Conversion Operators
1924 //===--------------------------------------------------------------------===//
1925
1926 Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") {
1927 return CreateCast(Instruction::Trunc, V, DestTy, Name);
1928 }
1929
1930 Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") {
1931 return CreateCast(Instruction::ZExt, V, DestTy, Name);
1932 }
1933
1934 Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") {
1935 return CreateCast(Instruction::SExt, V, DestTy, Name);
1936 }
1937
1938 /// Create a ZExt or Trunc from the integer value V to DestTy. Return
1939 /// the value untouched if the type of V is already DestTy.
1940 Value *CreateZExtOrTrunc(Value *V, Type *DestTy,
1941 const Twine &Name = "") {
1942 assert(V->getType()->isIntOrIntVectorTy() &&(static_cast <bool> (V->getType()->isIntOrIntVectorTy
() && DestTy->isIntOrIntVectorTy() && "Can only zero extend/truncate integers!"
) ? void (0) : __assert_fail ("V->getType()->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy() && \"Can only zero extend/truncate integers!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1944, __extension__ __PRETTY_FUNCTION__
))
1943 DestTy->isIntOrIntVectorTy() &&(static_cast <bool> (V->getType()->isIntOrIntVectorTy
() && DestTy->isIntOrIntVectorTy() && "Can only zero extend/truncate integers!"
) ? void (0) : __assert_fail ("V->getType()->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy() && \"Can only zero extend/truncate integers!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1944, __extension__ __PRETTY_FUNCTION__
))
1944 "Can only zero extend/truncate integers!")(static_cast <bool> (V->getType()->isIntOrIntVectorTy
() && DestTy->isIntOrIntVectorTy() && "Can only zero extend/truncate integers!"
) ? void (0) : __assert_fail ("V->getType()->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy() && \"Can only zero extend/truncate integers!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1944, __extension__ __PRETTY_FUNCTION__
))
;
1945 Type *VTy = V->getType();
1946 if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits())
1947 return CreateZExt(V, DestTy, Name);
1948 if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits())
1949 return CreateTrunc(V, DestTy, Name);
1950 return V;
1951 }
1952
1953 /// Create a SExt or Trunc from the integer value V to DestTy. Return
1954 /// the value untouched if the type of V is already DestTy.
1955 Value *CreateSExtOrTrunc(Value *V, Type *DestTy,
1956 const Twine &Name = "") {
1957 assert(V->getType()->isIntOrIntVectorTy() &&(static_cast <bool> (V->getType()->isIntOrIntVectorTy
() && DestTy->isIntOrIntVectorTy() && "Can only sign extend/truncate integers!"
) ? void (0) : __assert_fail ("V->getType()->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy() && \"Can only sign extend/truncate integers!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1959, __extension__ __PRETTY_FUNCTION__
))
1958 DestTy->isIntOrIntVectorTy() &&(static_cast <bool> (V->getType()->isIntOrIntVectorTy
() && DestTy->isIntOrIntVectorTy() && "Can only sign extend/truncate integers!"
) ? void (0) : __assert_fail ("V->getType()->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy() && \"Can only sign extend/truncate integers!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1959, __extension__ __PRETTY_FUNCTION__
))
1959 "Can only sign extend/truncate integers!")(static_cast <bool> (V->getType()->isIntOrIntVectorTy
() && DestTy->isIntOrIntVectorTy() && "Can only sign extend/truncate integers!"
) ? void (0) : __assert_fail ("V->getType()->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy() && \"Can only sign extend/truncate integers!\""
, "llvm/include/llvm/IR/IRBuilder.h", 1959, __extension__ __PRETTY_FUNCTION__
))
;
1960 Type *VTy = V->getType();
1961 if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits())
1962 return CreateSExt(V, DestTy, Name);
1963 if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits())
1964 return CreateTrunc(V, DestTy, Name);
1965 return V;
1966 }
1967
1968 Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = "") {
1969 if (IsFPConstrained)
1970 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fptoui,
1971 V, DestTy, nullptr, Name);
1972 return CreateCast(Instruction::FPToUI, V, DestTy, Name);
1973 }
1974
1975 Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = "") {
1976 if (IsFPConstrained)
1977 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fptosi,
1978 V, DestTy, nullptr, Name);
1979 return CreateCast(Instruction::FPToSI, V, DestTy, Name);
1980 }
1981
1982 Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
1983 if (IsFPConstrained)
1984 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_uitofp,
1985 V, DestTy, nullptr, Name);
1986 return CreateCast(Instruction::UIToFP, V, DestTy, Name);
1987 }
1988
1989 Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
1990 if (IsFPConstrained)
1991 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_sitofp,
1992 V, DestTy, nullptr, Name);
1993 return CreateCast(Instruction::SIToFP, V, DestTy, Name);
1994 }
1995
1996 Value *CreateFPTrunc(Value *V, Type *DestTy,
1997 const Twine &Name = "") {
1998 if (IsFPConstrained)
1999 return CreateConstrainedFPCast(
2000 Intrinsic::experimental_constrained_fptrunc, V, DestTy, nullptr,
2001 Name);
2002 return CreateCast(Instruction::FPTrunc, V, DestTy, Name);
2003 }
2004
2005 Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") {
2006 if (IsFPConstrained)
2007 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fpext,
2008 V, DestTy, nullptr, Name);
2009 return CreateCast(Instruction::FPExt, V, DestTy, Name);
2010 }
2011
2012 Value *CreatePtrToInt(Value *V, Type *DestTy,
2013 const Twine &Name = "") {
2014 return CreateCast(Instruction::PtrToInt, V, DestTy, Name);
2015 }
2016
2017 Value *CreateIntToPtr(Value *V, Type *DestTy,
2018 const Twine &Name = "") {
2019 return CreateCast(Instruction::IntToPtr, V, DestTy, Name);
2020 }
2021
2022 Value *CreateBitCast(Value *V, Type *DestTy,
2023 const Twine &Name = "") {
2024 return CreateCast(Instruction::BitCast, V, DestTy, Name);
2025 }
2026
2027 Value *CreateAddrSpaceCast(Value *V, Type *DestTy,
2028 const Twine &Name = "") {
2029 return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name);
2030 }
2031
2032 Value *CreateZExtOrBitCast(Value *V, Type *DestTy,
2033 const Twine &Name = "") {
2034 if (V->getType() == DestTy)
2035 return V;
2036 if (auto *VC = dyn_cast<Constant>(V))
2037 return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name);
2038 return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name);
2039 }
2040
2041 Value *CreateSExtOrBitCast(Value *V, Type *DestTy,
2042 const Twine &Name = "") {
2043 if (V->getType() == DestTy)
2044 return V;
2045 if (auto *VC = dyn_cast<Constant>(V))
2046 return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name);
2047 return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name);
2048 }
2049
2050 Value *CreateTruncOrBitCast(Value *V, Type *DestTy,
2051 const Twine &Name = "") {
2052 if (V->getType() == DestTy)
2053 return V;
2054 if (auto *VC = dyn_cast<Constant>(V))
2055 return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name);
2056 return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name);
2057 }
2058
2059 Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
2060 const Twine &Name = "") {
2061 if (V->getType() == DestTy)
2062 return V;
2063 if (auto *VC = dyn_cast<Constant>(V))
2064 return Insert(Folder.CreateCast(Op, VC, DestTy), Name);
2065 return Insert(CastInst::Create(Op, V, DestTy), Name);
2066 }
2067
2068 Value *CreatePointerCast(Value *V, Type *DestTy,
2069 const Twine &Name = "") {
2070 if (V->getType() == DestTy)
2071 return V;
2072 if (auto *VC = dyn_cast<Constant>(V))
2073 return Insert(Folder.CreatePointerCast(VC, DestTy), Name);
2074 return Insert(CastInst::CreatePointerCast(V, DestTy), Name);
2075 }
2076
2077 Value *CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy,
2078 const Twine &Name = "") {
2079 if (V->getType() == DestTy)
2080 return V;
2081
2082 if (auto *VC = dyn_cast<Constant>(V)) {
2083 return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy),
2084 Name);
2085 }
2086
2087 return Insert(CastInst::CreatePointerBitCastOrAddrSpaceCast(V, DestTy),
2088 Name);
2089 }
2090
2091 Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned,
2092 const Twine &Name = "") {
2093 if (V->getType() == DestTy)
2094 return V;
2095 if (auto *VC = dyn_cast<Constant>(V))
2096 return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name);
2097 return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name);
2098 }
2099
2100 Value *CreateBitOrPointerCast(Value *V, Type *DestTy,
2101 const Twine &Name = "") {
2102 if (V->getType() == DestTy)
2103 return V;
2104 if (V->getType()->isPtrOrPtrVectorTy() && DestTy->isIntOrIntVectorTy())
2105 return CreatePtrToInt(V, DestTy, Name);
2106 if (V->getType()->isIntOrIntVectorTy() && DestTy->isPtrOrPtrVectorTy())
2107 return CreateIntToPtr(V, DestTy, Name);
2108
2109 return CreateBitCast(V, DestTy, Name);
2110 }
2111
2112 Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") {
2113 if (V->getType() == DestTy)
2114 return V;
2115 if (auto *VC = dyn_cast<Constant>(V))
2116 return Insert(Folder.CreateFPCast(VC, DestTy), Name);
2117 return Insert(CastInst::CreateFPCast(V, DestTy), Name);
2118 }
2119
2120 CallInst *CreateConstrainedFPCast(
2121 Intrinsic::ID ID, Value *V, Type *DestTy,
2122 Instruction *FMFSource = nullptr, const Twine &Name = "",
2123 MDNode *FPMathTag = nullptr,
2124 std::optional<RoundingMode> Rounding = std::nullopt,
2125 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2126
2127 // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
2128 // compile time error, instead of converting the string to bool for the
2129 // isSigned parameter.
2130 Value *CreateIntCast(Value *, Type *, const char *) = delete;
2131
2132 //===--------------------------------------------------------------------===//
2133 // Instruction creation methods: Compare Instructions
2134 //===--------------------------------------------------------------------===//
2135
2136 Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") {
2137 return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name);
2138 }
2139
2140 Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") {
2141 return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name);
2142 }
2143
2144 Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") {
2145 return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name);
2146 }
2147
2148 Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") {
2149 return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name);
2150 }
2151
2152 Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") {
2153 return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name);
2154 }
2155
2156 Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") {
2157 return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name);
2158 }
2159
2160 Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") {
2161 return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name);
2162 }
2163
2164 Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") {
2165 return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name);
2166 }
2167
2168 Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") {
2169 return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name);
2170 }
2171
2172 Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") {
2173 return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name);
2174 }
2175
2176 Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "",
2177 MDNode *FPMathTag = nullptr) {
2178 return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag);
2179 }
2180
2181 Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "",
2182 MDNode *FPMathTag = nullptr) {
2183 return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag);
2184 }
2185
2186 Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "",
2187 MDNode *FPMathTag = nullptr) {
2188 return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag);
2189 }
2190
2191 Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "",
2192 MDNode *FPMathTag = nullptr) {
2193 return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag);
2194 }
2195
2196 Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "",
2197 MDNode *FPMathTag = nullptr) {
2198 return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag);
2199 }
2200
2201 Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "",
2202 MDNode *FPMathTag = nullptr) {
2203 return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag);
2204 }
2205
2206 Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "",
2207 MDNode *FPMathTag = nullptr) {
2208 return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag);
2209 }
2210
2211 Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "",
2212 MDNode *FPMathTag = nullptr) {
2213 return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag);
2214 }
2215
2216 Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "",
2217 MDNode *FPMathTag = nullptr) {
2218 return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag);
2219 }
2220
2221 Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "",
2222 MDNode *FPMathTag = nullptr) {
2223 return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag);
2224 }
2225
2226 Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "",
2227 MDNode *FPMathTag = nullptr) {
2228 return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag);
2229 }
2230
2231 Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "",
2232 MDNode *FPMathTag = nullptr) {
2233 return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag);
2234 }
2235
2236 Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "",
2237 MDNode *FPMathTag = nullptr) {
2238 return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag);
2239 }
2240
2241 Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "",
2242 MDNode *FPMathTag = nullptr) {
2243 return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag);
2244 }
2245
2246 Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
2247 const Twine &Name = "") {
2248 if (auto *V = Folder.FoldICmp(P, LHS, RHS))
2249 return V;
2250 return Insert(new ICmpInst(P, LHS, RHS), Name);
2251 }
2252
2253 // Create a quiet floating-point comparison (i.e. one that raises an FP
2254 // exception only in the case where an input is a signaling NaN).
2255 // Note that this differs from CreateFCmpS only if IsFPConstrained is true.
2256 Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
2257 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2258 return CreateFCmpHelper(P, LHS, RHS, Name, FPMathTag, false);
2259 }
2260
2261 Value *CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
2262 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2263 return CmpInst::isFPPredicate(Pred)
2264 ? CreateFCmp(Pred, LHS, RHS, Name, FPMathTag)
2265 : CreateICmp(Pred, LHS, RHS, Name);
2266 }
2267
2268 // Create a signaling floating-point comparison (i.e. one that raises an FP
2269 // exception whenever an input is any NaN, signaling or quiet).
2270 // Note that this differs from CreateFCmp only if IsFPConstrained is true.
2271 Value *CreateFCmpS(CmpInst::Predicate P, Value *LHS, Value *RHS,
2272 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2273 return CreateFCmpHelper(P, LHS, RHS, Name, FPMathTag, true);
2274 }
2275
2276private:
2277 // Helper routine to create either a signaling or a quiet FP comparison.
2278 Value *CreateFCmpHelper(CmpInst::Predicate P, Value *LHS, Value *RHS,
2279 const Twine &Name, MDNode *FPMathTag,
2280 bool IsSignaling);
2281
2282public:
2283 CallInst *CreateConstrainedFPCmp(
2284 Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R,
2285 const Twine &Name = "",
2286 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2287
2288 //===--------------------------------------------------------------------===//
2289 // Instruction creation methods: Other Instructions
2290 //===--------------------------------------------------------------------===//
2291
2292 PHINode *CreatePHI(Type *Ty, unsigned NumReservedValues,
2293 const Twine &Name = "") {
2294 PHINode *Phi = PHINode::Create(Ty, NumReservedValues);
2295 if (isa<FPMathOperator>(Phi))
2296 setFPAttrs(Phi, nullptr /* MDNode* */, FMF);
2297 return Insert(Phi, Name);
2298 }
2299
2300private:
2301 CallInst *createCallHelper(Function *Callee, ArrayRef<Value *> Ops,
2302 const Twine &Name = "",
2303 Instruction *FMFSource = nullptr,
2304 ArrayRef<OperandBundleDef> OpBundles = {});
2305
2306public:
2307 CallInst *CreateCall(FunctionType *FTy, Value *Callee,
2308 ArrayRef<Value *> Args = std::nullopt,
2309 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2310 CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
2311 if (IsFPConstrained)
2312 setConstrainedFPCallAttr(CI);
2313 if (isa<FPMathOperator>(CI))
2314 setFPAttrs(CI, FPMathTag, FMF);
2315 return Insert(CI, Name);
2316 }
2317
2318 CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
2319 ArrayRef<OperandBundleDef> OpBundles,
2320 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2321 CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles);
2322 if (IsFPConstrained)
2323 setConstrainedFPCallAttr(CI);
2324 if (isa<FPMathOperator>(CI))
2325 setFPAttrs(CI, FPMathTag, FMF);
2326 return Insert(CI, Name);
2327 }
2328
2329 CallInst *CreateCall(FunctionCallee Callee,
2330 ArrayRef<Value *> Args = std::nullopt,
2331 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2332 return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
2333 FPMathTag);
2334 }
2335
2336 CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
2337 ArrayRef<OperandBundleDef> OpBundles,
2338 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2339 return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args,
2340 OpBundles, Name, FPMathTag);
2341 }
2342
2343 CallInst *CreateConstrainedFPCall(
2344 Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
2345 std::optional<RoundingMode> Rounding = std::nullopt,
2346 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2347
2348 Value *CreateSelect(Value *C, Value *True, Value *False,
2349 const Twine &Name = "", Instruction *MDFrom = nullptr);
2350
2351 VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") {
2352 return Insert(new VAArgInst(List, Ty), Name);
2353 }
2354
2355 Value *CreateExtractElement(Value *Vec, Value *Idx,
2356 const Twine &Name = "") {
2357 if (Value *V = Folder.FoldExtractElement(Vec, Idx))
2358 return V;
2359 return Insert(ExtractElementInst::Create(Vec, Idx), Name);
2360 }
2361
2362 Value *CreateExtractElement(Value *Vec, uint64_t Idx,
2363 const Twine &Name = "") {
2364 return CreateExtractElement(Vec, getInt64(Idx), Name);
2365 }
2366
2367 Value *CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx,
2368 const Twine &Name = "") {
2369 return CreateInsertElement(PoisonValue::get(VecTy), NewElt, Idx, Name);
2370 }
2371
2372 Value *CreateInsertElement(Type *VecTy, Value *NewElt, uint64_t Idx,
2373 const Twine &Name = "") {
2374 return CreateInsertElement(PoisonValue::get(VecTy), NewElt, Idx, Name);
2375 }
2376
2377 Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx,
2378 const Twine &Name = "") {
2379 if (Value *V = Folder.FoldInsertElement(Vec, NewElt, Idx))
2380 return V;
2381 return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name);
2382 }
2383
2384 Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx,
2385 const Twine &Name = "") {
2386 return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name);
2387 }
2388
2389 Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask,
2390 const Twine &Name = "") {
2391 SmallVector<int, 16> IntMask;
2392 ShuffleVectorInst::getShuffleMask(cast<Constant>(Mask), IntMask);
2393 return CreateShuffleVector(V1, V2, IntMask, Name);
2394 }
2395
2396 /// See class ShuffleVectorInst for a description of the mask representation.
2397 Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> Mask,
2398 const Twine &Name = "") {
2399 if (Value *V = Folder.FoldShuffleVector(V1, V2, Mask))
2400 return V;
2401 return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
2402 }
2403
2404 /// Create a unary shuffle. The second vector operand of the IR instruction
2405 /// is poison.
2406 Value *CreateShuffleVector(Value *V, ArrayRef<int> Mask,
2407 const Twine &Name = "") {
2408 return CreateShuffleVector(V, PoisonValue::get(V->getType()), Mask, Name);
2409 }
2410
2411 Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs,
2412 const Twine &Name = "") {
2413 if (auto *V = Folder.FoldExtractValue(Agg, Idxs))
2414 return V;
2415 return Insert(ExtractValueInst::Create(Agg, Idxs), Name);
2416 }
2417
2418 Value *CreateInsertValue(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
2419 const Twine &Name = "") {
2420 if (auto *V = Folder.FoldInsertValue(Agg, Val, Idxs))
2421 return V;
2422 return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name);
2423 }
2424
2425 LandingPadInst *CreateLandingPad(Type *Ty, unsigned NumClauses,
2426 const Twine &Name = "") {
2427 return Insert(LandingPadInst::Create(Ty, NumClauses), Name);
2428 }
2429
2430 Value *CreateFreeze(Value *V, const Twine &Name = "") {
2431 return Insert(new FreezeInst(V), Name);
2432 }
2433
2434 //===--------------------------------------------------------------------===//
2435 // Utility creation methods
2436 //===--------------------------------------------------------------------===//
2437
2438 /// Return a boolean value testing if \p Arg == 0.
2439 Value *CreateIsNull(Value *Arg, const Twine &Name = "") {
2440 return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), Name);
2441 }
2442
2443 /// Return a boolean value testing if \p Arg != 0.
2444 Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") {
2445 return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), Name);
2446 }
2447
2448 /// Return a boolean value testing if \p Arg < 0.
2449 Value *CreateIsNeg(Value *Arg, const Twine &Name = "") {
2450 return CreateICmpSLT(Arg, ConstantInt::getNullValue(Arg->getType()), Name);
2451 }
2452
2453 /// Return a boolean value testing if \p Arg > -1.
2454 Value *CreateIsNotNeg(Value *Arg, const Twine &Name = "") {
2455 return CreateICmpSGT(Arg, ConstantInt::getAllOnesValue(Arg->getType()),
2456 Name);
2457 }
2458
2459 /// Return the i64 difference between two pointer values, dividing out
2460 /// the size of the pointed-to objects.
2461 ///
2462 /// This is intended to implement C-style pointer subtraction. As such, the
2463 /// pointers must be appropriately aligned for their element types and
2464 /// pointing into the same object.
2465 Value *CreatePtrDiff(Type *ElemTy, Value *LHS, Value *RHS,
2466 const Twine &Name = "");
2467
2468 /// Create a launder.invariant.group intrinsic call. If Ptr type is
2469 /// different from pointer to i8, it's casted to pointer to i8 in the same
2470 /// address space before call and casted back to Ptr type after call.
2471 Value *CreateLaunderInvariantGroup(Value *Ptr);
2472
2473 /// \brief Create a strip.invariant.group intrinsic call. If Ptr type is
2474 /// different from pointer to i8, it's casted to pointer to i8 in the same
2475 /// address space before call and casted back to Ptr type after call.
2476 Value *CreateStripInvariantGroup(Value *Ptr);
2477
2478 /// Return a vector value that contains the vector V reversed
2479 Value *CreateVectorReverse(Value *V, const Twine &Name = "");
2480
2481 /// Return a vector splice intrinsic if using scalable vectors, otherwise
2482 /// return a shufflevector. If the immediate is positive, a vector is
2483 /// extracted from concat(V1, V2), starting at Imm. If the immediate
2484 /// is negative, we extract -Imm elements from V1 and the remaining
2485 /// elements from V2. Imm is a signed integer in the range
2486 /// -VL <= Imm < VL (where VL is the runtime vector length of the
2487 /// source/result vector)
2488 Value *CreateVectorSplice(Value *V1, Value *V2, int64_t Imm,
2489 const Twine &Name = "");
2490
2491 /// Return a vector value that contains \arg V broadcasted to \p
2492 /// NumElts elements.
2493 Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "");
2494
2495 /// Return a vector value that contains \arg V broadcasted to \p
2496 /// EC elements.
2497 Value *CreateVectorSplat(ElementCount EC, Value *V, const Twine &Name = "");
2498
2499 /// Return a value that has been extracted from a larger integer type.
2500 Value *CreateExtractInteger(const DataLayout &DL, Value *From,
2501 IntegerType *ExtractedTy, uint64_t Offset,
2502 const Twine &Name);
2503
2504 Value *CreatePreserveArrayAccessIndex(Type *ElTy, Value *Base,
2505 unsigned Dimension, unsigned LastIndex,
2506 MDNode *DbgInfo);
2507
2508 Value *CreatePreserveUnionAccessIndex(Value *Base, unsigned FieldIndex,
2509 MDNode *DbgInfo);
2510
2511 Value *CreatePreserveStructAccessIndex(Type *ElTy, Value *Base,
2512 unsigned Index, unsigned FieldIndex,
2513 MDNode *DbgInfo);
2514
2515private:
2516 /// Helper function that creates an assume intrinsic call that
2517 /// represents an alignment assumption on the provided pointer \p PtrValue
2518 /// with offset \p OffsetValue and alignment value \p AlignValue.
2519 CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL,
2520 Value *PtrValue, Value *AlignValue,
2521 Value *OffsetValue);
2522
2523public:
2524 /// Create an assume intrinsic call that represents an alignment
2525 /// assumption on the provided pointer.
2526 ///
2527 /// An optional offset can be provided, and if it is provided, the offset
2528 /// must be subtracted from the provided pointer to get the pointer with the
2529 /// specified alignment.
2530 CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
2531 unsigned Alignment,
2532 Value *OffsetValue = nullptr);
2533
2534 /// Create an assume intrinsic call that represents an alignment
2535 /// assumption on the provided pointer.
2536 ///
2537 /// An optional offset can be provided, and if it is provided, the offset
2538 /// must be subtracted from the provided pointer to get the pointer with the
2539 /// specified alignment.
2540 ///
2541 /// This overload handles the condition where the Alignment is dependent
2542 /// on an existing value rather than a static value.
2543 CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
2544 Value *Alignment,
2545 Value *OffsetValue = nullptr);
2546};
2547
2548/// This provides a uniform API for creating instructions and inserting
2549/// them into a basic block: either at the end of a BasicBlock, or at a specific
2550/// iterator location in a block.
2551///
2552/// Note that the builder does not expose the full generality of LLVM
2553/// instructions. For access to extra instruction properties, use the mutators
2554/// (e.g. setVolatile) on the instructions after they have been
2555/// created. Convenience state exists to specify fast-math flags and fp-math
2556/// tags.
2557///
2558/// The first template argument specifies a class to use for creating constants.
2559/// This defaults to creating minimally folded constants. The second template
2560/// argument allows clients to specify custom insertion hooks that are called on
2561/// every newly created insertion.
2562template <typename FolderTy = ConstantFolder,
2563 typename InserterTy = IRBuilderDefaultInserter>
2564class IRBuilder : public IRBuilderBase {
2565private:
2566 FolderTy Folder;
2567 InserterTy Inserter;
2568
2569public:
2570 IRBuilder(LLVMContext &C, FolderTy Folder, InserterTy Inserter = InserterTy(),
2571 MDNode *FPMathTag = nullptr,
2572 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2573 : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles),
2574 Folder(Folder), Inserter(Inserter) {}
2575
2576 explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr,
2577 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2578 : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles) {}
2579
2580 explicit IRBuilder(BasicBlock *TheBB, FolderTy Folder,
2581 MDNode *FPMathTag = nullptr,
2582 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2583 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2584 FPMathTag, OpBundles),
2585 Folder(Folder) {
2586 SetInsertPoint(TheBB);
2587 }
2588
2589 explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr,
2590 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2591 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2592 FPMathTag, OpBundles) {
2593 SetInsertPoint(TheBB);
2594 }
2595
2596 explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr,
2597 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2598 : IRBuilderBase(IP->getContext(), this->Folder, this->Inserter, FPMathTag,
2599 OpBundles) {
2600 SetInsertPoint(IP);
2601 }
2602
2603 IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, FolderTy Folder,
2604 MDNode *FPMathTag = nullptr,
2605 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2606 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2607 FPMathTag, OpBundles),
2608 Folder(Folder) {
2609 SetInsertPoint(TheBB, IP);
2610 }
2611
2612 IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
2613 MDNode *FPMathTag = nullptr,
2614 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2615 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2616 FPMathTag, OpBundles) {
2617 SetInsertPoint(TheBB, IP);
2618 }
2619
2620 /// Avoid copying the full IRBuilder. Prefer using InsertPointGuard
2621 /// or FastMathFlagGuard instead.
2622 IRBuilder(const IRBuilder &) = delete;
2623
2624 InserterTy &getInserter() { return Inserter; }
2625};
2626
2627template <typename FolderTy, typename InserterTy>
2628IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *,
2629 ArrayRef<OperandBundleDef>) -> IRBuilder<FolderTy, InserterTy>;
2630IRBuilder(LLVMContext &, MDNode *, ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2631template <typename FolderTy>
2632IRBuilder(BasicBlock *, FolderTy, MDNode *, ArrayRef<OperandBundleDef>)
2633 -> IRBuilder<FolderTy>;
2634IRBuilder(BasicBlock *, MDNode *, ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2635IRBuilder(Instruction *, MDNode *, ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2636template <typename FolderTy>
2637IRBuilder(BasicBlock *, BasicBlock::iterator, FolderTy, MDNode *,
2638 ArrayRef<OperandBundleDef>) -> IRBuilder<FolderTy>;
2639IRBuilder(BasicBlock *, BasicBlock::iterator, MDNode *,
2640 ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2641
2642
2643// Create wrappers for C Binding types (see CBindingWrapping.h).
2644DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef)inline IRBuilder<> *unwrap(LLVMBuilderRef P) { return reinterpret_cast
<IRBuilder<>*>(P); } inline LLVMBuilderRef wrap(const
IRBuilder<> *P) { return reinterpret_cast<LLVMBuilderRef
>(const_cast<IRBuilder<>*>(P)); }
2645
2646} // end namespace llvm
2647
2648#endif // LLVM_IR_IRBUILDER_H