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 1679915782 -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-03-27-130437-16335-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 //===--------------------------------------------------------------------===//
571 // Intrinsic creation methods
572 //===--------------------------------------------------------------------===//
573
574 /// Create and insert a memset to the specified pointer and the
575 /// specified value.
576 ///
577 /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
578 /// specified, it will be added to the instruction. Likewise with alias.scope
579 /// and noalias tags.
580 CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size,
581 MaybeAlign Align, bool isVolatile = false,
582 MDNode *TBAATag = nullptr, MDNode *ScopeTag = nullptr,
583 MDNode *NoAliasTag = nullptr) {
584 return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile,
585 TBAATag, ScopeTag, NoAliasTag);
586 }
587
588 CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, MaybeAlign Align,
589 bool isVolatile = false, MDNode *TBAATag = nullptr,
590 MDNode *ScopeTag = nullptr,
591 MDNode *NoAliasTag = nullptr);
592
593 CallInst *CreateMemSetInline(Value *Dst, MaybeAlign DstAlign, Value *Val,
594 Value *Size, bool IsVolatile = false,
595 MDNode *TBAATag = nullptr,
596 MDNode *ScopeTag = nullptr,
597 MDNode *NoAliasTag = nullptr);
598
599 /// Create and insert an element unordered-atomic memset of the region of
600 /// memory starting at the given pointer to the given value.
601 ///
602 /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
603 /// specified, it will be added to the instruction. Likewise with alias.scope
604 /// and noalias tags.
605 CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val,
606 uint64_t Size, Align Alignment,
607 uint32_t ElementSize,
608 MDNode *TBAATag = nullptr,
609 MDNode *ScopeTag = nullptr,
610 MDNode *NoAliasTag = nullptr) {
611 return CreateElementUnorderedAtomicMemSet(Ptr, Val, getInt64(Size),
612 Align(Alignment), ElementSize,
613 TBAATag, ScopeTag, NoAliasTag);
614 }
615
616 CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val,
617 Value *Size, Align Alignment,
618 uint32_t ElementSize,
619 MDNode *TBAATag = nullptr,
620 MDNode *ScopeTag = nullptr,
621 MDNode *NoAliasTag = nullptr);
622
623 /// Create and insert a memcpy between the specified pointers.
624 ///
625 /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
626 /// specified, it will be added to the instruction. Likewise with alias.scope
627 /// and noalias tags.
628 CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src,
629 MaybeAlign SrcAlign, uint64_t Size,
630 bool isVolatile = false, MDNode *TBAATag = nullptr,
631 MDNode *TBAAStructTag = nullptr,
632 MDNode *ScopeTag = nullptr,
633 MDNode *NoAliasTag = nullptr) {
634 return CreateMemCpy(Dst, DstAlign, Src, SrcAlign, getInt64(Size),
635 isVolatile, TBAATag, TBAAStructTag, ScopeTag,
636 NoAliasTag);
637 }
638
639 CallInst *CreateMemTransferInst(
640 Intrinsic::ID IntrID, Value *Dst, MaybeAlign DstAlign, Value *Src,
641 MaybeAlign SrcAlign, Value *Size, bool isVolatile = false,
642 MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
643 MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr);
644
645 CallInst *CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src,
646 MaybeAlign SrcAlign, Value *Size,
647 bool isVolatile = false, MDNode *TBAATag = nullptr,
648 MDNode *TBAAStructTag = nullptr,
649 MDNode *ScopeTag = nullptr,
650 MDNode *NoAliasTag = nullptr) {
651 return CreateMemTransferInst(Intrinsic::memcpy, Dst, DstAlign, Src,
652 SrcAlign, Size, isVolatile, TBAATag,
653 TBAAStructTag, ScopeTag, NoAliasTag);
654 }
655
656 CallInst *
657 CreateMemCpyInline(Value *Dst, MaybeAlign DstAlign, Value *Src,
658 MaybeAlign SrcAlign, Value *Size, bool IsVolatile = false,
659 MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
660 MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr);
661
662 /// Create and insert an element unordered-atomic memcpy between the
663 /// specified pointers.
664 ///
665 /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, respectively.
666 ///
667 /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
668 /// specified, it will be added to the instruction. Likewise with alias.scope
669 /// and noalias tags.
670 CallInst *CreateElementUnorderedAtomicMemCpy(
671 Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size,
672 uint32_t ElementSize, MDNode *TBAATag = nullptr,
673 MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
674 MDNode *NoAliasTag = nullptr);
675
676 CallInst *CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src,
677 MaybeAlign SrcAlign, uint64_t Size,
678 bool isVolatile = false, MDNode *TBAATag = nullptr,
679 MDNode *ScopeTag = nullptr,
680 MDNode *NoAliasTag = nullptr) {
681 return CreateMemMove(Dst, DstAlign, Src, SrcAlign, getInt64(Size),
682 isVolatile, TBAATag, ScopeTag, NoAliasTag);
683 }
684
685 CallInst *CreateMemMove(Value *Dst, MaybeAlign DstAlign, Value *Src,
686 MaybeAlign SrcAlign, Value *Size,
687 bool isVolatile = false, MDNode *TBAATag = nullptr,
688 MDNode *ScopeTag = nullptr,
689 MDNode *NoAliasTag = nullptr);
690
691 /// \brief Create and insert an element unordered-atomic memmove between the
692 /// specified pointers.
693 ///
694 /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers,
695 /// respectively.
696 ///
697 /// If the pointers aren't i8*, they will be converted. If a TBAA tag is
698 /// specified, it will be added to the instruction. Likewise with alias.scope
699 /// and noalias tags.
700 CallInst *CreateElementUnorderedAtomicMemMove(
701 Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size,
702 uint32_t ElementSize, MDNode *TBAATag = nullptr,
703 MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr,
704 MDNode *NoAliasTag = nullptr);
705
706private:
707 CallInst *getReductionIntrinsic(Intrinsic::ID ID, Value *Src);
708
709public:
710 /// Create a sequential vector fadd reduction intrinsic of the source vector.
711 /// The first parameter is a scalar accumulator value. An unordered reduction
712 /// can be created by adding the reassoc fast-math flag to the resulting
713 /// sequential reduction.
714 CallInst *CreateFAddReduce(Value *Acc, Value *Src);
715
716 /// Create a sequential vector fmul 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 *CreateFMulReduce(Value *Acc, Value *Src);
721
722 /// Create a vector int add reduction intrinsic of the source vector.
723 CallInst *CreateAddReduce(Value *Src);
724
725 /// Create a vector int mul reduction intrinsic of the source vector.
726 CallInst *CreateMulReduce(Value *Src);
727
728 /// Create a vector int AND reduction intrinsic of the source vector.
729 CallInst *CreateAndReduce(Value *Src);
730
731 /// Create a vector int OR reduction intrinsic of the source vector.
732 CallInst *CreateOrReduce(Value *Src);
733
734 /// Create a vector int XOR reduction intrinsic of the source vector.
735 CallInst *CreateXorReduce(Value *Src);
736
737 /// Create a vector integer max reduction intrinsic of the source
738 /// vector.
739 CallInst *CreateIntMaxReduce(Value *Src, bool IsSigned = false);
740
741 /// Create a vector integer min reduction intrinsic of the source
742 /// vector.
743 CallInst *CreateIntMinReduce(Value *Src, bool IsSigned = false);
744
745 /// Create a vector float max reduction intrinsic of the source
746 /// vector.
747 CallInst *CreateFPMaxReduce(Value *Src);
748
749 /// Create a vector float min reduction intrinsic of the source
750 /// vector.
751 CallInst *CreateFPMinReduce(Value *Src);
752
753 /// Create a lifetime.start intrinsic.
754 ///
755 /// If the pointer isn't i8* it will be converted.
756 CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr);
757
758 /// Create a lifetime.end intrinsic.
759 ///
760 /// If the pointer isn't i8* it will be converted.
761 CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr);
762
763 /// Create a call to invariant.start intrinsic.
764 ///
765 /// If the pointer isn't i8* it will be converted.
766 CallInst *CreateInvariantStart(Value *Ptr, ConstantInt *Size = nullptr);
767
768 /// Create a call to llvm.threadlocal.address intrinsic.
769 CallInst *CreateThreadLocalAddress(Value *Ptr);
770
771 /// Create a call to Masked Load intrinsic
772 CallInst *CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask,
773 Value *PassThru = nullptr, const Twine &Name = "");
774
775 /// Create a call to Masked Store intrinsic
776 CallInst *CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment,
777 Value *Mask);
778
779 /// Create a call to Masked Gather intrinsic
780 CallInst *CreateMaskedGather(Type *Ty, Value *Ptrs, Align Alignment,
781 Value *Mask = nullptr, Value *PassThru = nullptr,
782 const Twine &Name = "");
783
784 /// Create a call to Masked Scatter intrinsic
785 CallInst *CreateMaskedScatter(Value *Val, Value *Ptrs, Align Alignment,
786 Value *Mask = nullptr);
787
788 /// Create a call to Masked Expand Load intrinsic
789 CallInst *CreateMaskedExpandLoad(Type *Ty, Value *Ptr, Value *Mask = nullptr,
790 Value *PassThru = nullptr,
791 const Twine &Name = "");
792
793 /// Create a call to Masked Compress Store intrinsic
794 CallInst *CreateMaskedCompressStore(Value *Val, Value *Ptr,
795 Value *Mask = nullptr);
796
797 /// Create an assume intrinsic call that allows the optimizer to
798 /// assume that the provided condition will be true.
799 ///
800 /// The optional argument \p OpBundles specifies operand bundles that are
801 /// added to the call instruction.
802 CallInst *
803 CreateAssumption(Value *Cond,
804 ArrayRef<OperandBundleDef> OpBundles = std::nullopt);
805
806 /// Create a llvm.experimental.noalias.scope.decl intrinsic call.
807 Instruction *CreateNoAliasScopeDeclaration(Value *Scope);
808 Instruction *CreateNoAliasScopeDeclaration(MDNode *ScopeTag) {
809 return CreateNoAliasScopeDeclaration(
810 MetadataAsValue::get(Context, ScopeTag));
811 }
812
813 /// Create a call to the experimental.gc.statepoint intrinsic to
814 /// start a new statepoint sequence.
815 CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
816 FunctionCallee ActualCallee,
817 ArrayRef<Value *> CallArgs,
818 std::optional<ArrayRef<Value *>> DeoptArgs,
819 ArrayRef<Value *> GCArgs,
820 const Twine &Name = "");
821
822 /// Create a call to the experimental.gc.statepoint intrinsic to
823 /// start a new statepoint sequence.
824 CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
825 FunctionCallee ActualCallee, uint32_t Flags,
826 ArrayRef<Value *> CallArgs,
827 std::optional<ArrayRef<Use>> TransitionArgs,
828 std::optional<ArrayRef<Use>> DeoptArgs,
829 ArrayRef<Value *> GCArgs,
830 const Twine &Name = "");
831
832 /// Conveninence function for the common case when CallArgs are filled
833 /// in using ArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be
834 /// .get()'ed to get the Value pointer.
835 CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes,
836 FunctionCallee ActualCallee,
837 ArrayRef<Use> CallArgs,
838 std::optional<ArrayRef<Value *>> DeoptArgs,
839 ArrayRef<Value *> GCArgs,
840 const Twine &Name = "");
841
842 /// Create an invoke to the experimental.gc.statepoint intrinsic to
843 /// start a new statepoint sequence.
844 InvokeInst *
845 CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
846 FunctionCallee ActualInvokee, BasicBlock *NormalDest,
847 BasicBlock *UnwindDest, ArrayRef<Value *> InvokeArgs,
848 std::optional<ArrayRef<Value *>> DeoptArgs,
849 ArrayRef<Value *> GCArgs, const Twine &Name = "");
850
851 /// Create an invoke to the experimental.gc.statepoint intrinsic to
852 /// start a new statepoint sequence.
853 InvokeInst *CreateGCStatepointInvoke(
854 uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee,
855 BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags,
856 ArrayRef<Value *> InvokeArgs, std::optional<ArrayRef<Use>> TransitionArgs,
857 std::optional<ArrayRef<Use>> DeoptArgs, ArrayRef<Value *> GCArgs,
858 const Twine &Name = "");
859
860 // Convenience function for the common case when CallArgs are filled in using
861 // ArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to
862 // get the Value *.
863 InvokeInst *
864 CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes,
865 FunctionCallee ActualInvokee, BasicBlock *NormalDest,
866 BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs,
867 std::optional<ArrayRef<Value *>> DeoptArgs,
868 ArrayRef<Value *> GCArgs, const Twine &Name = "");
869
870 /// Create a call to the experimental.gc.result intrinsic to extract
871 /// the result from a call wrapped in a statepoint.
872 CallInst *CreateGCResult(Instruction *Statepoint,
873 Type *ResultType,
874 const Twine &Name = "");
875
876 /// Create a call to the experimental.gc.relocate intrinsics to
877 /// project the relocated value of one pointer from the statepoint.
878 CallInst *CreateGCRelocate(Instruction *Statepoint,
879 int BaseOffset,
880 int DerivedOffset,
881 Type *ResultType,
882 const Twine &Name = "");
883
884 /// Create a call to the experimental.gc.pointer.base intrinsic to get the
885 /// base pointer for the specified derived pointer.
886 CallInst *CreateGCGetPointerBase(Value *DerivedPtr, const Twine &Name = "");
887
888 /// Create a call to the experimental.gc.get.pointer.offset intrinsic to get
889 /// the offset of the specified derived pointer from its base.
890 CallInst *CreateGCGetPointerOffset(Value *DerivedPtr, const Twine &Name = "");
891
892 /// Create a call to llvm.vscale, multiplied by \p Scaling. The type of VScale
893 /// will be the same type as that of \p Scaling.
894 Value *CreateVScale(Constant *Scaling, const Twine &Name = "");
895
896 /// Create an expression which evaluates to the number of elements in \p EC
897 /// at runtime.
898 Value *CreateElementCount(Type *DstType, ElementCount EC);
899
900 /// Create an expression which evaluates to the number of units in \p Size
901 /// at runtime. This works for both units of bits and bytes.
902 Value *CreateTypeSize(Type *DstType, TypeSize Size);
903
904 /// Creates a vector of type \p DstType with the linear sequence <0, 1, ...>
905 Value *CreateStepVector(Type *DstType, const Twine &Name = "");
906
907 /// Create a call to intrinsic \p ID with 1 operand which is mangled on its
908 /// type.
909 CallInst *CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,
910 Instruction *FMFSource = nullptr,
911 const Twine &Name = "");
912
913 /// Create a call to intrinsic \p ID with 2 operands which is mangled on the
914 /// first type.
915 CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS,
916 Instruction *FMFSource = nullptr,
917 const Twine &Name = "");
918
919 /// Create a call to intrinsic \p ID with \p Args, mangled using \p Types. If
920 /// \p FMFSource is provided, copy fast-math-flags from that instruction to
921 /// the intrinsic.
922 CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef<Type *> Types,
923 ArrayRef<Value *> Args,
924 Instruction *FMFSource = nullptr,
925 const Twine &Name = "");
926
927 /// Create a call to intrinsic \p ID with \p RetTy and \p Args. If
928 /// \p FMFSource is provided, copy fast-math-flags from that instruction to
929 /// the intrinsic.
930 CallInst *CreateIntrinsic(Type *RetTy, Intrinsic::ID ID,
931 ArrayRef<Value *> Args,
932 Instruction *FMFSource = nullptr,
933 const Twine &Name = "");
934
935 /// Create call to the minnum intrinsic.
936 CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
937 return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, nullptr, Name);
938 }
939
940 /// Create call to the maxnum intrinsic.
941 CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
942 return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, nullptr, Name);
943 }
944
945 /// Create call to the minimum intrinsic.
946 CallInst *CreateMinimum(Value *LHS, Value *RHS, const Twine &Name = "") {
947 return CreateBinaryIntrinsic(Intrinsic::minimum, LHS, RHS, nullptr, Name);
948 }
949
950 /// Create call to the maximum intrinsic.
951 CallInst *CreateMaximum(Value *LHS, Value *RHS, const Twine &Name = "") {
952 return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name);
953 }
954
955 /// Create call to the copysign intrinsic.
956 CallInst *CreateCopySign(Value *LHS, Value *RHS,
957 Instruction *FMFSource = nullptr,
958 const Twine &Name = "") {
959 return CreateBinaryIntrinsic(Intrinsic::copysign, LHS, RHS, FMFSource,
960 Name);
961 }
962
963 /// Create a call to the arithmetic_fence intrinsic.
964 CallInst *CreateArithmeticFence(Value *Val, Type *DstType,
965 const Twine &Name = "") {
966 return CreateIntrinsic(Intrinsic::arithmetic_fence, DstType, Val, nullptr,
967 Name);
968 }
969
970 /// Create a call to the vector.extract intrinsic.
971 CallInst *CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx,
972 const Twine &Name = "") {
973 return CreateIntrinsic(Intrinsic::vector_extract,
974 {DstType, SrcVec->getType()}, {SrcVec, Idx}, nullptr,
975 Name);
976 }
977
978 /// Create a call to the vector.insert intrinsic.
979 CallInst *CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec,
980 Value *Idx, const Twine &Name = "") {
981 return CreateIntrinsic(Intrinsic::vector_insert,
982 {DstType, SubVec->getType()}, {SrcVec, SubVec, Idx},
983 nullptr, Name);
984 }
985
986private:
987 /// Create a call to a masked intrinsic with given Id.
988 CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
989 ArrayRef<Type *> OverloadedTypes,
990 const Twine &Name = "");
991
992 Value *getCastedInt8PtrValue(Value *Ptr);
993
994 //===--------------------------------------------------------------------===//
995 // Instruction creation methods: Terminators
996 //===--------------------------------------------------------------------===//
997
998private:
999 /// Helper to add branch weight and unpredictable metadata onto an
1000 /// instruction.
1001 /// \returns The annotated instruction.
1002 template <typename InstTy>
1003 InstTy *addBranchMetadata(InstTy *I, MDNode *Weights, MDNode *Unpredictable) {
1004 if (Weights)
1005 I->setMetadata(LLVMContext::MD_prof, Weights);
1006 if (Unpredictable)
1007 I->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);
1008 return I;
1009 }
1010
1011public:
1012 /// Create a 'ret void' instruction.
1013 ReturnInst *CreateRetVoid() {
1014 return Insert(ReturnInst::Create(Context));
1015 }
1016
1017 /// Create a 'ret <val>' instruction.
1018 ReturnInst *CreateRet(Value *V) {
1019 return Insert(ReturnInst::Create(Context, V));
1020 }
1021
1022 /// Create a sequence of N insertvalue instructions,
1023 /// with one Value from the retVals array each, that build a aggregate
1024 /// return value one value at a time, and a ret instruction to return
1025 /// the resulting aggregate value.
1026 ///
1027 /// This is a convenience function for code that uses aggregate return values
1028 /// as a vehicle for having multiple return values.
1029 ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) {
1030 Value *V = PoisonValue::get(getCurrentFunctionReturnType());
1031 for (unsigned i = 0; i != N; ++i)
1032 V = CreateInsertValue(V, retVals[i], i, "mrv");
1033 return Insert(ReturnInst::Create(Context, V));
1034 }
1035
1036 /// Create an unconditional 'br label X' instruction.
1037 BranchInst *CreateBr(BasicBlock *Dest) {
1038 return Insert(BranchInst::Create(Dest));
1039 }
1040
1041 /// Create a conditional 'br Cond, TrueDest, FalseDest'
1042 /// instruction.
1043 BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
1044 MDNode *BranchWeights = nullptr,
1045 MDNode *Unpredictable = nullptr) {
1046 return Insert(addBranchMetadata(BranchInst::Create(True, False, Cond),
1047 BranchWeights, Unpredictable));
1048 }
1049
1050 /// Create a conditional 'br Cond, TrueDest, FalseDest'
1051 /// instruction. Copy branch meta data if available.
1052 BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
1053 Instruction *MDSrc) {
1054 BranchInst *Br = BranchInst::Create(True, False, Cond);
1055 if (MDSrc) {
1056 unsigned WL[4] = {LLVMContext::MD_prof, LLVMContext::MD_unpredictable,
1057 LLVMContext::MD_make_implicit, LLVMContext::MD_dbg};
1058 Br->copyMetadata(*MDSrc, WL);
1059 }
1060 return Insert(Br);
1061 }
1062
1063 /// Create a switch instruction with the specified value, default dest,
1064 /// and with a hint for the number of cases that will be added (for efficient
1065 /// allocation).
1066 SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10,
1067 MDNode *BranchWeights = nullptr,
1068 MDNode *Unpredictable = nullptr) {
1069 return Insert(addBranchMetadata(SwitchInst::Create(V, Dest, NumCases),
1070 BranchWeights, Unpredictable));
1071 }
1072
1073 /// Create an indirect branch instruction with the specified address
1074 /// operand, with an optional hint for the number of destinations that will be
1075 /// added (for efficient allocation).
1076 IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) {
1077 return Insert(IndirectBrInst::Create(Addr, NumDests));
1078 }
1079
1080 /// Create an invoke instruction.
1081 InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee,
1082 BasicBlock *NormalDest, BasicBlock *UnwindDest,
1083 ArrayRef<Value *> Args,
1084 ArrayRef<OperandBundleDef> OpBundles,
1085 const Twine &Name = "") {
1086 InvokeInst *II =
1087 InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args, OpBundles);
1088 if (IsFPConstrained)
1089 setConstrainedFPCallAttr(II);
1090 return Insert(II, Name);
1091 }
1092 InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee,
1093 BasicBlock *NormalDest, BasicBlock *UnwindDest,
1094 ArrayRef<Value *> Args = std::nullopt,
1095 const Twine &Name = "") {
1096 InvokeInst *II =
1097 InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args);
1098 if (IsFPConstrained)
1099 setConstrainedFPCallAttr(II);
1100 return Insert(II, Name);
1101 }
1102
1103 InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest,
1104 BasicBlock *UnwindDest, ArrayRef<Value *> Args,
1105 ArrayRef<OperandBundleDef> OpBundles,
1106 const Twine &Name = "") {
1107 return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(),
1108 NormalDest, UnwindDest, Args, OpBundles, Name);
1109 }
1110
1111 InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest,
1112 BasicBlock *UnwindDest,
1113 ArrayRef<Value *> Args = std::nullopt,
1114 const Twine &Name = "") {
1115 return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(),
1116 NormalDest, UnwindDest, Args, Name);
1117 }
1118
1119 /// \brief Create a callbr instruction.
1120 CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee,
1121 BasicBlock *DefaultDest,
1122 ArrayRef<BasicBlock *> IndirectDests,
1123 ArrayRef<Value *> Args = std::nullopt,
1124 const Twine &Name = "") {
1125 return Insert(CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests,
1126 Args), Name);
1127 }
1128 CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee,
1129 BasicBlock *DefaultDest,
1130 ArrayRef<BasicBlock *> IndirectDests,
1131 ArrayRef<Value *> Args,
1132 ArrayRef<OperandBundleDef> OpBundles,
1133 const Twine &Name = "") {
1134 return Insert(
1135 CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, Args,
1136 OpBundles), Name);
1137 }
1138
1139 CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest,
1140 ArrayRef<BasicBlock *> IndirectDests,
1141 ArrayRef<Value *> Args = std::nullopt,
1142 const Twine &Name = "") {
1143 return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(),
1144 DefaultDest, IndirectDests, Args, Name);
1145 }
1146 CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest,
1147 ArrayRef<BasicBlock *> IndirectDests,
1148 ArrayRef<Value *> Args,
1149 ArrayRef<OperandBundleDef> OpBundles,
1150 const Twine &Name = "") {
1151 return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(),
1152 DefaultDest, IndirectDests, Args, Name);
1153 }
1154
1155 ResumeInst *CreateResume(Value *Exn) {
1156 return Insert(ResumeInst::Create(Exn));
1157 }
1158
1159 CleanupReturnInst *CreateCleanupRet(CleanupPadInst *CleanupPad,
1160 BasicBlock *UnwindBB = nullptr) {
1161 return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB));
1162 }
1163
1164 CatchSwitchInst *CreateCatchSwitch(Value *ParentPad, BasicBlock *UnwindBB,
1165 unsigned NumHandlers,
1166 const Twine &Name = "") {
1167 return Insert(CatchSwitchInst::Create(ParentPad, UnwindBB, NumHandlers),
1168 Name);
1169 }
1170
1171 CatchPadInst *CreateCatchPad(Value *ParentPad, ArrayRef<Value *> Args,
1172 const Twine &Name = "") {
1173 return Insert(CatchPadInst::Create(ParentPad, Args), Name);
1174 }
1175
1176 CleanupPadInst *CreateCleanupPad(Value *ParentPad,
1177 ArrayRef<Value *> Args = std::nullopt,
1178 const Twine &Name = "") {
1179 return Insert(CleanupPadInst::Create(ParentPad, Args), Name);
1180 }
1181
1182 CatchReturnInst *CreateCatchRet(CatchPadInst *CatchPad, BasicBlock *BB) {
1183 return Insert(CatchReturnInst::Create(CatchPad, BB));
1184 }
1185
1186 UnreachableInst *CreateUnreachable() {
1187 return Insert(new UnreachableInst(Context));
1188 }
1189
1190 //===--------------------------------------------------------------------===//
1191 // Instruction creation methods: Binary Operators
1192 //===--------------------------------------------------------------------===//
1193private:
1194 BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc,
1195 Value *LHS, Value *RHS,
1196 const Twine &Name,
1197 bool HasNUW, bool HasNSW) {
1198 BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name);
1199 if (HasNUW) BO->setHasNoUnsignedWrap();
1200 if (HasNSW) BO->setHasNoSignedWrap();
1201 return BO;
1202 }
1203
1204 Instruction *setFPAttrs(Instruction *I, MDNode *FPMD,
1205 FastMathFlags FMF) const {
1206 if (!FPMD)
1207 FPMD = DefaultFPMathTag;
1208 if (FPMD)
1209 I->setMetadata(LLVMContext::MD_fpmath, FPMD);
1210 I->setFastMathFlags(FMF);
1211 return I;
1212 }
1213
1214 Value *getConstrainedFPRounding(std::optional<RoundingMode> Rounding) {
1215 RoundingMode UseRounding = DefaultConstrainedRounding;
1216
1217 if (Rounding)
1218 UseRounding = *Rounding;
1219
1220 std::optional<StringRef> RoundingStr =
1221 convertRoundingModeToStr(UseRounding);
1222 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", 1222, __extension__ __PRETTY_FUNCTION__
))
;
1223 auto *RoundingMDS = MDString::get(Context, *RoundingStr);
1224
1225 return MetadataAsValue::get(Context, RoundingMDS);
1226 }
1227
1228 Value *getConstrainedFPExcept(std::optional<fp::ExceptionBehavior> Except) {
1229 std::optional<StringRef> ExceptStr = convertExceptionBehaviorToStr(
1230 Except.value_or(DefaultConstrainedExcept));
1231 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", 1231, __extension__ __PRETTY_FUNCTION__
))
;
1232 auto *ExceptMDS = MDString::get(Context, *ExceptStr);
1233
1234 return MetadataAsValue::get(Context, ExceptMDS);
1235 }
1236
1237 Value *getConstrainedFPPredicate(CmpInst::Predicate Predicate) {
1238 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", 1241, __extension__ __PRETTY_FUNCTION__
))
1239 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", 1241, __extension__ __PRETTY_FUNCTION__
))
1240 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", 1241, __extension__ __PRETTY_FUNCTION__
))
1241 "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", 1241, __extension__ __PRETTY_FUNCTION__
))
;
1242
1243 StringRef PredicateStr = CmpInst::getPredicateName(Predicate);
1244 auto *PredicateMDS = MDString::get(Context, PredicateStr);
1245
1246 return MetadataAsValue::get(Context, PredicateMDS);
1247 }
1248
1249public:
1250 Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
1251 bool HasNUW = false, bool HasNSW = false) {
1252 if (Value *V =
34
Assuming 'V' is non-null
35
Taking true branch
1253 Folder.FoldNoWrapBinOp(Instruction::Add, LHS, RHS, HasNUW, HasNSW))
1254 return V;
1255 return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, HasNUW,
1256 HasNSW);
1257 }
1258
1259 Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
1260 return CreateAdd(LHS, RHS, Name, false, true);
1261 }
1262
1263 Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") {
1264 return CreateAdd(LHS, RHS, Name, true, false);
1265 }
1266
1267 Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "",
1268 bool HasNUW = false, bool HasNSW = false) {
1269 if (Value *V =
1270 Folder.FoldNoWrapBinOp(Instruction::Sub, LHS, RHS, HasNUW, HasNSW))
1271 return V;
1272 return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, HasNUW,
1273 HasNSW);
1274 }
1275
1276 Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
1277 return CreateSub(LHS, RHS, Name, false, true);
1278 }
1279
1280 Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") {
1281 return CreateSub(LHS, RHS, Name, true, false);
1282 }
1283
1284 Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "",
1285 bool HasNUW = false, bool HasNSW = false) {
1286 if (Value *V =
1287 Folder.FoldNoWrapBinOp(Instruction::Mul, LHS, RHS, HasNUW, HasNSW))
1288 return V;
1289 return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, HasNUW,
1290 HasNSW);
1291 }
1292
1293 Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
1294 return CreateMul(LHS, RHS, Name, false, true);
1295 }
1296
1297 Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") {
1298 return CreateMul(LHS, RHS, Name, true, false);
1299 }
1300
1301 Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "",
1302 bool isExact = false) {
1303 if (Value *V = Folder.FoldExactBinOp(Instruction::UDiv, LHS, RHS, isExact))
1304 return V;
1305 if (!isExact)
1306 return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name);
1307 return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name);
1308 }
1309
1310 Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
1311 return CreateUDiv(LHS, RHS, Name, true);
1312 }
1313
1314 Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "",
1315 bool isExact = false) {
1316 if (Value *V = Folder.FoldExactBinOp(Instruction::SDiv, LHS, RHS, isExact))
1317 return V;
1318 if (!isExact)
1319 return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name);
1320 return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name);
1321 }
1322
1323 Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
1324 return CreateSDiv(LHS, RHS, Name, true);
1325 }
1326
1327 Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") {
1328 if (Value *V = Folder.FoldBinOp(Instruction::URem, LHS, RHS))
1329 return V;
1330 return Insert(BinaryOperator::CreateURem(LHS, RHS), Name);
1331 }
1332
1333 Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") {
1334 if (Value *V = Folder.FoldBinOp(Instruction::SRem, LHS, RHS))
1335 return V;
1336 return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name);
1337 }
1338
1339 Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "",
1340 bool HasNUW = false, bool HasNSW = false) {
1341 if (Value *V =
1342 Folder.FoldNoWrapBinOp(Instruction::Shl, LHS, RHS, HasNUW, HasNSW))
1343 return V;
1344 return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name,
1345 HasNUW, HasNSW);
1346 }
1347
1348 Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "",
1349 bool HasNUW = false, bool HasNSW = false) {
1350 return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name,
1351 HasNUW, HasNSW);
1352 }
1353
1354 Value *CreateShl(Value *LHS, uint64_t 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 *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "",
1361 bool isExact = false) {
1362 if (Value *V = Folder.FoldExactBinOp(Instruction::LShr, LHS, RHS, isExact))
1363 return V;
1364 if (!isExact)
1365 return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name);
1366 return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name);
1367 }
1368
1369 Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
1370 bool isExact = false) {
1371 return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1372 }
1373
1374 Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
1375 bool isExact = false) {
1376 return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1377 }
1378
1379 Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "",
1380 bool isExact = false) {
1381 if (Value *V = Folder.FoldExactBinOp(Instruction::AShr, LHS, RHS, isExact))
1382 return V;
1383 if (!isExact)
1384 return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name);
1385 return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name);
1386 }
1387
1388 Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
1389 bool isExact = false) {
1390 return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1391 }
1392
1393 Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
1394 bool isExact = false) {
1395 return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
1396 }
1397
1398 Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
1399 if (auto *V = Folder.FoldBinOp(Instruction::And, LHS, RHS))
1400 return V;
1401 return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name);
1402 }
1403
1404 Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") {
1405 return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1406 }
1407
1408 Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") {
1409 return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1410 }
1411
1412 Value *CreateAnd(ArrayRef<Value*> Ops) {
1413 assert(!Ops.empty())(static_cast <bool> (!Ops.empty()) ? void (0) : __assert_fail
("!Ops.empty()", "llvm/include/llvm/IR/IRBuilder.h", 1413, __extension__
__PRETTY_FUNCTION__))
;
1414 Value *Accum = Ops[0];
1415 for (unsigned i = 1; i < Ops.size(); i++)
1416 Accum = CreateAnd(Accum, Ops[i]);
1417 return Accum;
1418 }
1419
1420 Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") {
1421 if (auto *V = Folder.FoldBinOp(Instruction::Or, LHS, RHS))
1422 return V;
1423 return Insert(BinaryOperator::CreateOr(LHS, RHS), Name);
1424 }
1425
1426 Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
1427 return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1428 }
1429
1430 Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
1431 return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1432 }
1433
1434 Value *CreateOr(ArrayRef<Value*> Ops) {
1435 assert(!Ops.empty())(static_cast <bool> (!Ops.empty()) ? void (0) : __assert_fail
("!Ops.empty()", "llvm/include/llvm/IR/IRBuilder.h", 1435, __extension__
__PRETTY_FUNCTION__))
;
1436 Value *Accum = Ops[0];
1437 for (unsigned i = 1; i < Ops.size(); i++)
1438 Accum = CreateOr(Accum, Ops[i]);
1439 return Accum;
1440 }
1441
1442 Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") {
1443 if (Value *V = Folder.FoldBinOp(Instruction::Xor, LHS, RHS))
1444 return V;
1445 return Insert(BinaryOperator::CreateXor(LHS, RHS), Name);
1446 }
1447
1448 Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") {
1449 return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1450 }
1451
1452 Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") {
1453 return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
1454 }
1455
1456 Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
1457 MDNode *FPMD = nullptr) {
1458 if (IsFPConstrained)
1459 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
1460 L, R, nullptr, Name, FPMD);
1461
1462 if (Value *V = Folder.FoldBinOpFMF(Instruction::FAdd, L, R, FMF))
1463 return V;
1464 Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
1465 return Insert(I, Name);
1466 }
1467
1468 /// Copy fast-math-flags from an instruction rather than using the builder's
1469 /// default FMF.
1470 Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource,
1471 const Twine &Name = "") {
1472 if (IsFPConstrained)
1473 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
1474 L, R, FMFSource, Name);
1475
1476 FastMathFlags FMF = FMFSource->getFastMathFlags();
1477 if (Value *V = Folder.FoldBinOpFMF(Instruction::FAdd, L, R, FMF))
1478 return V;
1479 Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, FMF);
1480 return Insert(I, Name);
1481 }
1482
1483 Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
1484 MDNode *FPMD = nullptr) {
1485 if (IsFPConstrained)
1486 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
1487 L, R, nullptr, Name, FPMD);
1488
1489 if (Value *V = Folder.FoldBinOpFMF(Instruction::FSub, L, R, FMF))
1490 return V;
1491 Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
1492 return Insert(I, Name);
1493 }
1494
1495 /// Copy fast-math-flags from an instruction rather than using the builder's
1496 /// default FMF.
1497 Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource,
1498 const Twine &Name = "") {
1499 if (IsFPConstrained)
1500 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
1501 L, R, FMFSource, Name);
1502
1503 FastMathFlags FMF = FMFSource->getFastMathFlags();
1504 if (Value *V = Folder.FoldBinOpFMF(Instruction::FSub, L, R, FMF))
1505 return V;
1506 Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, FMF);
1507 return Insert(I, Name);
1508 }
1509
1510 Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
1511 MDNode *FPMD = nullptr) {
1512 if (IsFPConstrained)
1513 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
1514 L, R, nullptr, Name, FPMD);
1515
1516 if (Value *V = Folder.FoldBinOpFMF(Instruction::FMul, L, R, FMF))
1517 return V;
1518 Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
1519 return Insert(I, Name);
1520 }
1521
1522 /// Copy fast-math-flags from an instruction rather than using the builder's
1523 /// default FMF.
1524 Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource,
1525 const Twine &Name = "") {
1526 if (IsFPConstrained)
1527 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
1528 L, R, FMFSource, Name);
1529
1530 FastMathFlags FMF = FMFSource->getFastMathFlags();
1531 if (Value *V = Folder.FoldBinOpFMF(Instruction::FMul, L, R, FMF))
1532 return V;
1533 Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, FMF);
1534 return Insert(I, Name);
1535 }
1536
1537 Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
1538 MDNode *FPMD = nullptr) {
1539 if (IsFPConstrained)
1540 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
1541 L, R, nullptr, Name, FPMD);
1542
1543 if (Value *V = Folder.FoldBinOpFMF(Instruction::FDiv, L, R, FMF))
1544 return V;
1545 Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
1546 return Insert(I, Name);
1547 }
1548
1549 /// Copy fast-math-flags from an instruction rather than using the builder's
1550 /// default FMF.
1551 Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource,
1552 const Twine &Name = "") {
1553 if (IsFPConstrained)
1554 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
1555 L, R, FMFSource, Name);
1556
1557 FastMathFlags FMF = FMFSource->getFastMathFlags();
1558 if (Value *V = Folder.FoldBinOpFMF(Instruction::FDiv, L, R, FMF))
1559 return V;
1560 Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, FMF);
1561 return Insert(I, Name);
1562 }
1563
1564 Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
1565 MDNode *FPMD = nullptr) {
1566 if (IsFPConstrained)
1567 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
1568 L, R, nullptr, Name, FPMD);
1569
1570 if (Value *V = Folder.FoldBinOpFMF(Instruction::FRem, L, R, FMF)) return V;
1571 Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
1572 return Insert(I, Name);
1573 }
1574
1575 /// Copy fast-math-flags from an instruction rather than using the builder's
1576 /// default FMF.
1577 Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource,
1578 const Twine &Name = "") {
1579 if (IsFPConstrained)
1580 return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
1581 L, R, FMFSource, Name);
1582
1583 FastMathFlags FMF = FMFSource->getFastMathFlags();
1584 if (Value *V = Folder.FoldBinOpFMF(Instruction::FRem, L, R, FMF)) return V;
1585 Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, FMF);
1586 return Insert(I, Name);
1587 }
1588
1589 Value *CreateBinOp(Instruction::BinaryOps Opc,
1590 Value *LHS, Value *RHS, const Twine &Name = "",
1591 MDNode *FPMathTag = nullptr) {
1592 if (Value *V = Folder.FoldBinOp(Opc, LHS, RHS)) return V;
1593 Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS);
1594 if (isa<FPMathOperator>(BinOp))
1595 setFPAttrs(BinOp, FPMathTag, FMF);
1596 return Insert(BinOp, Name);
1597 }
1598
1599 Value *CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name = "") {
1600 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", 1600, __extension__ __PRETTY_FUNCTION__
))
;
1601 return CreateSelect(Cond1, Cond2,
1602 ConstantInt::getNullValue(Cond2->getType()), Name);
1603 }
1604
1605 Value *CreateLogicalOr(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, ConstantInt::getAllOnesValue(Cond2->getType()),
1608 Cond2, Name);
1609 }
1610
1611 Value *CreateLogicalOp(Instruction::BinaryOps Opc, Value *Cond1, Value *Cond2,
1612 const Twine &Name = "") {
1613 switch (Opc) {
1614 case Instruction::And:
1615 return CreateLogicalAnd(Cond1, Cond2, Name);
1616 case Instruction::Or:
1617 return CreateLogicalOr(Cond1, Cond2, Name);
1618 default:
1619 break;
1620 }
1621 llvm_unreachable("Not a logical operation.")::llvm::llvm_unreachable_internal("Not a logical operation.",
"llvm/include/llvm/IR/IRBuilder.h", 1621)
;
1622 }
1623
1624 // NOTE: this is sequential, non-commutative, ordered reduction!
1625 Value *CreateLogicalOr(ArrayRef<Value *> Ops) {
1626 assert(!Ops.empty())(static_cast <bool> (!Ops.empty()) ? void (0) : __assert_fail
("!Ops.empty()", "llvm/include/llvm/IR/IRBuilder.h", 1626, __extension__
__PRETTY_FUNCTION__))
;
1627 Value *Accum = Ops[0];
1628 for (unsigned i = 1; i < Ops.size(); i++)
1629 Accum = CreateLogicalOr(Accum, Ops[i]);
1630 return Accum;
1631 }
1632
1633 CallInst *CreateConstrainedFPBinOp(
1634 Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr,
1635 const Twine &Name = "", MDNode *FPMathTag = nullptr,
1636 std::optional<RoundingMode> Rounding = std::nullopt,
1637 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
1638
1639 Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNUW = false,
1640 bool HasNSW = false) {
1641 return CreateSub(Constant::getNullValue(V->getType()), V, Name, HasNUW,
1642 HasNSW);
1643 }
1644
1645 Value *CreateNSWNeg(Value *V, const Twine &Name = "") {
1646 return CreateNeg(V, Name, false, true);
1647 }
1648
1649 Value *CreateNUWNeg(Value *V, const Twine &Name = "") {
1650 return CreateNeg(V, Name, true, false);
1651 }
1652
1653 Value *CreateFNeg(Value *V, const Twine &Name = "",
1654 MDNode *FPMathTag = nullptr) {
1655 if (Value *Res = Folder.FoldUnOpFMF(Instruction::FNeg, V, FMF))
1656 return Res;
1657 return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), FPMathTag, FMF),
1658 Name);
1659 }
1660
1661 /// Copy fast-math-flags from an instruction rather than using the builder's
1662 /// default FMF.
1663 Value *CreateFNegFMF(Value *V, Instruction *FMFSource,
1664 const Twine &Name = "") {
1665 FastMathFlags FMF = FMFSource->getFastMathFlags();
1666 if (Value *Res = Folder.FoldUnOpFMF(Instruction::FNeg, V, FMF))
1667 return Res;
1668 return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V), nullptr, FMF),
1669 Name);
1670 }
1671
1672 Value *CreateNot(Value *V, const Twine &Name = "") {
1673 return CreateXor(V, Constant::getAllOnesValue(V->getType()), Name);
1674 }
1675
1676 Value *CreateUnOp(Instruction::UnaryOps Opc,
1677 Value *V, const Twine &Name = "",
1678 MDNode *FPMathTag = nullptr) {
1679 if (Value *Res = Folder.FoldUnOpFMF(Opc, V, FMF))
1680 return Res;
1681 Instruction *UnOp = UnaryOperator::Create(Opc, V);
1682 if (isa<FPMathOperator>(UnOp))
1683 setFPAttrs(UnOp, FPMathTag, FMF);
1684 return Insert(UnOp, Name);
1685 }
1686
1687 /// Create either a UnaryOperator or BinaryOperator depending on \p Opc.
1688 /// Correct number of operands must be passed accordingly.
1689 Value *CreateNAryOp(unsigned Opc, ArrayRef<Value *> Ops,
1690 const Twine &Name = "", MDNode *FPMathTag = nullptr);
1691
1692 //===--------------------------------------------------------------------===//
1693 // Instruction creation methods: Memory Instructions
1694 //===--------------------------------------------------------------------===//
1695
1696 AllocaInst *CreateAlloca(Type *Ty, unsigned AddrSpace,
1697 Value *ArraySize = nullptr, const Twine &Name = "") {
1698 const DataLayout &DL = BB->getModule()->getDataLayout();
1699 Align AllocaAlign = DL.getPrefTypeAlign(Ty);
1700 return Insert(new AllocaInst(Ty, AddrSpace, ArraySize, AllocaAlign), Name);
1701 }
1702
1703 AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr,
1704 const Twine &Name = "") {
1705 const DataLayout &DL = BB->getModule()->getDataLayout();
1706 Align AllocaAlign = DL.getPrefTypeAlign(Ty);
1707 unsigned AddrSpace = DL.getAllocaAddrSpace();
1708 return Insert(new AllocaInst(Ty, AddrSpace, ArraySize, AllocaAlign), Name);
1709 }
1710
1711 /// Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of
1712 /// converting the string to 'bool' for the isVolatile parameter.
1713 LoadInst *CreateLoad(Type *Ty, Value *Ptr, const char *Name) {
1714 return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), Name);
1715 }
1716
1717 LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") {
1718 return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), Name);
1719 }
1720
1721 LoadInst *CreateLoad(Type *Ty, Value *Ptr, bool isVolatile,
1722 const Twine &Name = "") {
1723 return CreateAlignedLoad(Ty, Ptr, MaybeAlign(), isVolatile, Name);
1724 }
1725
1726 StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) {
1727 return CreateAlignedStore(Val, Ptr, MaybeAlign(), isVolatile);
1728 }
1729
1730 LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align,
1731 const char *Name) {
1732 return CreateAlignedLoad(Ty, Ptr, Align, /*isVolatile*/false, Name);
1733 }
1734
1735 LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align,
1736 const Twine &Name = "") {
1737 return CreateAlignedLoad(Ty, Ptr, Align, /*isVolatile*/false, Name);
1738 }
1739
1740 LoadInst *CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align,
1741 bool isVolatile, const Twine &Name = "") {
1742 if (!Align) {
1743 const DataLayout &DL = BB->getModule()->getDataLayout();
1744 Align = DL.getABITypeAlign(Ty);
1745 }
1746 return Insert(new LoadInst(Ty, Ptr, Twine(), isVolatile, *Align), Name);
1747 }
1748
1749 StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align,
1750 bool isVolatile = false) {
1751 if (!Align) {
1752 const DataLayout &DL = BB->getModule()->getDataLayout();
1753 Align = DL.getABITypeAlign(Val->getType());
1754 }
1755 return Insert(new StoreInst(Val, Ptr, isVolatile, *Align));
1756 }
1757 FenceInst *CreateFence(AtomicOrdering Ordering,
1758 SyncScope::ID SSID = SyncScope::System,
1759 const Twine &Name = "") {
1760 return Insert(new FenceInst(Context, Ordering, SSID), Name);
1761 }
1762
1763 AtomicCmpXchgInst *
1764 CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
1765 AtomicOrdering SuccessOrdering,
1766 AtomicOrdering FailureOrdering,
1767 SyncScope::ID SSID = SyncScope::System) {
1768 if (!Align) {
1769 const DataLayout &DL = BB->getModule()->getDataLayout();
1770 Align = llvm::Align(DL.getTypeStoreSize(New->getType()));
1771 }
1772
1773 return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, *Align, SuccessOrdering,
1774 FailureOrdering, SSID));
1775 }
1776
1777 AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr,
1778 Value *Val, MaybeAlign Align,
1779 AtomicOrdering Ordering,
1780 SyncScope::ID SSID = SyncScope::System) {
1781 if (!Align) {
1782 const DataLayout &DL = BB->getModule()->getDataLayout();
1783 Align = llvm::Align(DL.getTypeStoreSize(Val->getType()));
1784 }
1785
1786 return Insert(new AtomicRMWInst(Op, Ptr, Val, *Align, Ordering, SSID));
1787 }
1788
1789 Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
1790 const Twine &Name = "", bool IsInBounds = false) {
1791 if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, IsInBounds))
1792 return V;
1793 return Insert(IsInBounds
1794 ? GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList)
1795 : GetElementPtrInst::Create(Ty, Ptr, IdxList),
1796 Name);
1797 }
1798
1799 Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
1800 const Twine &Name = "") {
1801 return CreateGEP(Ty, Ptr, IdxList, Name, /* IsInBounds */ true);
1802 }
1803
1804 Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
1805 const Twine &Name = "") {
1806 Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
1807
1808 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/false))
1809 return V;
1810
1811 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
1812 }
1813
1814 Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,
1815 const Twine &Name = "") {
1816 Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0);
1817
1818 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/true))
1819 return V;
1820
1821 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
1822 }
1823
1824 Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1,
1825 const Twine &Name = "") {
1826 Value *Idxs[] = {
1827 ConstantInt::get(Type::getInt32Ty(Context), Idx0),
1828 ConstantInt::get(Type::getInt32Ty(Context), Idx1)
1829 };
1830
1831 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/false))
1832 return V;
1833
1834 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name);
1835 }
1836
1837 Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0,
1838 unsigned Idx1, const Twine &Name = "") {
1839 Value *Idxs[] = {
1840 ConstantInt::get(Type::getInt32Ty(Context), Idx0),
1841 ConstantInt::get(Type::getInt32Ty(Context), Idx1)
1842 };
1843
1844 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/true))
1845 return V;
1846
1847 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name);
1848 }
1849
1850 Value *CreateConstGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0,
1851 const Twine &Name = "") {
1852 Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
1853
1854 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/false))
1855 return V;
1856
1857 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name);
1858 }
1859
1860 Value *CreateConstInBoundsGEP1_64(Type *Ty, Value *Ptr, uint64_t Idx0,
1861 const Twine &Name = "") {
1862 Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0);
1863
1864 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idx, /*IsInBounds=*/true))
1865 return V;
1866
1867 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name);
1868 }
1869
1870 Value *CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1,
1871 const Twine &Name = "") {
1872 Value *Idxs[] = {
1873 ConstantInt::get(Type::getInt64Ty(Context), Idx0),
1874 ConstantInt::get(Type::getInt64Ty(Context), Idx1)
1875 };
1876
1877 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/false))
1878 return V;
1879
1880 return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name);
1881 }
1882
1883 Value *CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0,
1884 uint64_t Idx1, const Twine &Name = "") {
1885 Value *Idxs[] = {
1886 ConstantInt::get(Type::getInt64Ty(Context), Idx0),
1887 ConstantInt::get(Type::getInt64Ty(Context), Idx1)
1888 };
1889
1890 if (auto *V = Folder.FoldGEP(Ty, Ptr, Idxs, /*IsInBounds=*/true))
1891 return V;
1892
1893 return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name);
1894 }
1895
1896 Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx,
1897 const Twine &Name = "") {
1898 return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name);
1899 }
1900
1901 /// Same as CreateGlobalString, but return a pointer with "i8*" type
1902 /// instead of a pointer to array of i8.
1903 ///
1904 /// If no module is given via \p M, it is take from the insertion point basic
1905 /// block.
1906 Constant *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "",
1907 unsigned AddressSpace = 0,
1908 Module *M = nullptr) {
1909 GlobalVariable *GV = CreateGlobalString(Str, Name, AddressSpace, M);
1910 Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0);
1911 Constant *Indices[] = {Zero, Zero};
1912 return ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV,
1913 Indices);
1914 }
1915
1916 //===--------------------------------------------------------------------===//
1917 // Instruction creation methods: Cast/Conversion Operators
1918 //===--------------------------------------------------------------------===//
1919
1920 Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") {
1921 return CreateCast(Instruction::Trunc, V, DestTy, Name);
1922 }
1923
1924 Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") {
1925 return CreateCast(Instruction::ZExt, V, DestTy, Name);
1926 }
1927
1928 Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") {
1929 return CreateCast(Instruction::SExt, V, DestTy, Name);
1930 }
1931
1932 /// Create a ZExt or Trunc from the integer value V to DestTy. Return
1933 /// the value untouched if the type of V is already DestTy.
1934 Value *CreateZExtOrTrunc(Value *V, Type *DestTy,
1935 const Twine &Name = "") {
1936 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", 1938, __extension__ __PRETTY_FUNCTION__
))
1937 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", 1938, __extension__ __PRETTY_FUNCTION__
))
1938 "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", 1938, __extension__ __PRETTY_FUNCTION__
))
;
1939 Type *VTy = V->getType();
1940 if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits())
1941 return CreateZExt(V, DestTy, Name);
1942 if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits())
1943 return CreateTrunc(V, DestTy, Name);
1944 return V;
1945 }
1946
1947 /// Create a SExt or Trunc from the integer value V to DestTy. Return
1948 /// the value untouched if the type of V is already DestTy.
1949 Value *CreateSExtOrTrunc(Value *V, Type *DestTy,
1950 const Twine &Name = "") {
1951 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", 1953, __extension__ __PRETTY_FUNCTION__
))
1952 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", 1953, __extension__ __PRETTY_FUNCTION__
))
1953 "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", 1953, __extension__ __PRETTY_FUNCTION__
))
;
1954 Type *VTy = V->getType();
1955 if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits())
1956 return CreateSExt(V, DestTy, Name);
1957 if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits())
1958 return CreateTrunc(V, DestTy, Name);
1959 return V;
1960 }
1961
1962 Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = "") {
1963 if (IsFPConstrained)
1964 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fptoui,
1965 V, DestTy, nullptr, Name);
1966 return CreateCast(Instruction::FPToUI, V, DestTy, Name);
1967 }
1968
1969 Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = "") {
1970 if (IsFPConstrained)
1971 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fptosi,
1972 V, DestTy, nullptr, Name);
1973 return CreateCast(Instruction::FPToSI, V, DestTy, Name);
1974 }
1975
1976 Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
1977 if (IsFPConstrained)
1978 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_uitofp,
1979 V, DestTy, nullptr, Name);
1980 return CreateCast(Instruction::UIToFP, V, DestTy, Name);
1981 }
1982
1983 Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
1984 if (IsFPConstrained)
1985 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_sitofp,
1986 V, DestTy, nullptr, Name);
1987 return CreateCast(Instruction::SIToFP, V, DestTy, Name);
1988 }
1989
1990 Value *CreateFPTrunc(Value *V, Type *DestTy,
1991 const Twine &Name = "") {
1992 if (IsFPConstrained)
1993 return CreateConstrainedFPCast(
1994 Intrinsic::experimental_constrained_fptrunc, V, DestTy, nullptr,
1995 Name);
1996 return CreateCast(Instruction::FPTrunc, V, DestTy, Name);
1997 }
1998
1999 Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") {
2000 if (IsFPConstrained)
2001 return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fpext,
2002 V, DestTy, nullptr, Name);
2003 return CreateCast(Instruction::FPExt, V, DestTy, Name);
2004 }
2005
2006 Value *CreatePtrToInt(Value *V, Type *DestTy,
2007 const Twine &Name = "") {
2008 return CreateCast(Instruction::PtrToInt, V, DestTy, Name);
2009 }
2010
2011 Value *CreateIntToPtr(Value *V, Type *DestTy,
2012 const Twine &Name = "") {
2013 return CreateCast(Instruction::IntToPtr, V, DestTy, Name);
2014 }
2015
2016 Value *CreateBitCast(Value *V, Type *DestTy,
2017 const Twine &Name = "") {
2018 return CreateCast(Instruction::BitCast, V, DestTy, Name);
2019 }
2020
2021 Value *CreateAddrSpaceCast(Value *V, Type *DestTy,
2022 const Twine &Name = "") {
2023 return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name);
2024 }
2025
2026 Value *CreateZExtOrBitCast(Value *V, Type *DestTy,
2027 const Twine &Name = "") {
2028 if (V->getType() == DestTy)
2029 return V;
2030 if (auto *VC = dyn_cast<Constant>(V))
2031 return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name);
2032 return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name);
2033 }
2034
2035 Value *CreateSExtOrBitCast(Value *V, Type *DestTy,
2036 const Twine &Name = "") {
2037 if (V->getType() == DestTy)
2038 return V;
2039 if (auto *VC = dyn_cast<Constant>(V))
2040 return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name);
2041 return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name);
2042 }
2043
2044 Value *CreateTruncOrBitCast(Value *V, Type *DestTy,
2045 const Twine &Name = "") {
2046 if (V->getType() == DestTy)
2047 return V;
2048 if (auto *VC = dyn_cast<Constant>(V))
2049 return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name);
2050 return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name);
2051 }
2052
2053 Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
2054 const Twine &Name = "") {
2055 if (V->getType() == DestTy)
2056 return V;
2057 if (auto *VC = dyn_cast<Constant>(V))
2058 return Insert(Folder.CreateCast(Op, VC, DestTy), Name);
2059 return Insert(CastInst::Create(Op, V, DestTy), Name);
2060 }
2061
2062 Value *CreatePointerCast(Value *V, Type *DestTy,
2063 const Twine &Name = "") {
2064 if (V->getType() == DestTy)
2065 return V;
2066 if (auto *VC = dyn_cast<Constant>(V))
2067 return Insert(Folder.CreatePointerCast(VC, DestTy), Name);
2068 return Insert(CastInst::CreatePointerCast(V, DestTy), Name);
2069 }
2070
2071 Value *CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy,
2072 const Twine &Name = "") {
2073 if (V->getType() == DestTy)
2074 return V;
2075
2076 if (auto *VC = dyn_cast<Constant>(V)) {
2077 return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy),
2078 Name);
2079 }
2080
2081 return Insert(CastInst::CreatePointerBitCastOrAddrSpaceCast(V, DestTy),
2082 Name);
2083 }
2084
2085 Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned,
2086 const Twine &Name = "") {
2087 if (V->getType() == DestTy)
2088 return V;
2089 if (auto *VC = dyn_cast<Constant>(V))
2090 return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name);
2091 return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name);
2092 }
2093
2094 Value *CreateBitOrPointerCast(Value *V, Type *DestTy,
2095 const Twine &Name = "") {
2096 if (V->getType() == DestTy)
2097 return V;
2098 if (V->getType()->isPtrOrPtrVectorTy() && DestTy->isIntOrIntVectorTy())
2099 return CreatePtrToInt(V, DestTy, Name);
2100 if (V->getType()->isIntOrIntVectorTy() && DestTy->isPtrOrPtrVectorTy())
2101 return CreateIntToPtr(V, DestTy, Name);
2102
2103 return CreateBitCast(V, DestTy, Name);
2104 }
2105
2106 Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") {
2107 if (V->getType() == DestTy)
2108 return V;
2109 if (auto *VC = dyn_cast<Constant>(V))
2110 return Insert(Folder.CreateFPCast(VC, DestTy), Name);
2111 return Insert(CastInst::CreateFPCast(V, DestTy), Name);
2112 }
2113
2114 CallInst *CreateConstrainedFPCast(
2115 Intrinsic::ID ID, Value *V, Type *DestTy,
2116 Instruction *FMFSource = nullptr, const Twine &Name = "",
2117 MDNode *FPMathTag = nullptr,
2118 std::optional<RoundingMode> Rounding = std::nullopt,
2119 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2120
2121 // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
2122 // compile time error, instead of converting the string to bool for the
2123 // isSigned parameter.
2124 Value *CreateIntCast(Value *, Type *, const char *) = delete;
2125
2126 //===--------------------------------------------------------------------===//
2127 // Instruction creation methods: Compare Instructions
2128 //===--------------------------------------------------------------------===//
2129
2130 Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") {
2131 return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name);
2132 }
2133
2134 Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") {
2135 return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name);
2136 }
2137
2138 Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") {
2139 return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name);
2140 }
2141
2142 Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") {
2143 return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name);
2144 }
2145
2146 Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") {
2147 return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name);
2148 }
2149
2150 Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") {
2151 return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name);
2152 }
2153
2154 Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") {
2155 return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name);
2156 }
2157
2158 Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") {
2159 return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name);
2160 }
2161
2162 Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") {
2163 return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name);
2164 }
2165
2166 Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") {
2167 return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name);
2168 }
2169
2170 Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "",
2171 MDNode *FPMathTag = nullptr) {
2172 return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag);
2173 }
2174
2175 Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "",
2176 MDNode *FPMathTag = nullptr) {
2177 return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag);
2178 }
2179
2180 Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "",
2181 MDNode *FPMathTag = nullptr) {
2182 return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag);
2183 }
2184
2185 Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "",
2186 MDNode *FPMathTag = nullptr) {
2187 return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag);
2188 }
2189
2190 Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "",
2191 MDNode *FPMathTag = nullptr) {
2192 return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag);
2193 }
2194
2195 Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "",
2196 MDNode *FPMathTag = nullptr) {
2197 return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag);
2198 }
2199
2200 Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "",
2201 MDNode *FPMathTag = nullptr) {
2202 return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag);
2203 }
2204
2205 Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "",
2206 MDNode *FPMathTag = nullptr) {
2207 return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag);
2208 }
2209
2210 Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "",
2211 MDNode *FPMathTag = nullptr) {
2212 return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag);
2213 }
2214
2215 Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "",
2216 MDNode *FPMathTag = nullptr) {
2217 return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag);
2218 }
2219
2220 Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "",
2221 MDNode *FPMathTag = nullptr) {
2222 return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag);
2223 }
2224
2225 Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "",
2226 MDNode *FPMathTag = nullptr) {
2227 return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag);
2228 }
2229
2230 Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "",
2231 MDNode *FPMathTag = nullptr) {
2232 return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag);
2233 }
2234
2235 Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "",
2236 MDNode *FPMathTag = nullptr) {
2237 return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag);
2238 }
2239
2240 Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
2241 const Twine &Name = "") {
2242 if (auto *V = Folder.FoldICmp(P, LHS, RHS))
2243 return V;
2244 return Insert(new ICmpInst(P, LHS, RHS), Name);
2245 }
2246
2247 // Create a quiet floating-point comparison (i.e. one that raises an FP
2248 // exception only in the case where an input is a signaling NaN).
2249 // Note that this differs from CreateFCmpS only if IsFPConstrained is true.
2250 Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
2251 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2252 return CreateFCmpHelper(P, LHS, RHS, Name, FPMathTag, false);
2253 }
2254
2255 Value *CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
2256 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2257 return CmpInst::isFPPredicate(Pred)
2258 ? CreateFCmp(Pred, LHS, RHS, Name, FPMathTag)
2259 : CreateICmp(Pred, LHS, RHS, Name);
2260 }
2261
2262 // Create a signaling floating-point comparison (i.e. one that raises an FP
2263 // exception whenever an input is any NaN, signaling or quiet).
2264 // Note that this differs from CreateFCmp only if IsFPConstrained is true.
2265 Value *CreateFCmpS(CmpInst::Predicate P, Value *LHS, Value *RHS,
2266 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2267 return CreateFCmpHelper(P, LHS, RHS, Name, FPMathTag, true);
2268 }
2269
2270private:
2271 // Helper routine to create either a signaling or a quiet FP comparison.
2272 Value *CreateFCmpHelper(CmpInst::Predicate P, Value *LHS, Value *RHS,
2273 const Twine &Name, MDNode *FPMathTag,
2274 bool IsSignaling);
2275
2276public:
2277 CallInst *CreateConstrainedFPCmp(
2278 Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R,
2279 const Twine &Name = "",
2280 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2281
2282 //===--------------------------------------------------------------------===//
2283 // Instruction creation methods: Other Instructions
2284 //===--------------------------------------------------------------------===//
2285
2286 PHINode *CreatePHI(Type *Ty, unsigned NumReservedValues,
2287 const Twine &Name = "") {
2288 PHINode *Phi = PHINode::Create(Ty, NumReservedValues);
2289 if (isa<FPMathOperator>(Phi))
2290 setFPAttrs(Phi, nullptr /* MDNode* */, FMF);
2291 return Insert(Phi, Name);
2292 }
2293
2294private:
2295 CallInst *createCallHelper(Function *Callee, ArrayRef<Value *> Ops,
2296 const Twine &Name = "",
2297 Instruction *FMFSource = nullptr,
2298 ArrayRef<OperandBundleDef> OpBundles = {});
2299
2300public:
2301 CallInst *CreateCall(FunctionType *FTy, Value *Callee,
2302 ArrayRef<Value *> Args = std::nullopt,
2303 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2304 CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
2305 if (IsFPConstrained)
2306 setConstrainedFPCallAttr(CI);
2307 if (isa<FPMathOperator>(CI))
2308 setFPAttrs(CI, FPMathTag, FMF);
2309 return Insert(CI, Name);
2310 }
2311
2312 CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value *> Args,
2313 ArrayRef<OperandBundleDef> OpBundles,
2314 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2315 CallInst *CI = CallInst::Create(FTy, Callee, Args, OpBundles);
2316 if (IsFPConstrained)
2317 setConstrainedFPCallAttr(CI);
2318 if (isa<FPMathOperator>(CI))
2319 setFPAttrs(CI, FPMathTag, FMF);
2320 return Insert(CI, Name);
2321 }
2322
2323 CallInst *CreateCall(FunctionCallee Callee,
2324 ArrayRef<Value *> Args = std::nullopt,
2325 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2326 return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
2327 FPMathTag);
2328 }
2329
2330 CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
2331 ArrayRef<OperandBundleDef> OpBundles,
2332 const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2333 return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args,
2334 OpBundles, Name, FPMathTag);
2335 }
2336
2337 CallInst *CreateConstrainedFPCall(
2338 Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
2339 std::optional<RoundingMode> Rounding = std::nullopt,
2340 std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2341
2342 Value *CreateSelect(Value *C, Value *True, Value *False,
2343 const Twine &Name = "", Instruction *MDFrom = nullptr);
2344
2345 VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") {
2346 return Insert(new VAArgInst(List, Ty), Name);
2347 }
2348
2349 Value *CreateExtractElement(Value *Vec, Value *Idx,
2350 const Twine &Name = "") {
2351 if (Value *V = Folder.FoldExtractElement(Vec, Idx))
2352 return V;
2353 return Insert(ExtractElementInst::Create(Vec, Idx), Name);
2354 }
2355
2356 Value *CreateExtractElement(Value *Vec, uint64_t Idx,
2357 const Twine &Name = "") {
2358 return CreateExtractElement(Vec, getInt64(Idx), Name);
2359 }
2360
2361 Value *CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx,
2362 const Twine &Name = "") {
2363 return CreateInsertElement(PoisonValue::get(VecTy), NewElt, Idx, Name);
2364 }
2365
2366 Value *CreateInsertElement(Type *VecTy, Value *NewElt, uint64_t Idx,
2367 const Twine &Name = "") {
2368 return CreateInsertElement(PoisonValue::get(VecTy), NewElt, Idx, Name);
2369 }
2370
2371 Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx,
2372 const Twine &Name = "") {
2373 if (Value *V = Folder.FoldInsertElement(Vec, NewElt, Idx))
2374 return V;
2375 return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name);
2376 }
2377
2378 Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx,
2379 const Twine &Name = "") {
2380 return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name);
2381 }
2382
2383 Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask,
2384 const Twine &Name = "") {
2385 SmallVector<int, 16> IntMask;
2386 ShuffleVectorInst::getShuffleMask(cast<Constant>(Mask), IntMask);
2387 return CreateShuffleVector(V1, V2, IntMask, Name);
2388 }
2389
2390 /// See class ShuffleVectorInst for a description of the mask representation.
2391 Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> Mask,
2392 const Twine &Name = "") {
2393 if (Value *V = Folder.FoldShuffleVector(V1, V2, Mask))
2394 return V;
2395 return Insert(new ShuffleVectorInst(V1, V2, Mask), Name);
2396 }
2397
2398 /// Create a unary shuffle. The second vector operand of the IR instruction
2399 /// is poison.
2400 Value *CreateShuffleVector(Value *V, ArrayRef<int> Mask,
2401 const Twine &Name = "") {
2402 return CreateShuffleVector(V, PoisonValue::get(V->getType()), Mask, Name);
2403 }
2404
2405 Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs,
2406 const Twine &Name = "") {
2407 if (auto *V = Folder.FoldExtractValue(Agg, Idxs))
2408 return V;
2409 return Insert(ExtractValueInst::Create(Agg, Idxs), Name);
2410 }
2411
2412 Value *CreateInsertValue(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
2413 const Twine &Name = "") {
2414 if (auto *V = Folder.FoldInsertValue(Agg, Val, Idxs))
2415 return V;
2416 return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name);
2417 }
2418
2419 LandingPadInst *CreateLandingPad(Type *Ty, unsigned NumClauses,
2420 const Twine &Name = "") {
2421 return Insert(LandingPadInst::Create(Ty, NumClauses), Name);
2422 }
2423
2424 Value *CreateFreeze(Value *V, const Twine &Name = "") {
2425 return Insert(new FreezeInst(V), Name);
2426 }
2427
2428 //===--------------------------------------------------------------------===//
2429 // Utility creation methods
2430 //===--------------------------------------------------------------------===//
2431
2432 /// Return a boolean value testing if \p Arg == 0.
2433 Value *CreateIsNull(Value *Arg, const Twine &Name = "") {
2434 return CreateICmpEQ(Arg, ConstantInt::getNullValue(Arg->getType()), Name);
2435 }
2436
2437 /// Return a boolean value testing if \p Arg != 0.
2438 Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") {
2439 return CreateICmpNE(Arg, ConstantInt::getNullValue(Arg->getType()), Name);
2440 }
2441
2442 /// Return a boolean value testing if \p Arg < 0.
2443 Value *CreateIsNeg(Value *Arg, const Twine &Name = "") {
2444 return CreateICmpSLT(Arg, ConstantInt::getNullValue(Arg->getType()), Name);
2445 }
2446
2447 /// Return a boolean value testing if \p Arg > -1.
2448 Value *CreateIsNotNeg(Value *Arg, const Twine &Name = "") {
2449 return CreateICmpSGT(Arg, ConstantInt::getAllOnesValue(Arg->getType()),
2450 Name);
2451 }
2452
2453 /// Return the i64 difference between two pointer values, dividing out
2454 /// the size of the pointed-to objects.
2455 ///
2456 /// This is intended to implement C-style pointer subtraction. As such, the
2457 /// pointers must be appropriately aligned for their element types and
2458 /// pointing into the same object.
2459 Value *CreatePtrDiff(Type *ElemTy, Value *LHS, Value *RHS,
2460 const Twine &Name = "");
2461
2462 /// Create a launder.invariant.group intrinsic call. If Ptr type is
2463 /// different from pointer to i8, it's casted to pointer to i8 in the same
2464 /// address space before call and casted back to Ptr type after call.
2465 Value *CreateLaunderInvariantGroup(Value *Ptr);
2466
2467 /// \brief Create a strip.invariant.group intrinsic call. If Ptr type is
2468 /// different from pointer to i8, it's casted to pointer to i8 in the same
2469 /// address space before call and casted back to Ptr type after call.
2470 Value *CreateStripInvariantGroup(Value *Ptr);
2471
2472 /// Return a vector value that contains the vector V reversed
2473 Value *CreateVectorReverse(Value *V, const Twine &Name = "");
2474
2475 /// Return a vector splice intrinsic if using scalable vectors, otherwise
2476 /// return a shufflevector. If the immediate is positive, a vector is
2477 /// extracted from concat(V1, V2), starting at Imm. If the immediate
2478 /// is negative, we extract -Imm elements from V1 and the remaining
2479 /// elements from V2. Imm is a signed integer in the range
2480 /// -VL <= Imm < VL (where VL is the runtime vector length of the
2481 /// source/result vector)
2482 Value *CreateVectorSplice(Value *V1, Value *V2, int64_t Imm,
2483 const Twine &Name = "");
2484
2485 /// Return a vector value that contains \arg V broadcasted to \p
2486 /// NumElts elements.
2487 Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "");
2488
2489 /// Return a vector value that contains \arg V broadcasted to \p
2490 /// EC elements.
2491 Value *CreateVectorSplat(ElementCount EC, Value *V, const Twine &Name = "");
2492
2493 /// Return a value that has been extracted from a larger integer type.
2494 Value *CreateExtractInteger(const DataLayout &DL, Value *From,
2495 IntegerType *ExtractedTy, uint64_t Offset,
2496 const Twine &Name);
2497
2498 Value *CreatePreserveArrayAccessIndex(Type *ElTy, Value *Base,
2499 unsigned Dimension, unsigned LastIndex,
2500 MDNode *DbgInfo);
2501
2502 Value *CreatePreserveUnionAccessIndex(Value *Base, unsigned FieldIndex,
2503 MDNode *DbgInfo);
2504
2505 Value *CreatePreserveStructAccessIndex(Type *ElTy, Value *Base,
2506 unsigned Index, unsigned FieldIndex,
2507 MDNode *DbgInfo);
2508
2509private:
2510 /// Helper function that creates an assume intrinsic call that
2511 /// represents an alignment assumption on the provided pointer \p PtrValue
2512 /// with offset \p OffsetValue and alignment value \p AlignValue.
2513 CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL,
2514 Value *PtrValue, Value *AlignValue,
2515 Value *OffsetValue);
2516
2517public:
2518 /// Create an assume intrinsic call that represents an alignment
2519 /// assumption on the provided pointer.
2520 ///
2521 /// An optional offset can be provided, and if it is provided, the offset
2522 /// must be subtracted from the provided pointer to get the pointer with the
2523 /// specified alignment.
2524 CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
2525 unsigned Alignment,
2526 Value *OffsetValue = nullptr);
2527
2528 /// Create an assume intrinsic call that represents an alignment
2529 /// assumption on the provided pointer.
2530 ///
2531 /// An optional offset can be provided, and if it is provided, the offset
2532 /// must be subtracted from the provided pointer to get the pointer with the
2533 /// specified alignment.
2534 ///
2535 /// This overload handles the condition where the Alignment is dependent
2536 /// on an existing value rather than a static value.
2537 CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
2538 Value *Alignment,
2539 Value *OffsetValue = nullptr);
2540};
2541
2542/// This provides a uniform API for creating instructions and inserting
2543/// them into a basic block: either at the end of a BasicBlock, or at a specific
2544/// iterator location in a block.
2545///
2546/// Note that the builder does not expose the full generality of LLVM
2547/// instructions. For access to extra instruction properties, use the mutators
2548/// (e.g. setVolatile) on the instructions after they have been
2549/// created. Convenience state exists to specify fast-math flags and fp-math
2550/// tags.
2551///
2552/// The first template argument specifies a class to use for creating constants.
2553/// This defaults to creating minimally folded constants. The second template
2554/// argument allows clients to specify custom insertion hooks that are called on
2555/// every newly created insertion.
2556template <typename FolderTy = ConstantFolder,
2557 typename InserterTy = IRBuilderDefaultInserter>
2558class IRBuilder : public IRBuilderBase {
2559private:
2560 FolderTy Folder;
2561 InserterTy Inserter;
2562
2563public:
2564 IRBuilder(LLVMContext &C, FolderTy Folder, InserterTy Inserter = InserterTy(),
2565 MDNode *FPMathTag = nullptr,
2566 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2567 : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles),
2568 Folder(Folder), Inserter(Inserter) {}
2569
2570 explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr,
2571 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2572 : IRBuilderBase(C, this->Folder, this->Inserter, FPMathTag, OpBundles) {}
2573
2574 explicit IRBuilder(BasicBlock *TheBB, FolderTy Folder,
2575 MDNode *FPMathTag = nullptr,
2576 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2577 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2578 FPMathTag, OpBundles),
2579 Folder(Folder) {
2580 SetInsertPoint(TheBB);
2581 }
2582
2583 explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr,
2584 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2585 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2586 FPMathTag, OpBundles) {
2587 SetInsertPoint(TheBB);
2588 }
2589
2590 explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr,
2591 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2592 : IRBuilderBase(IP->getContext(), this->Folder, this->Inserter, FPMathTag,
2593 OpBundles) {
2594 SetInsertPoint(IP);
2595 }
2596
2597 IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, FolderTy Folder,
2598 MDNode *FPMathTag = nullptr,
2599 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2600 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2601 FPMathTag, OpBundles),
2602 Folder(Folder) {
2603 SetInsertPoint(TheBB, IP);
2604 }
2605
2606 IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
2607 MDNode *FPMathTag = nullptr,
2608 ArrayRef<OperandBundleDef> OpBundles = std::nullopt)
2609 : IRBuilderBase(TheBB->getContext(), this->Folder, this->Inserter,
2610 FPMathTag, OpBundles) {
2611 SetInsertPoint(TheBB, IP);
2612 }
2613
2614 /// Avoid copying the full IRBuilder. Prefer using InsertPointGuard
2615 /// or FastMathFlagGuard instead.
2616 IRBuilder(const IRBuilder &) = delete;
2617
2618 InserterTy &getInserter() { return Inserter; }
2619};
2620
2621template <typename FolderTy, typename InserterTy>
2622IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *,
2623 ArrayRef<OperandBundleDef>) -> IRBuilder<FolderTy, InserterTy>;
2624IRBuilder(LLVMContext &, MDNode *, ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2625template <typename FolderTy>
2626IRBuilder(BasicBlock *, FolderTy, MDNode *, ArrayRef<OperandBundleDef>)
2627 -> IRBuilder<FolderTy>;
2628IRBuilder(BasicBlock *, MDNode *, ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2629IRBuilder(Instruction *, MDNode *, ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2630template <typename FolderTy>
2631IRBuilder(BasicBlock *, BasicBlock::iterator, FolderTy, MDNode *,
2632 ArrayRef<OperandBundleDef>) -> IRBuilder<FolderTy>;
2633IRBuilder(BasicBlock *, BasicBlock::iterator, MDNode *,
2634 ArrayRef<OperandBundleDef>) -> IRBuilder<>;
2635
2636
2637// Create wrappers for C Binding types (see CBindingWrapping.h).
2638DEFINE_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)); }
2639
2640} // end namespace llvm
2641
2642#endif // LLVM_IR_IRBUILDER_H