Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86/X86PreAMXConfig.cpp
Warning:line 246, column 22
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name X86PreAMXConfig.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -D PIC -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -D_RET_PROTECTOR -ret-protector -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86/X86PreAMXConfig.cpp

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86/X86PreAMXConfig.cpp

1//===- Target/X86/X86PreAMXConfig.cpp - ------------------------*- 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/// Insert tilecfg for each area of key AMX intrinsic.
10/// All the key AMX intrinsic's tile operand must come from tileload. And the
11/// def tile of key AMX intrinsic must be tilestored.
12/// take tdpbssd for example:
13/// --------------------------------------------------------------------------
14/// %t1 = call x86_amx @llvm.x86.tileloadd64.internal(...) key
15/// %t2 = call x86_amx @llvm.x86.tileloadd64.internal(...) |
16/// %t3 = call x86_amx @llvm.x86.tileloadd64.internal(...) amx
17/// %td = tail call x86_amx @llvm.x86.tdpbssd.internal(t1, t2, t3) |
18/// call void @llvm.x86.tilestored64.internal(... td) area
19/// --------------------------------------------------------------------------
20/// This pass will insert tilecfg before every key-amx-area, some like:
21/// --------------------------------------------------------------------------
22/// %cfgmem = alloca <16 x i32>, align 4 * allocate mem
23/// store <16 x i32> zeroinitializer, <16 x i32>* %cfgmem * zero init
24/// ...
25/// ... pre-config shape of %t1 *
26/// store volatile i8 %m, i8* %amx.tmm.0.shape.row, align 1 *
27/// store volatile i16 %k, i16* %amx.tmm.0.shape.col, align 2 * pre-config
28/// ... *
29/// ... pre-config shape of %t2 * shapes
30/// store volatile i8 %k, i8* %amx.tmm.1.shape.row, align 1 *
31/// store volatile i16 %n, i16* %amx.tmm.1.shape.col, align 2 *
32/// ...
33/// call void @llvm.x86.ldtilecfg(i8* %cfgmem) * tile config
34//
35//===----------------------------------------------------------------------===//
36//
37#include "X86.h"
38#include "llvm/ADT/SmallSet.h"
39#include "llvm/Analysis/TargetTransformInfo.h"
40#include "llvm/CodeGen/Passes.h"
41#include "llvm/CodeGen/TargetPassConfig.h"
42#include "llvm/CodeGen/ValueTypes.h"
43#include "llvm/IR/DataLayout.h"
44#include "llvm/IR/Function.h"
45#include "llvm/IR/IRBuilder.h"
46#include "llvm/IR/Instructions.h"
47#include "llvm/IR/IntrinsicInst.h"
48#include "llvm/IR/IntrinsicsX86.h"
49#include "llvm/IR/PatternMatch.h"
50#include "llvm/InitializePasses.h"
51#include "llvm/Pass.h"
52#include "llvm/Support/raw_ostream.h"
53#include "llvm/Target/TargetMachine.h"
54
55using namespace llvm;
56using namespace PatternMatch;
57
58#define DEBUG_TYPE"pre-amx-config" "pre-amx-config"
59
60static bool isAMXIntrinsic(IntrinsicInst *II) {
61 for (Value *Operand : II->operands())
62 if (Operand->getType()->isX86_AMXTy())
63 return true;
64 return II->getType()->isX86_AMXTy();
65}
66
67static bool isTileLoad(IntrinsicInst *II) {
68 return II->getIntrinsicID() == Intrinsic::x86_tileloadd64_internal ||
69 II->getIntrinsicID() == Intrinsic::x86_tileloaddt164_internal;
70}
71
72static bool isTileStore(IntrinsicInst *II) {
73 return II->getIntrinsicID() == Intrinsic::x86_tilestored64_internal;
74}
75
76#ifndef NDEBUG1
77static bool onlyTileDef(IntrinsicInst *II) {
78 for (Value *Operand : II->operands())
79 if (Operand->getType()->isX86_AMXTy())
80 return false;
81 return II->getType()->isX86_AMXTy();
82}
83
84static bool brokenVolatile(Instruction *I) {
85 // Todo: it is weak to identify a normal call here.
86 if ((isa<CallInst>(I) && !isa<IntrinsicInst>(I)) || I->isTerminator())
87 return true;
88 return false;
89}
90#endif
91
92namespace {
93class X86PreAMXConfig {
94 Function &F;
95
96public:
97 X86PreAMXConfig(Function &Func) : F(Func) {}
98 bool preTileConfig();
99 bool addTileConfig(Instruction *ModelStart, SmallVector<Value *, 8> &Shapes);
100 bool findConfigShapes(
101 DenseMap<Instruction *, SmallVector<Value *, 8>> &PosAndShapes);
102 bool getKeyAMXShapes(IntrinsicInst *KeyAMX, SmallVector<Value *, 8> &Shapes);
103 bool preWriteTileCfg(Value *I8Ptr, Instruction *Pos,
104 SmallVector<Value *, 8> &Shapes);
105 BasicBlock::iterator
106 getShapesAndConfigPosEnd(BasicBlock::iterator Iter,
107 SmallVector<Value *, 8> &Shapes);
108 bool checkVolatileModel(SmallSet<Value *, 4> &Loads, IntrinsicInst *Store,
109 IntrinsicInst *KeyAMX);
110};
111
112// Orderly write the shapes in tilecfg's mem. This maybe not right.
113// Because the first shape may not corresponding to the first tmm register,
114// so we need to handle at at X86FastTileConfig::materializeTileCfg()
115// after register allocation.
116// For example:
117// --------------------------------------------------------------------------
118// zeroinitialize tilecfg's mem (of ldtilecfg)
119// --------------------------------------------------------------------------
120// ... pre-config shape of %t1 *
121// %amx.tmm.0.shape.row = getelementptr i8, i8* %mem, i64 48 *
122// %amx.tmm.0.shape.col = getelementptr i16, i16* %mem, i64 16 *
123// store volatile i8 %m, i8* %amx.tmm.0.shape.row, align 1 *
124// store volatile i16 %k, i16* %amx.tmm.0.shape.col, align 2 * pre-config
125// ... *
126// ... pre-config shape of %t2 *
127// %amx.tmm.1.shape.row = getelementptr i8, i8* %mem, i64 49 *
128// %amx.tmm.1.shape.col = getelementptr i16, i16* %mem, i64 18 *
129// store volatile i8 %k, i8* %amx.tmm.1.shape.row, align 1 * shapes
130// store volatile i16 %n, i16* %amx.tmm.1.shape.col, align 2 *
131// ... *
132// ... pre-config shape of %t3 * of
133// %amx.tmm.2.shape.row = getelementptr i8, i8* %mem, i64 50 *
134// %amx.tmm.2.shape.col = getelementptr i16, i16* %mem, i64 20 *
135// store volatile i8 %m, i8* %amx.tmm.2.shape.row, align 1 *
136// store volatile i16 %n, i16* %amx.tmm.2.shape.col, align 2 *
137// ... * tiles
138// ... pre-config shape of %td *
139// %amx.tmm.3.shape.row = getelementptr i8, i8* %mem, i64 51 *
140// %amx.tmm.3.shape.col = getelementptr i16, i16* %mem, i64 22 *
141// store volatile i8 %m, i8* %amx.tmm.3.shape.row, align 1 *
142// store volatile i16 %n, i16* %amx.tmm.3.shape.col, align 2 *
143// --------------------------------------------------------------------------
144// call void @llvm.x86.ldtilecfg(i8* %mem) * tile config
145// --------------------------------------------------------------------------
146// %t1 = call x86_amx @llvm.x86.tileloadd64.internal(m, k, ...) key
147// %t2 = call x86_amx @llvm.x86.tileloadd64.internal(k, n, ...)
148// %t3 = call x86_amx @llvm.x86.tileloadd64.internal(m, n, ...) amx
149// %td = tail call x86_amx @llvm.x86.tdpbssd.internal(m, n, k, t1, t2, t3)
150// call void @llvm.x86.tilestored64.internal(... td) area
151// --------------------------------------------------------------------------
152bool X86PreAMXConfig::preWriteTileCfg(Value *I8Ptr, Instruction *Pos,
153 SmallVector<Value *, 8> &Shapes) {
154 bool Write = false;
155 LLVMContext &Ctx = Pos->getParent()->getContext();
156 Type *I8Ty = Type::getInt8Ty(Ctx);
157 Type *I16Ty = Type::getInt16Ty(Ctx);
158
159 // TODO: Currently we defaultly set Palette = 1, it may be assigned to
160 // other value in the future.
161 Value *PaletteOffset = ConstantInt::get(Type::getInt64Ty(Ctx), 0);
162 Value *PaletteValue = ConstantInt::get(Type::getInt8Ty(Ctx), 1);
163 Value *PalettePos =
164 GetElementPtrInst::Create(I8Ty, I8Ptr, PaletteOffset, "", Pos);
165 new StoreInst(PaletteValue, PalettePos, Pos);
166
167 for (int I = 0, E = Shapes.size() / 2; I < E; I++) {
168 Value *RowOffset = ConstantInt::get(Type::getInt64Ty(Ctx), 48 + I);
169 Value *ColOffset = ConstantInt::get(Type::getInt64Ty(Ctx), 16 + I * 2);
170 const std::string ShapeName = "amx.tmm." + itostr(I);
171 Value *RowPos = GetElementPtrInst::Create(I8Ty, I8Ptr, RowOffset,
172 ShapeName + ".shape.row", Pos);
173 Value *ColPos = GetElementPtrInst::Create(I8Ty, I8Ptr, ColOffset, "", Pos);
174 ColPos = new BitCastInst(ColPos, PointerType::get(I16Ty, 0),
175 ShapeName + ".shape.col", Pos);
176 Value *Row = Shapes[I * 2];
177 Value *Col = Shapes[I * 2 + 1];
178 Row = new TruncInst(Row, I8Ty, "", Pos);
179 new StoreInst(Row, RowPos, Pos);
180 new StoreInst(Col, ColPos, Pos);
181 Write = true;
182 }
183 return Write;
184}
185
186bool X86PreAMXConfig::addTileConfig(Instruction *ModelStart,
187 SmallVector<Value *, 8> &Shapes) {
188 Module *M = F.getParent();
189 IRBuilder<> Builder(ModelStart);
190 const DataLayout &DL = M->getDataLayout();
191 unsigned AddrSpace = DL.getAllocaAddrSpace();
192 LLVMContext &Ctx = Builder.getContext();
193 Type *V512Ty = VectorType::get(Builder.getInt32Ty(), 16, false);
194 Align Alignment = DL.getPrefTypeAlign(Type::getInt32Ty(Ctx));
195
196 AllocaInst *Addr =
197 new AllocaInst(V512Ty, AddrSpace, "", &F.getEntryBlock().front());
198 Addr->setAlignment(Alignment);
199 Value *I8Ptr = Builder.CreateBitCast(Addr, Builder.getInt8PtrTy());
200
201 std::array<Value *, 1> Args = {I8Ptr};
202 Instruction *Cfg =
203 Builder.CreateIntrinsic(Intrinsic::x86_ldtilecfg_internal, None, Args);
204
205 Value *Val0 = Constant::getNullValue(V512Ty);
206 Instruction *Init0 = new StoreInst(Val0, Addr, false, Alignment, Cfg);
207 assert(Init0 && "Not Zero initilizate the cfg mem!")((void)0);
208
209 preWriteTileCfg(I8Ptr, Cfg, Shapes);
210
211 return Init0;
212}
213
214// Todo: We may need to handle "more than one store" case in the future.
215bool X86PreAMXConfig::checkVolatileModel(SmallSet<Value *, 4> &Loads,
216 IntrinsicInst *Store,
217 IntrinsicInst *KeyAMX) {
218 Value *ST = Store->getOperand(4);
219
220 // Only has tileload and tilestore.
221 if (!KeyAMX)
222 return (Loads.size() == 1) && Loads.contains(ST);
223
224 // All Loads should be operands of KeyAMX.
225 // All tile operands of KeyAMX should come from Loads.
226 for (Value *Op : KeyAMX->operands()) {
227 if (Op->getType()->isX86_AMXTy())
228 if (!Loads.erase(Op))
229 return false;
230 }
231
232 // The def of KeyAMX should be stored into mem.
233 // Todo: is it key amx can be no def?
234 return Loads.empty() && (ST == cast<Value>(KeyAMX));
235}
236
237bool X86PreAMXConfig::getKeyAMXShapes(IntrinsicInst *KeyAMX,
238 SmallVector<Value *, 8> &Shapes) {
239 for (unsigned I = 0; I < KeyAMX->getNumOperands(); I++) {
14
Assuming the condition is true
15
Loop condition is true. Entering loop body
240 Value *Op = KeyAMX->getOperand(I);
241 if (!Op->getType()->isX86_AMXTy())
16
Calling 'Type::isX86_AMXTy'
19
Returning from 'Type::isX86_AMXTy'
20
Taking false branch
242 continue;
243 IntrinsicInst *TileDef = dyn_cast<IntrinsicInst>(Op);
21
Assuming 'Op' is not a 'IntrinsicInst'
22
'TileDef' initialized to a null pointer value
244 assert((TileDef && isTileLoad(TileDef)) &&((void)0)
245 "All KeyAMX's tile definiation should comes from TileLoad!")((void)0);
246 Shapes.push_back(TileDef->getOperand(0));
23
Called C++ object pointer is null
247 Shapes.push_back(TileDef->getOperand(1));
248 }
249 if (!isTileStore(KeyAMX)) {
250 Shapes.push_back(KeyAMX->getOperand(0));
251 Shapes.push_back(KeyAMX->getOperand(1));
252 }
253 return Shapes.size() != 0;
254}
255
256// Collect the shapes and skip the area of current key amx intrinsic.
257//
258// For example:
259// ...
260// --------------------------------------------------------------------------
261// %t1 = call x86_amx @llvm.x86.tileloadd64.internal(m, k, ...) record (m,k)
262// %t2 = call x86_amx @llvm.x86.tileloadd64.internal(k, n, ...) record (m,k)
263// %t3 = call x86_amx @llvm.x86.tileloadd64.internal(m, n, ...) record (m,k)
264// %td = call x86_amx @llvm.x86.tdpbssd.internal(...t1, t2, t3)
265// call void @llvm.x86.tilestored64.internal(m, n,... td) <--PosEnd record (m,k)
266// --------------------------------------------------------------------------
267BasicBlock::iterator
268X86PreAMXConfig::getShapesAndConfigPosEnd(BasicBlock::iterator Iter,
269 SmallVector<Value *, 8> &Shapes) {
270 IntrinsicInst *KeyAMX = nullptr;
271 BasicBlock *BB = Iter->getParent();
272 BasicBlock::iterator PosEnd = BB->end();
273 SmallSet<Value *, 4> Loads;
274
275 // See TileStore as "Config Position End" and check volatile model.
276 for (auto I = Iter, E = BB->end(); I != E; ++I) {
10
Loop condition is false. Execution continues on line 294
277 assert(!brokenVolatile(&*I) && "Not reach tile store!")((void)0);
278 IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*I);
279 if (!II || !isAMXIntrinsic(II))
280 continue;
281
282 if (isTileLoad(II)) {
283 Loads.insert(II);
284 } else if (isTileStore(II)) {
285 if (!checkVolatileModel(Loads, II, KeyAMX))
286 report_fatal_error("Not Volatile AMX Model!");
287 PosEnd = I;
288 break;
289 } else {
290 assert(!KeyAMX && "Too many key amx intrinsic!")((void)0);
291 KeyAMX = II;
292 }
293 }
294 assert(PosEnd != BB->end() && "Not find TileStore!")((void)0);
295
296 // See KeyAMX as TileStore if only TileLoad and TileStore.
297 if (!KeyAMX
10.1
'KeyAMX' is null
10.1
'KeyAMX' is null
)
11
Taking true branch
298 KeyAMX = dyn_cast<IntrinsicInst>(&*PosEnd);
12
Assuming the object is a 'IntrinsicInst'
299
300 // Get Shapes in order.
301 assert(Shapes.empty() && "Shapes should be clean.")((void)0);
302 getKeyAMXShapes(KeyAMX, Shapes);
13
Calling 'X86PreAMXConfig::getKeyAMXShapes'
303
304 return PosEnd;
305}
306
307// Record a key amx area's shapes with its position.
308// Use the first tileload as its position.
309// For example:
310// ...
311// --------------------------------------------------------------------------
312// %t1 = call x86_amx @llvm.x86.tileloadd64.internal(m, k, ...) <-- pos
313// %t2 = call x86_amx @llvm.x86.tileloadd64.internal(k, n, ...) /
314// %t3 = call x86_amx @llvm.x86.tileloadd64.internal(m, n, ...) shapes:
315// %td = call x86_amx @llvm.x86.tdpbssd.internal(...t1, t2, t3) (m,k)(k,n)
316// call void @llvm.x86.tilestored64.internal(m, n,... td) (m,n)(m,n)
317// --------------------------------------------------------------------------
318bool X86PreAMXConfig::findConfigShapes(
319 DenseMap<Instruction *, SmallVector<Value *, 8>> &PosAndShapes) {
320 bool Find = false;
321 for (BasicBlock &BB : F) {
322 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
5
Loop condition is true. Entering loop body
323 IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*I);
6
Assuming the object is a 'IntrinsicInst'
324 if (!II
6.1
'II' is non-null
6.1
'II' is non-null
)
7
Taking false branch
325 continue;
326 if (!isAMXIntrinsic(II))
8
Taking false branch
327 continue;
328 assert(onlyTileDef(II) && "Not volatile model for AMX at O0!")((void)0);
329
330 I = getShapesAndConfigPosEnd(I, PosAndShapes[&*I]);
9
Calling 'X86PreAMXConfig::getShapesAndConfigPosEnd'
331 Find = true;
332 }
333 }
334 return Find;
335}
336
337// Insert ldtilecfg and preconfig the shapes for each area of key AMX intrinsic.
338// e.g. (key amx = tdpbssd)
339// --------------------------------------------------------------------------
340// %cfgmem = alloca <16 x i32>, align 4 * allocate mem
341// store <16 x i32> zeroinitializer, <16 x i32>* %cfgmem * zero init
342// ...
343// ... pre-config shape of %t1 *
344// store volatile i8 %m, i8* %amx.tmm.0.shape.row, align 1 *
345// store volatile i16 %k, i16* %amx.tmm.0.shape.col, align 2 * pre-config
346// ... *
347// ... pre-config shape of %t2 *
348// store volatile i8 %k, i8* %amx.tmm.1.shape.row, align 1 * shapes
349// store volatile i16 %n, i16* %amx.tmm.1.shape.col, align 2 *
350// ... *
351// ... pre-config shape of %t3 * of
352// store volatile i8 %m, i8* %amx.tmm.2.shape.row, align 1 *
353// store volatile i16 %n, i16* %amx.tmm.2.shape.col, align 2 *
354// ... * tiles
355// ... pre-config shape of %td *
356// store volatile i8 %m, i8* %amx.tmm.3.shape.row, align 1 *
357// store volatile i16 %n, i16* %amx.tmm.3.shape.col, align 2 *
358//
359// call void @llvm.x86.ldtilecfg(i8* %cfgmem) * pre-config
360// --------------------------------------------------------------------------
361// %t1 = call x86_amx @llvm.x86.tileloadd64.internal(m, k, ...) key
362// %t2 = call x86_amx @llvm.x86.tileloadd64.internal(k, n, ...)
363// %t3 = call x86_amx @llvm.x86.tileloadd64.internal(m, n, ...) amx
364// %td = tail call x86_amx @llvm.x86.tdpbssd.internal(m, n, k, t1, t2, t3)
365// call void @llvm.x86.tilestored64.internal(... td) area
366// --------------------------------------------------------------------------
367bool X86PreAMXConfig::preTileConfig() {
368 DenseMap<Instruction *, SmallVector<Value *, 8>> PosAndShapes;
369 bool NeedCfg = findConfigShapes(PosAndShapes);
4
Calling 'X86PreAMXConfig::findConfigShapes'
370 if (!NeedCfg)
371 return false;
372 for (auto &IPAndShapes : PosAndShapes)
373 addTileConfig(IPAndShapes.first, IPAndShapes.second);
374
375 return true;
376}
377} // anonymous namespace
378
379namespace {
380
381class X86PreAMXConfigPass : public FunctionPass {
382public:
383 static char ID;
384
385 X86PreAMXConfigPass() : FunctionPass(ID) {
386 initializeX86PreAMXConfigPassPass(*PassRegistry::getPassRegistry());
387 }
388
389 bool runOnFunction(Function &F) override {
390 TargetMachine *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
391 bool C = false;
392
393 // Prepare for fast register allocation at O0.
394 if (TM->getOptLevel() == CodeGenOpt::None) {
1
Assuming the condition is true
2
Taking true branch
395
396 // We pre-config each key AMX intrinsic at O0.
397 // In theory, one tile config can cover several AMX intrinsics, but
398 // it is very diffcult to classify the tile shapes at O0. So here we
399 // let thing be easy, pre-config every key AMX intrinsic.
400 X86PreAMXConfig PCFG(F);
401 C = PCFG.preTileConfig();
3
Calling 'X86PreAMXConfig::preTileConfig'
402 }
403
404 return C;
405 }
406
407 void getAnalysisUsage(AnalysisUsage &AU) const override {
408 AU.setPreservesCFG();
409 AU.addRequired<TargetPassConfig>();
410 }
411};
412
413} // anonymous namespace
414
415static const char PassName[] = "Pre AMX Tile Config";
416char X86PreAMXConfigPass::ID = 0;
417INITIALIZE_PASS_BEGIN(X86PreAMXConfigPass, DEBUG_TYPE, PassName, false, false)static void *initializeX86PreAMXConfigPassPassOnce(PassRegistry
&Registry) {
418INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)initializeTargetPassConfigPass(Registry);
419INITIALIZE_PASS_END(X86PreAMXConfigPass, DEBUG_TYPE, PassName, false, false)PassInfo *PI = new PassInfo( PassName, "pre-amx-config", &
X86PreAMXConfigPass::ID, PassInfo::NormalCtor_t(callDefaultCtor
<X86PreAMXConfigPass>), false, false); Registry.registerPass
(*PI, true); return PI; } static llvm::once_flag InitializeX86PreAMXConfigPassPassFlag
; void llvm::initializeX86PreAMXConfigPassPass(PassRegistry &
Registry) { llvm::call_once(InitializeX86PreAMXConfigPassPassFlag
, initializeX86PreAMXConfigPassPassOnce, std::ref(Registry));
}
420
421FunctionPass *llvm::createX86PreAMXConfigPass() {
422 return new X86PreAMXConfigPass();
423}

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR/Type.h

1//===- llvm/Type.h - Classes for handling data types ------------*- 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 contains the declaration of the Type class. For more "Type"
10// stuff, look in DerivedTypes.h.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_IR_TYPE_H
15#define LLVM_IR_TYPE_H
16
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/SmallPtrSet.h"
20#include "llvm/Support/CBindingWrapping.h"
21#include "llvm/Support/Casting.h"
22#include "llvm/Support/Compiler.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/TypeSize.h"
25#include <cassert>
26#include <cstdint>
27#include <iterator>
28
29namespace llvm {
30
31class IntegerType;
32class LLVMContext;
33class PointerType;
34class raw_ostream;
35class StringRef;
36
37/// The instances of the Type class are immutable: once they are created,
38/// they are never changed. Also note that only one instance of a particular
39/// type is ever created. Thus seeing if two types are equal is a matter of
40/// doing a trivial pointer comparison. To enforce that no two equal instances
41/// are created, Type instances can only be created via static factory methods
42/// in class Type and in derived classes. Once allocated, Types are never
43/// free'd.
44///
45class Type {
46public:
47 //===--------------------------------------------------------------------===//
48 /// Definitions of all of the base types for the Type system. Based on this
49 /// value, you can cast to a class defined in DerivedTypes.h.
50 /// Note: If you add an element to this, you need to add an element to the
51 /// Type::getPrimitiveType function, or else things will break!
52 /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding.
53 ///
54 enum TypeID {
55 // PrimitiveTypes
56 HalfTyID = 0, ///< 16-bit floating point type
57 BFloatTyID, ///< 16-bit floating point type (7-bit significand)
58 FloatTyID, ///< 32-bit floating point type
59 DoubleTyID, ///< 64-bit floating point type
60 X86_FP80TyID, ///< 80-bit floating point type (X87)
61 FP128TyID, ///< 128-bit floating point type (112-bit significand)
62 PPC_FP128TyID, ///< 128-bit floating point type (two 64-bits, PowerPC)
63 VoidTyID, ///< type with no size
64 LabelTyID, ///< Labels
65 MetadataTyID, ///< Metadata
66 X86_MMXTyID, ///< MMX vectors (64 bits, X86 specific)
67 X86_AMXTyID, ///< AMX vectors (8192 bits, X86 specific)
68 TokenTyID, ///< Tokens
69
70 // Derived types... see DerivedTypes.h file.
71 IntegerTyID, ///< Arbitrary bit width integers
72 FunctionTyID, ///< Functions
73 PointerTyID, ///< Pointers
74 StructTyID, ///< Structures
75 ArrayTyID, ///< Arrays
76 FixedVectorTyID, ///< Fixed width SIMD vector type
77 ScalableVectorTyID ///< Scalable SIMD vector type
78 };
79
80private:
81 /// This refers to the LLVMContext in which this type was uniqued.
82 LLVMContext &Context;
83
84 TypeID ID : 8; // The current base type of this type.
85 unsigned SubclassData : 24; // Space for subclasses to store data.
86 // Note that this should be synchronized with
87 // MAX_INT_BITS value in IntegerType class.
88
89protected:
90 friend class LLVMContextImpl;
91
92 explicit Type(LLVMContext &C, TypeID tid)
93 : Context(C), ID(tid), SubclassData(0) {}
94 ~Type() = default;
95
96 unsigned getSubclassData() const { return SubclassData; }
97
98 void setSubclassData(unsigned val) {
99 SubclassData = val;
100 // Ensure we don't have any accidental truncation.
101 assert(getSubclassData() == val && "Subclass data too large for field")((void)0);
102 }
103
104 /// Keeps track of how many Type*'s there are in the ContainedTys list.
105 unsigned NumContainedTys = 0;
106
107 /// A pointer to the array of Types contained by this Type. For example, this
108 /// includes the arguments of a function type, the elements of a structure,
109 /// the pointee of a pointer, the element type of an array, etc. This pointer
110 /// may be 0 for types that don't contain other types (Integer, Double,
111 /// Float).
112 Type * const *ContainedTys = nullptr;
113
114public:
115 /// Print the current type.
116 /// Omit the type details if \p NoDetails == true.
117 /// E.g., let %st = type { i32, i16 }
118 /// When \p NoDetails is true, we only print %st.
119 /// Put differently, \p NoDetails prints the type as if
120 /// inlined with the operands when printing an instruction.
121 void print(raw_ostream &O, bool IsForDebug = false,
122 bool NoDetails = false) const;
123
124 void dump() const;
125
126 /// Return the LLVMContext in which this type was uniqued.
127 LLVMContext &getContext() const { return Context; }
128
129 //===--------------------------------------------------------------------===//
130 // Accessors for working with types.
131 //
132
133 /// Return the type id for the type. This will return one of the TypeID enum
134 /// elements defined above.
135 TypeID getTypeID() const { return ID; }
136
137 /// Return true if this is 'void'.
138 bool isVoidTy() const { return getTypeID() == VoidTyID; }
139
140 /// Return true if this is 'half', a 16-bit IEEE fp type.
141 bool isHalfTy() const { return getTypeID() == HalfTyID; }
142
143 /// Return true if this is 'bfloat', a 16-bit bfloat type.
144 bool isBFloatTy() const { return getTypeID() == BFloatTyID; }
145
146 /// Return true if this is 'float', a 32-bit IEEE fp type.
147 bool isFloatTy() const { return getTypeID() == FloatTyID; }
148
149 /// Return true if this is 'double', a 64-bit IEEE fp type.
150 bool isDoubleTy() const { return getTypeID() == DoubleTyID; }
151
152 /// Return true if this is x86 long double.
153 bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; }
154
155 /// Return true if this is 'fp128'.
156 bool isFP128Ty() const { return getTypeID() == FP128TyID; }
157
158 /// Return true if this is powerpc long double.
159 bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; }
160
161 /// Return true if this is one of the six floating-point types
162 bool isFloatingPointTy() const {
163 return getTypeID() == HalfTyID || getTypeID() == BFloatTyID ||
164 getTypeID() == FloatTyID || getTypeID() == DoubleTyID ||
165 getTypeID() == X86_FP80TyID || getTypeID() == FP128TyID ||
166 getTypeID() == PPC_FP128TyID;
167 }
168
169 const fltSemantics &getFltSemantics() const {
170 switch (getTypeID()) {
171 case HalfTyID: return APFloat::IEEEhalf();
172 case BFloatTyID: return APFloat::BFloat();
173 case FloatTyID: return APFloat::IEEEsingle();
174 case DoubleTyID: return APFloat::IEEEdouble();
175 case X86_FP80TyID: return APFloat::x87DoubleExtended();
176 case FP128TyID: return APFloat::IEEEquad();
177 case PPC_FP128TyID: return APFloat::PPCDoubleDouble();
178 default: llvm_unreachable("Invalid floating type")__builtin_unreachable();
179 }
180 }
181
182 /// Return true if this is X86 MMX.
183 bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; }
184
185 /// Return true if this is X86 AMX.
186 bool isX86_AMXTy() const { return getTypeID() == X86_AMXTyID; }
17
Assuming the condition is true
18
Returning the value 1, which participates in a condition later
187
188 /// Return true if this is a FP type or a vector of FP.
189 bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); }
190
191 /// Return true if this is 'label'.
192 bool isLabelTy() const { return getTypeID() == LabelTyID; }
193
194 /// Return true if this is 'metadata'.
195 bool isMetadataTy() const { return getTypeID() == MetadataTyID; }
196
197 /// Return true if this is 'token'.
198 bool isTokenTy() const { return getTypeID() == TokenTyID; }
199
200 /// True if this is an instance of IntegerType.
201 bool isIntegerTy() const { return getTypeID() == IntegerTyID; }
202
203 /// Return true if this is an IntegerType of the given width.
204 bool isIntegerTy(unsigned Bitwidth) const;
205
206 /// Return true if this is an integer type or a vector of integer types.
207 bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); }
208
209 /// Return true if this is an integer type or a vector of integer types of
210 /// the given width.
211 bool isIntOrIntVectorTy(unsigned BitWidth) const {
212 return getScalarType()->isIntegerTy(BitWidth);
213 }
214
215 /// Return true if this is an integer type or a pointer type.
216 bool isIntOrPtrTy() const { return isIntegerTy() || isPointerTy(); }
217
218 /// True if this is an instance of FunctionType.
219 bool isFunctionTy() const { return getTypeID() == FunctionTyID; }
220
221 /// True if this is an instance of StructType.
222 bool isStructTy() const { return getTypeID() == StructTyID; }
223
224 /// True if this is an instance of ArrayType.
225 bool isArrayTy() const { return getTypeID() == ArrayTyID; }
226
227 /// True if this is an instance of PointerType.
228 bool isPointerTy() const { return getTypeID() == PointerTyID; }
229
230 /// True if this is an instance of an opaque PointerType.
231 bool isOpaquePointerTy() const;
232
233 /// Return true if this is a pointer type or a vector of pointer types.
234 bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); }
235
236 /// True if this is an instance of VectorType.
237 inline bool isVectorTy() const {
238 return getTypeID() == ScalableVectorTyID || getTypeID() == FixedVectorTyID;
239 }
240
241 /// Return true if this type could be converted with a lossless BitCast to
242 /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the
243 /// same size only where no re-interpretation of the bits is done.
244 /// Determine if this type could be losslessly bitcast to Ty
245 bool canLosslesslyBitCastTo(Type *Ty) const;
246
247 /// Return true if this type is empty, that is, it has no elements or all of
248 /// its elements are empty.
249 bool isEmptyTy() const;
250
251 /// Return true if the type is "first class", meaning it is a valid type for a
252 /// Value.
253 bool isFirstClassType() const {
254 return getTypeID() != FunctionTyID && getTypeID() != VoidTyID;
255 }
256
257 /// Return true if the type is a valid type for a register in codegen. This
258 /// includes all first-class types except struct and array types.
259 bool isSingleValueType() const {
260 return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() ||
261 isPointerTy() || isVectorTy() || isX86_AMXTy();
262 }
263
264 /// Return true if the type is an aggregate type. This means it is valid as
265 /// the first operand of an insertvalue or extractvalue instruction. This
266 /// includes struct and array types, but does not include vector types.
267 bool isAggregateType() const {
268 return getTypeID() == StructTyID || getTypeID() == ArrayTyID;
269 }
270
271 /// Return true if it makes sense to take the size of this type. To get the
272 /// actual size for a particular target, it is reasonable to use the
273 /// DataLayout subsystem to do this.
274 bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const {
275 // If it's a primitive, it is always sized.
276 if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
277 getTypeID() == PointerTyID || getTypeID() == X86_MMXTyID ||
278 getTypeID() == X86_AMXTyID)
279 return true;
280 // If it is not something that can have a size (e.g. a function or label),
281 // it doesn't have a size.
282 if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && !isVectorTy())
283 return false;
284 // Otherwise we have to try harder to decide.
285 return isSizedDerivedType(Visited);
286 }
287
288 /// Return the basic size of this type if it is a primitive type. These are
289 /// fixed by LLVM and are not target-dependent.
290 /// This will return zero if the type does not have a size or is not a
291 /// primitive type.
292 ///
293 /// If this is a scalable vector type, the scalable property will be set and
294 /// the runtime size will be a positive integer multiple of the base size.
295 ///
296 /// Note that this may not reflect the size of memory allocated for an
297 /// instance of the type or the number of bytes that are written when an
298 /// instance of the type is stored to memory. The DataLayout class provides
299 /// additional query functions to provide this information.
300 ///
301 TypeSize getPrimitiveSizeInBits() const LLVM_READONLY__attribute__((__pure__));
302
303 /// If this is a vector type, return the getPrimitiveSizeInBits value for the
304 /// element type. Otherwise return the getPrimitiveSizeInBits value for this
305 /// type.
306 unsigned getScalarSizeInBits() const LLVM_READONLY__attribute__((__pure__));
307
308 /// Return the width of the mantissa of this type. This is only valid on
309 /// floating-point types. If the FP type does not have a stable mantissa (e.g.
310 /// ppc long double), this method returns -1.
311 int getFPMantissaWidth() const;
312
313 /// Return whether the type is IEEE compatible, as defined by the eponymous
314 /// method in APFloat.
315 bool isIEEE() const { return APFloat::getZero(getFltSemantics()).isIEEE(); }
316
317 /// If this is a vector type, return the element type, otherwise return
318 /// 'this'.
319 inline Type *getScalarType() const {
320 if (isVectorTy())
321 return getContainedType(0);
322 return const_cast<Type *>(this);
323 }
324
325 //===--------------------------------------------------------------------===//
326 // Type Iteration support.
327 //
328 using subtype_iterator = Type * const *;
329
330 subtype_iterator subtype_begin() const { return ContainedTys; }
331 subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];}
332 ArrayRef<Type*> subtypes() const {
333 return makeArrayRef(subtype_begin(), subtype_end());
334 }
335
336 using subtype_reverse_iterator = std::reverse_iterator<subtype_iterator>;
337
338 subtype_reverse_iterator subtype_rbegin() const {
339 return subtype_reverse_iterator(subtype_end());
340 }
341 subtype_reverse_iterator subtype_rend() const {
342 return subtype_reverse_iterator(subtype_begin());
343 }
344
345 /// This method is used to implement the type iterator (defined at the end of
346 /// the file). For derived types, this returns the types 'contained' in the
347 /// derived type.
348 Type *getContainedType(unsigned i) const {
349 assert(i < NumContainedTys && "Index out of range!")((void)0);
350 return ContainedTys[i];
351 }
352
353 /// Return the number of types in the derived type.
354 unsigned getNumContainedTypes() const { return NumContainedTys; }
355
356 //===--------------------------------------------------------------------===//
357 // Helper methods corresponding to subclass methods. This forces a cast to
358 // the specified subclass and calls its accessor. "getArrayNumElements" (for
359 // example) is shorthand for cast<ArrayType>(Ty)->getNumElements(). This is
360 // only intended to cover the core methods that are frequently used, helper
361 // methods should not be added here.
362
363 inline unsigned getIntegerBitWidth() const;
364
365 inline Type *getFunctionParamType(unsigned i) const;
366 inline unsigned getFunctionNumParams() const;
367 inline bool isFunctionVarArg() const;
368
369 inline StringRef getStructName() const;
370 inline unsigned getStructNumElements() const;
371 inline Type *getStructElementType(unsigned N) const;
372
373 inline uint64_t getArrayNumElements() const;
374
375 Type *getArrayElementType() const {
376 assert(getTypeID() == ArrayTyID)((void)0);
377 return ContainedTys[0];
378 }
379
380 Type *getPointerElementType() const {
381 assert(getTypeID() == PointerTyID)((void)0);
382 return ContainedTys[0];
383 }
384
385 /// Given vector type, change the element type,
386 /// whilst keeping the old number of elements.
387 /// For non-vectors simply returns \p EltTy.
388 inline Type *getWithNewType(Type *EltTy) const;
389
390 /// Given an integer or vector type, change the lane bitwidth to NewBitwidth,
391 /// whilst keeping the old number of lanes.
392 inline Type *getWithNewBitWidth(unsigned NewBitWidth) const;
393
394 /// Given scalar/vector integer type, returns a type with elements twice as
395 /// wide as in the original type. For vectors, preserves element count.
396 inline Type *getExtendedType() const;
397
398 /// Get the address space of this pointer or pointer vector type.
399 inline unsigned getPointerAddressSpace() const;
400
401 //===--------------------------------------------------------------------===//
402 // Static members exported by the Type class itself. Useful for getting
403 // instances of Type.
404 //
405
406 /// Return a type based on an identifier.
407 static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber);
408
409 //===--------------------------------------------------------------------===//
410 // These are the builtin types that are always available.
411 //
412 static Type *getVoidTy(LLVMContext &C);
413 static Type *getLabelTy(LLVMContext &C);
414 static Type *getHalfTy(LLVMContext &C);
415 static Type *getBFloatTy(LLVMContext &C);
416 static Type *getFloatTy(LLVMContext &C);
417 static Type *getDoubleTy(LLVMContext &C);
418 static Type *getMetadataTy(LLVMContext &C);
419 static Type *getX86_FP80Ty(LLVMContext &C);
420 static Type *getFP128Ty(LLVMContext &C);
421 static Type *getPPC_FP128Ty(LLVMContext &C);
422 static Type *getX86_MMXTy(LLVMContext &C);
423 static Type *getX86_AMXTy(LLVMContext &C);
424 static Type *getTokenTy(LLVMContext &C);
425 static IntegerType *getIntNTy(LLVMContext &C, unsigned N);
426 static IntegerType *getInt1Ty(LLVMContext &C);
427 static IntegerType *getInt8Ty(LLVMContext &C);
428 static IntegerType *getInt16Ty(LLVMContext &C);
429 static IntegerType *getInt32Ty(LLVMContext &C);
430 static IntegerType *getInt64Ty(LLVMContext &C);
431 static IntegerType *getInt128Ty(LLVMContext &C);
432 template <typename ScalarTy> static Type *getScalarTy(LLVMContext &C) {
433 int noOfBits = sizeof(ScalarTy) * CHAR_BIT8;
434 if (std::is_integral<ScalarTy>::value) {
435 return (Type*) Type::getIntNTy(C, noOfBits);
436 } else if (std::is_floating_point<ScalarTy>::value) {
437 switch (noOfBits) {
438 case 32:
439 return Type::getFloatTy(C);
440 case 64:
441 return Type::getDoubleTy(C);
442 }
443 }
444 llvm_unreachable("Unsupported type in Type::getScalarTy")__builtin_unreachable();
445 }
446 static Type *getFloatingPointTy(LLVMContext &C, const fltSemantics &S) {
447 Type *Ty;
448 if (&S == &APFloat::IEEEhalf())
449 Ty = Type::getHalfTy(C);
450 else if (&S == &APFloat::BFloat())
451 Ty = Type::getBFloatTy(C);
452 else if (&S == &APFloat::IEEEsingle())
453 Ty = Type::getFloatTy(C);
454 else if (&S == &APFloat::IEEEdouble())
455 Ty = Type::getDoubleTy(C);
456 else if (&S == &APFloat::x87DoubleExtended())
457 Ty = Type::getX86_FP80Ty(C);
458 else if (&S == &APFloat::IEEEquad())
459 Ty = Type::getFP128Ty(C);
460 else {
461 assert(&S == &APFloat::PPCDoubleDouble() && "Unknown FP format")((void)0);
462 Ty = Type::getPPC_FP128Ty(C);
463 }
464 return Ty;
465 }
466
467 //===--------------------------------------------------------------------===//
468 // Convenience methods for getting pointer types with one of the above builtin
469 // types as pointee.
470 //
471 static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0);
472 static PointerType *getBFloatPtrTy(LLVMContext &C, unsigned AS = 0);
473 static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0);
474 static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0);
475 static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0);
476 static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0);
477 static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0);
478 static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0);
479 static PointerType *getX86_AMXPtrTy(LLVMContext &C, unsigned AS = 0);
480 static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0);
481 static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0);
482 static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0);
483 static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0);
484 static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0);
485 static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0);
486
487 /// Return a pointer to the current type. This is equivalent to
488 /// PointerType::get(Foo, AddrSpace).
489 /// TODO: Remove this after opaque pointer transition is complete.
490 PointerType *getPointerTo(unsigned AddrSpace = 0) const;
491
492private:
493 /// Derived types like structures and arrays are sized iff all of the members
494 /// of the type are sized as well. Since asking for their size is relatively
495 /// uncommon, move this operation out-of-line.
496 bool isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited = nullptr) const;
497};
498
499// Printing of types.
500inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) {
501 T.print(OS);
502 return OS;
503}
504
505// allow isa<PointerType>(x) to work without DerivedTypes.h included.
506template <> struct isa_impl<PointerType, Type> {
507 static inline bool doit(const Type &Ty) {
508 return Ty.getTypeID() == Type::PointerTyID;
509 }
510};
511
512// Create wrappers for C Binding types (see CBindingWrapping.h).
513DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef)inline Type *unwrap(LLVMTypeRef P) { return reinterpret_cast<
Type*>(P); } inline LLVMTypeRef wrap(const Type *P) { return
reinterpret_cast<LLVMTypeRef>(const_cast<Type*>(
P)); } template<typename T> inline T *unwrap(LLVMTypeRef
P) { return cast<T>(unwrap(P)); }
514
515/* Specialized opaque type conversions.
516 */
517inline Type **unwrap(LLVMTypeRef* Tys) {
518 return reinterpret_cast<Type**>(Tys);
519}
520
521inline LLVMTypeRef *wrap(Type **Tys) {
522 return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys));
523}
524
525} // end namespace llvm
526
527#endif // LLVM_IR_TYPE_H