Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 1 | //===- IRBuilder.cpp - Builder for LLVM Instrs ----------------------------===// |
Chris Lattner | 17079fc | 2009-12-28 21:28:46 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Chris Lattner | 17079fc | 2009-12-28 21:28:46 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the IRBuilder class, which is used as a convenient way |
| 10 | // to create LLVM instructions with a consistent and simplified interface. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Chandler Carruth | 6bda14b | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 14 | #include "llvm/IR/IRBuilder.h" |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/ArrayRef.h" |
| 16 | #include "llvm/ADT/None.h" |
| 17 | #include "llvm/IR/Constant.h" |
| 18 | #include "llvm/IR/Constants.h" |
| 19 | #include "llvm/IR/DerivedTypes.h" |
Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 20 | #include "llvm/IR/Function.h" |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 21 | #include "llvm/IR/GlobalValue.h" |
Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 22 | #include "llvm/IR/GlobalVariable.h" |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 23 | #include "llvm/IR/IntrinsicInst.h" |
Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 24 | #include "llvm/IR/Intrinsics.h" |
| 25 | #include "llvm/IR/LLVMContext.h" |
Nikita Popov | 3eaa53e | 2020-02-16 17:10:09 +0100 | [diff] [blame] | 26 | #include "llvm/IR/NoFolder.h" |
Simon Pilgrim | c941b64 | 2020-06-25 12:48:14 +0100 | [diff] [blame] | 27 | #include "llvm/IR/Operator.h" |
Pat Gavlin | cc0431d | 2015-05-08 18:07:42 +0000 | [diff] [blame] | 28 | #include "llvm/IR/Statepoint.h" |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 29 | #include "llvm/IR/Type.h" |
| 30 | #include "llvm/IR/Value.h" |
| 31 | #include "llvm/Support/Casting.h" |
| 32 | #include "llvm/Support/MathExtras.h" |
| 33 | #include <cassert> |
| 34 | #include <cstdint> |
| 35 | #include <vector> |
| 36 | |
Chris Lattner | 17079fc | 2009-12-28 21:28:46 +0000 | [diff] [blame] | 37 | using namespace llvm; |
| 38 | |
| 39 | /// CreateGlobalString - Make a new global variable with an initializer that |
Dan Gohman | 97c5902 | 2010-02-10 20:04:19 +0000 | [diff] [blame] | 40 | /// has array of i8 type filled in with the nul terminated string value |
Chris Lattner | 17079fc | 2009-12-28 21:28:46 +0000 | [diff] [blame] | 41 | /// specified. If Name is specified, it is the name of the global variable |
| 42 | /// created. |
David Blaikie | aa41cd5 | 2015-04-03 21:33:42 +0000 | [diff] [blame] | 43 | GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str, |
Tobias Grosser | cdb8914 | 2015-06-19 02:12:07 +0000 | [diff] [blame] | 44 | const Twine &Name, |
Johannes Doerfert | fa5d22a | 2020-05-28 09:41:01 -0500 | [diff] [blame] | 45 | unsigned AddressSpace, |
| 46 | Module *M) { |
Chris Lattner | cf9e8f6 | 2012-02-05 02:29:43 +0000 | [diff] [blame] | 47 | Constant *StrConstant = ConstantDataArray::getString(Context, Str); |
Johannes Doerfert | fa5d22a | 2020-05-28 09:41:01 -0500 | [diff] [blame] | 48 | if (!M) |
| 49 | M = BB->getParent()->getParent(); |
| 50 | auto *GV = new GlobalVariable( |
| 51 | *M, StrConstant->getType(), true, GlobalValue::PrivateLinkage, |
| 52 | StrConstant, Name, nullptr, GlobalVariable::NotThreadLocal, AddressSpace); |
Peter Collingbourne | 96efdd6 | 2016-06-14 21:01:22 +0000 | [diff] [blame] | 53 | GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); |
Guillaume Chatelet | 805c157 | 2020-01-21 15:00:04 +0100 | [diff] [blame] | 54 | GV->setAlignment(Align(1)); |
Chris Lattner | 17079fc | 2009-12-28 21:28:46 +0000 | [diff] [blame] | 55 | return GV; |
| 56 | } |
Chris Lattner | 7ef1cac | 2009-12-28 21:45:40 +0000 | [diff] [blame] | 57 | |
Chris Lattner | b1907b2 | 2011-07-12 04:14:22 +0000 | [diff] [blame] | 58 | Type *IRBuilderBase::getCurrentFunctionReturnType() const { |
Chris Lattner | 49f9f76 | 2009-12-28 21:50:56 +0000 | [diff] [blame] | 59 | assert(BB && BB->getParent() && "No current function!"); |
| 60 | return BB->getParent()->getReturnType(); |
| 61 | } |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 62 | |
| 63 | Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) { |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 64 | auto *PT = cast<PointerType>(Ptr->getType()); |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 65 | if (PT->getElementType()->isIntegerTy(8)) |
| 66 | return Ptr; |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 67 | |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 68 | // Otherwise, we need to insert a bitcast. |
Nikita Popov | f6875c4 | 2020-02-18 20:35:16 +0100 | [diff] [blame] | 69 | return CreateBitCast(Ptr, getInt8PtrTy(PT->getAddressSpace())); |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 70 | } |
| 71 | |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 72 | static CallInst *createCallHelper(Function *Callee, ArrayRef<Value *> Ops, |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 73 | IRBuilderBase *Builder, |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 74 | const Twine &Name = "", |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 75 | Instruction *FMFSource = nullptr, |
| 76 | ArrayRef<OperandBundleDef> OpBundles = {}) { |
| 77 | CallInst *CI = Builder->CreateCall(Callee, Ops, OpBundles, Name); |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 78 | if (FMFSource) |
| 79 | CI->copyFastMathFlags(FMFSource); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 80 | return CI; |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 81 | } |
| 82 | |
Guillaume Chatelet | 1b2842b | 2019-12-09 17:36:50 +0100 | [diff] [blame] | 83 | CallInst *IRBuilderBase::CreateMemSet(Value *Ptr, Value *Val, Value *Size, |
| 84 | MaybeAlign Align, bool isVolatile, |
| 85 | MDNode *TBAATag, MDNode *ScopeTag, |
| 86 | MDNode *NoAliasTag) { |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 87 | Ptr = getCastedInt8PtrValue(Ptr); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 88 | Value *Ops[] = {Ptr, Val, Size, getInt1(isVolatile)}; |
Jay Foad | b804a2b | 2011-07-12 14:06:48 +0000 | [diff] [blame] | 89 | Type *Tys[] = { Ptr->getType(), Size->getType() }; |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 90 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 91 | Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 92 | |
Jay Foad | 5bd375a | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 93 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 94 | |
Guillaume Chatelet | 1b2842b | 2019-12-09 17:36:50 +0100 | [diff] [blame] | 95 | if (Align) |
| 96 | cast<MemSetInst>(CI)->setDestAlignment(Align->value()); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 97 | |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 98 | // Set the TBAA info if present. |
| 99 | if (TBAATag) |
| 100 | CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); |
Hal Finkel | 9414665 | 2014-07-24 14:25:39 +0000 | [diff] [blame] | 101 | |
| 102 | if (ScopeTag) |
| 103 | CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 104 | |
Hal Finkel | 9414665 | 2014-07-24 14:25:39 +0000 | [diff] [blame] | 105 | if (NoAliasTag) |
| 106 | CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 107 | |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 108 | return CI; |
| 109 | } |
| 110 | |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 111 | CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemSet( |
Guillaume Chatelet | b4982d6 | 2019-12-19 15:41:05 +0100 | [diff] [blame] | 112 | Value *Ptr, Value *Val, Value *Size, Align Alignment, uint32_t ElementSize, |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 113 | MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) { |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 114 | |
| 115 | Ptr = getCastedInt8PtrValue(Ptr); |
| 116 | Value *Ops[] = {Ptr, Val, Size, getInt32(ElementSize)}; |
| 117 | Type *Tys[] = {Ptr->getType(), Size->getType()}; |
| 118 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 119 | Function *TheFn = Intrinsic::getDeclaration( |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 120 | M, Intrinsic::memset_element_unordered_atomic, Tys); |
| 121 | |
| 122 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
| 123 | |
Guillaume Chatelet | b4982d6 | 2019-12-19 15:41:05 +0100 | [diff] [blame] | 124 | cast<AtomicMemSetInst>(CI)->setDestAlignment(Alignment); |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 125 | |
| 126 | // Set the TBAA info if present. |
| 127 | if (TBAATag) |
| 128 | CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); |
| 129 | |
| 130 | if (ScopeTag) |
| 131 | CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); |
| 132 | |
| 133 | if (NoAliasTag) |
| 134 | CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); |
| 135 | |
| 136 | return CI; |
| 137 | } |
| 138 | |
Guillaume Chatelet | dbc5acf | 2019-12-12 15:32:19 +0100 | [diff] [blame] | 139 | CallInst *IRBuilderBase::CreateMemCpy(Value *Dst, MaybeAlign DstAlign, |
| 140 | Value *Src, MaybeAlign SrcAlign, |
| 141 | Value *Size, bool isVolatile, |
| 142 | MDNode *TBAATag, MDNode *TBAAStructTag, |
| 143 | MDNode *ScopeTag, MDNode *NoAliasTag) { |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 144 | Dst = getCastedInt8PtrValue(Dst); |
| 145 | Src = getCastedInt8PtrValue(Src); |
| 146 | |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 147 | Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)}; |
Jay Foad | b804a2b | 2011-07-12 14:06:48 +0000 | [diff] [blame] | 148 | Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() }; |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 149 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 150 | Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 151 | |
Jay Foad | 5bd375a | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 152 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 153 | |
Daniel Neilson | 551a4d6 | 2018-01-27 17:59:10 +0000 | [diff] [blame] | 154 | auto* MCI = cast<MemCpyInst>(CI); |
Guillaume Chatelet | dbc5acf | 2019-12-12 15:32:19 +0100 | [diff] [blame] | 155 | if (DstAlign) |
| 156 | MCI->setDestAlignment(*DstAlign); |
| 157 | if (SrcAlign) |
| 158 | MCI->setSourceAlignment(*SrcAlign); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 159 | |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 160 | // Set the TBAA info if present. |
| 161 | if (TBAATag) |
| 162 | CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); |
Dan Gohman | 099727f | 2012-09-26 22:17:14 +0000 | [diff] [blame] | 163 | |
| 164 | // Set the TBAA Struct info if present. |
| 165 | if (TBAAStructTag) |
| 166 | CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 167 | |
Hal Finkel | 9414665 | 2014-07-24 14:25:39 +0000 | [diff] [blame] | 168 | if (ScopeTag) |
| 169 | CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 170 | |
Hal Finkel | 9414665 | 2014-07-24 14:25:39 +0000 | [diff] [blame] | 171 | if (NoAliasTag) |
| 172 | CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 173 | |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 174 | return CI; |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 175 | } |
| 176 | |
Guillaume Chatelet | d65bbf8 | 2020-01-28 13:01:19 +0100 | [diff] [blame] | 177 | CallInst *IRBuilderBase::CreateMemCpyInline(Value *Dst, MaybeAlign DstAlign, |
| 178 | Value *Src, MaybeAlign SrcAlign, |
| 179 | Value *Size) { |
| 180 | Dst = getCastedInt8PtrValue(Dst); |
| 181 | Src = getCastedInt8PtrValue(Src); |
| 182 | Value *IsVolatile = getInt1(false); |
| 183 | |
| 184 | Value *Ops[] = {Dst, Src, Size, IsVolatile}; |
| 185 | Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()}; |
| 186 | Function *F = BB->getParent(); |
| 187 | Module *M = F->getParent(); |
| 188 | Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy_inline, Tys); |
| 189 | |
| 190 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
| 191 | |
| 192 | auto *MCI = cast<MemCpyInlineInst>(CI); |
| 193 | if (DstAlign) |
| 194 | MCI->setDestAlignment(*DstAlign); |
| 195 | if (SrcAlign) |
| 196 | MCI->setSourceAlignment(*SrcAlign); |
| 197 | |
| 198 | return CI; |
| 199 | } |
| 200 | |
Daniel Neilson | 3faabbb | 2017-06-16 14:43:59 +0000 | [diff] [blame] | 201 | CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy( |
Guillaume Chatelet | 46b9563 | 2020-01-20 14:47:28 +0100 | [diff] [blame] | 202 | Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size, |
Daniel Neilson | 6e4aa1e | 2017-11-10 19:38:12 +0000 | [diff] [blame] | 203 | uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag, |
| 204 | MDNode *ScopeTag, MDNode *NoAliasTag) { |
| 205 | assert(DstAlign >= ElementSize && |
| 206 | "Pointer alignment must be at least element size"); |
| 207 | assert(SrcAlign >= ElementSize && |
| 208 | "Pointer alignment must be at least element size"); |
Anna Thomas | b2a212c | 2017-06-06 16:45:25 +0000 | [diff] [blame] | 209 | Dst = getCastedInt8PtrValue(Dst); |
| 210 | Src = getCastedInt8PtrValue(Src); |
| 211 | |
Daniel Neilson | 3faabbb | 2017-06-16 14:43:59 +0000 | [diff] [blame] | 212 | Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)}; |
| 213 | Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()}; |
Anna Thomas | b2a212c | 2017-06-06 16:45:25 +0000 | [diff] [blame] | 214 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 215 | Function *TheFn = Intrinsic::getDeclaration( |
Daniel Neilson | 3faabbb | 2017-06-16 14:43:59 +0000 | [diff] [blame] | 216 | M, Intrinsic::memcpy_element_unordered_atomic, Tys); |
Anna Thomas | b2a212c | 2017-06-06 16:45:25 +0000 | [diff] [blame] | 217 | |
| 218 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
| 219 | |
Daniel Neilson | 6e4aa1e | 2017-11-10 19:38:12 +0000 | [diff] [blame] | 220 | // Set the alignment of the pointer args. |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 221 | auto *AMCI = cast<AtomicMemCpyInst>(CI); |
| 222 | AMCI->setDestAlignment(DstAlign); |
| 223 | AMCI->setSourceAlignment(SrcAlign); |
Daniel Neilson | 6e4aa1e | 2017-11-10 19:38:12 +0000 | [diff] [blame] | 224 | |
Anna Thomas | b2a212c | 2017-06-06 16:45:25 +0000 | [diff] [blame] | 225 | // Set the TBAA info if present. |
| 226 | if (TBAATag) |
| 227 | CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); |
| 228 | |
| 229 | // Set the TBAA Struct info if present. |
| 230 | if (TBAAStructTag) |
| 231 | CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); |
| 232 | |
| 233 | if (ScopeTag) |
| 234 | CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); |
| 235 | |
| 236 | if (NoAliasTag) |
| 237 | CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); |
| 238 | |
| 239 | return CI; |
| 240 | } |
| 241 | |
Guillaume Chatelet | dbc5acf | 2019-12-12 15:32:19 +0100 | [diff] [blame] | 242 | CallInst *IRBuilderBase::CreateMemMove(Value *Dst, MaybeAlign DstAlign, |
| 243 | Value *Src, MaybeAlign SrcAlign, |
| 244 | Value *Size, bool isVolatile, |
| 245 | MDNode *TBAATag, MDNode *ScopeTag, |
| 246 | MDNode *NoAliasTag) { |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 247 | Dst = getCastedInt8PtrValue(Dst); |
| 248 | Src = getCastedInt8PtrValue(Src); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 249 | |
| 250 | Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)}; |
Jay Foad | b804a2b | 2011-07-12 14:06:48 +0000 | [diff] [blame] | 251 | Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() }; |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 252 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 253 | Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 254 | |
Jay Foad | 5bd375a | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 255 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 256 | |
| 257 | auto *MMI = cast<MemMoveInst>(CI); |
Guillaume Chatelet | dbc5acf | 2019-12-12 15:32:19 +0100 | [diff] [blame] | 258 | if (DstAlign) |
| 259 | MMI->setDestAlignment(*DstAlign); |
| 260 | if (SrcAlign) |
| 261 | MMI->setSourceAlignment(*SrcAlign); |
Daniel Neilson | 1e68724 | 2018-01-19 17:13:12 +0000 | [diff] [blame] | 262 | |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 263 | // Set the TBAA info if present. |
| 264 | if (TBAATag) |
| 265 | CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 266 | |
Hal Finkel | 9414665 | 2014-07-24 14:25:39 +0000 | [diff] [blame] | 267 | if (ScopeTag) |
| 268 | CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 269 | |
Hal Finkel | 9414665 | 2014-07-24 14:25:39 +0000 | [diff] [blame] | 270 | if (NoAliasTag) |
| 271 | CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); |
Bjorn Pettersson | aa02580 | 2018-07-03 12:39:52 +0000 | [diff] [blame] | 272 | |
| 273 | return CI; |
Chris Lattner | 143a07c | 2010-12-26 22:49:25 +0000 | [diff] [blame] | 274 | } |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 275 | |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 276 | CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemMove( |
Guillaume Chatelet | 139771f | 2020-01-20 17:11:00 +0100 | [diff] [blame] | 277 | Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size, |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 278 | uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag, |
| 279 | MDNode *ScopeTag, MDNode *NoAliasTag) { |
| 280 | assert(DstAlign >= ElementSize && |
| 281 | "Pointer alignment must be at least element size"); |
| 282 | assert(SrcAlign >= ElementSize && |
| 283 | "Pointer alignment must be at least element size"); |
| 284 | Dst = getCastedInt8PtrValue(Dst); |
| 285 | Src = getCastedInt8PtrValue(Src); |
| 286 | |
| 287 | Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)}; |
| 288 | Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()}; |
| 289 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 290 | Function *TheFn = Intrinsic::getDeclaration( |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 291 | M, Intrinsic::memmove_element_unordered_atomic, Tys); |
| 292 | |
| 293 | CallInst *CI = createCallHelper(TheFn, Ops, this); |
| 294 | |
| 295 | // Set the alignment of the pointer args. |
Guillaume Chatelet | 139771f | 2020-01-20 17:11:00 +0100 | [diff] [blame] | 296 | CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign)); |
| 297 | CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign)); |
Daniel Neilson | 936d50a | 2018-05-30 20:02:56 +0000 | [diff] [blame] | 298 | |
| 299 | // Set the TBAA info if present. |
| 300 | if (TBAATag) |
| 301 | CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); |
| 302 | |
| 303 | // Set the TBAA Struct info if present. |
| 304 | if (TBAAStructTag) |
| 305 | CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); |
| 306 | |
| 307 | if (ScopeTag) |
| 308 | CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); |
| 309 | |
| 310 | if (NoAliasTag) |
| 311 | CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); |
| 312 | |
| 313 | return CI; |
| 314 | } |
| 315 | |
Amara Emerson | cf9daa3 | 2017-05-09 10:43:25 +0000 | [diff] [blame] | 316 | static CallInst *getReductionIntrinsic(IRBuilderBase *Builder, Intrinsic::ID ID, |
| 317 | Value *Src) { |
| 318 | Module *M = Builder->GetInsertBlock()->getParent()->getParent(); |
| 319 | Value *Ops[] = {Src}; |
Sander de Smalen | 51c2fa0 | 2019-06-13 09:37:38 +0000 | [diff] [blame] | 320 | Type *Tys[] = { Src->getType() }; |
Amara Emerson | cf9daa3 | 2017-05-09 10:43:25 +0000 | [diff] [blame] | 321 | auto Decl = Intrinsic::getDeclaration(M, ID, Tys); |
| 322 | return createCallHelper(Decl, Ops, Builder); |
| 323 | } |
| 324 | |
| 325 | CallInst *IRBuilderBase::CreateFAddReduce(Value *Acc, Value *Src) { |
| 326 | Module *M = GetInsertBlock()->getParent()->getParent(); |
| 327 | Value *Ops[] = {Acc, Src}; |
Sander de Smalen | f83cccf | 2019-05-20 09:54:06 +0000 | [diff] [blame] | 328 | Type *Tys[] = {Acc->getType(), Src->getType()}; |
Amara Emerson | cf9daa3 | 2017-05-09 10:43:25 +0000 | [diff] [blame] | 329 | auto Decl = Intrinsic::getDeclaration( |
Sander de Smalen | cbeb563 | 2019-06-11 08:22:10 +0000 | [diff] [blame] | 330 | M, Intrinsic::experimental_vector_reduce_v2_fadd, Tys); |
Amara Emerson | cf9daa3 | 2017-05-09 10:43:25 +0000 | [diff] [blame] | 331 | return createCallHelper(Decl, Ops, this); |
| 332 | } |
| 333 | |
| 334 | CallInst *IRBuilderBase::CreateFMulReduce(Value *Acc, Value *Src) { |
| 335 | Module *M = GetInsertBlock()->getParent()->getParent(); |
| 336 | Value *Ops[] = {Acc, Src}; |
Sander de Smalen | f83cccf | 2019-05-20 09:54:06 +0000 | [diff] [blame] | 337 | Type *Tys[] = {Acc->getType(), Src->getType()}; |
Amara Emerson | cf9daa3 | 2017-05-09 10:43:25 +0000 | [diff] [blame] | 338 | auto Decl = Intrinsic::getDeclaration( |
Sander de Smalen | cbeb563 | 2019-06-11 08:22:10 +0000 | [diff] [blame] | 339 | M, Intrinsic::experimental_vector_reduce_v2_fmul, Tys); |
Amara Emerson | cf9daa3 | 2017-05-09 10:43:25 +0000 | [diff] [blame] | 340 | return createCallHelper(Decl, Ops, this); |
| 341 | } |
| 342 | |
| 343 | CallInst *IRBuilderBase::CreateAddReduce(Value *Src) { |
| 344 | return getReductionIntrinsic(this, Intrinsic::experimental_vector_reduce_add, |
| 345 | Src); |
| 346 | } |
| 347 | |
| 348 | CallInst *IRBuilderBase::CreateMulReduce(Value *Src) { |
| 349 | return getReductionIntrinsic(this, Intrinsic::experimental_vector_reduce_mul, |
| 350 | Src); |
| 351 | } |
| 352 | |
| 353 | CallInst *IRBuilderBase::CreateAndReduce(Value *Src) { |
| 354 | return getReductionIntrinsic(this, Intrinsic::experimental_vector_reduce_and, |
| 355 | Src); |
| 356 | } |
| 357 | |
| 358 | CallInst *IRBuilderBase::CreateOrReduce(Value *Src) { |
| 359 | return getReductionIntrinsic(this, Intrinsic::experimental_vector_reduce_or, |
| 360 | Src); |
| 361 | } |
| 362 | |
| 363 | CallInst *IRBuilderBase::CreateXorReduce(Value *Src) { |
| 364 | return getReductionIntrinsic(this, Intrinsic::experimental_vector_reduce_xor, |
| 365 | Src); |
| 366 | } |
| 367 | |
| 368 | CallInst *IRBuilderBase::CreateIntMaxReduce(Value *Src, bool IsSigned) { |
| 369 | auto ID = IsSigned ? Intrinsic::experimental_vector_reduce_smax |
| 370 | : Intrinsic::experimental_vector_reduce_umax; |
| 371 | return getReductionIntrinsic(this, ID, Src); |
| 372 | } |
| 373 | |
| 374 | CallInst *IRBuilderBase::CreateIntMinReduce(Value *Src, bool IsSigned) { |
| 375 | auto ID = IsSigned ? Intrinsic::experimental_vector_reduce_smin |
| 376 | : Intrinsic::experimental_vector_reduce_umin; |
| 377 | return getReductionIntrinsic(this, ID, Src); |
| 378 | } |
| 379 | |
| 380 | CallInst *IRBuilderBase::CreateFPMaxReduce(Value *Src, bool NoNaN) { |
| 381 | auto Rdx = getReductionIntrinsic( |
| 382 | this, Intrinsic::experimental_vector_reduce_fmax, Src); |
| 383 | if (NoNaN) { |
| 384 | FastMathFlags FMF; |
| 385 | FMF.setNoNaNs(); |
| 386 | Rdx->setFastMathFlags(FMF); |
| 387 | } |
| 388 | return Rdx; |
| 389 | } |
| 390 | |
| 391 | CallInst *IRBuilderBase::CreateFPMinReduce(Value *Src, bool NoNaN) { |
| 392 | auto Rdx = getReductionIntrinsic( |
| 393 | this, Intrinsic::experimental_vector_reduce_fmin, Src); |
| 394 | if (NoNaN) { |
| 395 | FastMathFlags FMF; |
| 396 | FMF.setNoNaNs(); |
| 397 | Rdx->setFastMathFlags(FMF); |
| 398 | } |
| 399 | return Rdx; |
| 400 | } |
| 401 | |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 402 | CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr, ConstantInt *Size) { |
| 403 | assert(isa<PointerType>(Ptr->getType()) && |
Bill Wendling | ea6397f | 2012-07-19 00:11:40 +0000 | [diff] [blame] | 404 | "lifetime.start only applies to pointers."); |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 405 | Ptr = getCastedInt8PtrValue(Ptr); |
| 406 | if (!Size) |
| 407 | Size = getInt64(-1); |
| 408 | else |
| 409 | assert(Size->getType() == getInt64Ty() && |
Bill Wendling | ea6397f | 2012-07-19 00:11:40 +0000 | [diff] [blame] | 410 | "lifetime.start requires the size to be an i64"); |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 411 | Value *Ops[] = { Size, Ptr }; |
| 412 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 413 | Function *TheFn = |
| 414 | Intrinsic::getDeclaration(M, Intrinsic::lifetime_start, {Ptr->getType()}); |
Jay Foad | 5bd375a | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 415 | return createCallHelper(TheFn, Ops, this); |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 416 | } |
| 417 | |
| 418 | CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) { |
| 419 | assert(isa<PointerType>(Ptr->getType()) && |
Bill Wendling | ea6397f | 2012-07-19 00:11:40 +0000 | [diff] [blame] | 420 | "lifetime.end only applies to pointers."); |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 421 | Ptr = getCastedInt8PtrValue(Ptr); |
| 422 | if (!Size) |
| 423 | Size = getInt64(-1); |
| 424 | else |
| 425 | assert(Size->getType() == getInt64Ty() && |
Bill Wendling | ea6397f | 2012-07-19 00:11:40 +0000 | [diff] [blame] | 426 | "lifetime.end requires the size to be an i64"); |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 427 | Value *Ops[] = { Size, Ptr }; |
| 428 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 429 | Function *TheFn = |
| 430 | Intrinsic::getDeclaration(M, Intrinsic::lifetime_end, {Ptr->getType()}); |
Jay Foad | 5bd375a | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 431 | return createCallHelper(TheFn, Ops, this); |
Nick Lewycky | babca9a | 2011-05-21 23:14:36 +0000 | [diff] [blame] | 432 | } |
Hal Finkel | 6f814db | 2014-10-15 23:44:22 +0000 | [diff] [blame] | 433 | |
Anna Thomas | 58d1192 | 2016-07-22 20:57:23 +0000 | [diff] [blame] | 434 | CallInst *IRBuilderBase::CreateInvariantStart(Value *Ptr, ConstantInt *Size) { |
| 435 | |
| 436 | assert(isa<PointerType>(Ptr->getType()) && |
| 437 | "invariant.start only applies to pointers."); |
| 438 | Ptr = getCastedInt8PtrValue(Ptr); |
| 439 | if (!Size) |
| 440 | Size = getInt64(-1); |
| 441 | else |
| 442 | assert(Size->getType() == getInt64Ty() && |
| 443 | "invariant.start requires the size to be an i64"); |
| 444 | |
| 445 | Value *Ops[] = {Size, Ptr}; |
| 446 | // Fill in the single overloaded type: memory object type. |
| 447 | Type *ObjectPtr[1] = {Ptr->getType()}; |
| 448 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 449 | Function *TheFn = |
Anna Thomas | 58d1192 | 2016-07-22 20:57:23 +0000 | [diff] [blame] | 450 | Intrinsic::getDeclaration(M, Intrinsic::invariant_start, ObjectPtr); |
| 451 | return createCallHelper(TheFn, Ops, this); |
| 452 | } |
| 453 | |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 454 | CallInst * |
| 455 | IRBuilderBase::CreateAssumption(Value *Cond, |
| 456 | ArrayRef<OperandBundleDef> OpBundles) { |
Hal Finkel | 6f814db | 2014-10-15 23:44:22 +0000 | [diff] [blame] | 457 | assert(Cond->getType() == getInt1Ty() && |
| 458 | "an assumption condition must be of type i1"); |
| 459 | |
| 460 | Value *Ops[] = { Cond }; |
| 461 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 462 | Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume); |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 463 | return createCallHelper(FnAssume, Ops, this, "", nullptr, OpBundles); |
Hal Finkel | 6f814db | 2014-10-15 23:44:22 +0000 | [diff] [blame] | 464 | } |
| 465 | |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 466 | /// Create a call to a Masked Load intrinsic. |
Guillaume Chatelet | bc8a1ab | 2020-01-21 11:21:31 +0100 | [diff] [blame] | 467 | /// \p Ptr - base pointer for the load |
| 468 | /// \p Alignment - alignment of the source location |
| 469 | /// \p Mask - vector of booleans which indicates what vector lanes should |
| 470 | /// be accessed in memory |
| 471 | /// \p PassThru - pass-through value that is used to fill the masked-off lanes |
| 472 | /// of the result |
| 473 | /// \p Name - name of the result variable |
| 474 | CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, Align Alignment, |
Elena Demikhovsky | 84d1997 | 2014-12-30 14:28:14 +0000 | [diff] [blame] | 475 | Value *Mask, Value *PassThru, |
| 476 | const Twine &Name) { |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 477 | auto *PtrTy = cast<PointerType>(Ptr->getType()); |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 478 | Type *DataTy = PtrTy->getElementType(); |
Elena Demikhovsky | 84d1997 | 2014-12-30 14:28:14 +0000 | [diff] [blame] | 479 | assert(DataTy->isVectorTy() && "Ptr should point to a vector"); |
Ayal Zaks | e841b21 | 2017-07-31 13:21:42 +0000 | [diff] [blame] | 480 | assert(Mask && "Mask should not be all-ones (null)"); |
Elena Demikhovsky | 84d1997 | 2014-12-30 14:28:14 +0000 | [diff] [blame] | 481 | if (!PassThru) |
| 482 | PassThru = UndefValue::get(DataTy); |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 483 | Type *OverloadedTypes[] = { DataTy, PtrTy }; |
Guillaume Chatelet | bc8a1ab | 2020-01-21 11:21:31 +0100 | [diff] [blame] | 484 | Value *Ops[] = {Ptr, getInt32(Alignment.value()), Mask, PassThru}; |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 485 | return CreateMaskedIntrinsic(Intrinsic::masked_load, Ops, |
| 486 | OverloadedTypes, Name); |
Elena Demikhovsky | f1de34b | 2014-12-04 09:40:44 +0000 | [diff] [blame] | 487 | } |
| 488 | |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 489 | /// Create a call to a Masked Store intrinsic. |
Guillaume Chatelet | 0957233 | 2020-01-21 16:13:04 +0100 | [diff] [blame] | 490 | /// \p Val - data to be stored, |
| 491 | /// \p Ptr - base pointer for the store |
| 492 | /// \p Alignment - alignment of the destination location |
| 493 | /// \p Mask - vector of booleans which indicates what vector lanes should |
| 494 | /// be accessed in memory |
Elena Demikhovsky | 84d1997 | 2014-12-30 14:28:14 +0000 | [diff] [blame] | 495 | CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr, |
Guillaume Chatelet | 0957233 | 2020-01-21 16:13:04 +0100 | [diff] [blame] | 496 | Align Alignment, Value *Mask) { |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 497 | auto *PtrTy = cast<PointerType>(Ptr->getType()); |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 498 | Type *DataTy = PtrTy->getElementType(); |
| 499 | assert(DataTy->isVectorTy() && "Ptr should point to a vector"); |
Ayal Zaks | e841b21 | 2017-07-31 13:21:42 +0000 | [diff] [blame] | 500 | assert(Mask && "Mask should not be all-ones (null)"); |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 501 | Type *OverloadedTypes[] = { DataTy, PtrTy }; |
Guillaume Chatelet | 0957233 | 2020-01-21 16:13:04 +0100 | [diff] [blame] | 502 | Value *Ops[] = {Val, Ptr, getInt32(Alignment.value()), Mask}; |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 503 | return CreateMaskedIntrinsic(Intrinsic::masked_store, Ops, OverloadedTypes); |
Elena Demikhovsky | f1de34b | 2014-12-04 09:40:44 +0000 | [diff] [blame] | 504 | } |
| 505 | |
| 506 | /// Create a call to a Masked intrinsic, with given intrinsic Id, |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 507 | /// an array of operands - Ops, and an array of overloaded types - |
| 508 | /// OverloadedTypes. |
Pete Cooper | 9e1d335 | 2015-05-20 17:16:39 +0000 | [diff] [blame] | 509 | CallInst *IRBuilderBase::CreateMaskedIntrinsic(Intrinsic::ID Id, |
Elena Demikhovsky | f1de34b | 2014-12-04 09:40:44 +0000 | [diff] [blame] | 510 | ArrayRef<Value *> Ops, |
Artur Pilipenko | 7ad95ec | 2016-06-28 18:27:25 +0000 | [diff] [blame] | 511 | ArrayRef<Type *> OverloadedTypes, |
Elena Demikhovsky | 84d1997 | 2014-12-30 14:28:14 +0000 | [diff] [blame] | 512 | const Twine &Name) { |
Elena Demikhovsky | f1de34b | 2014-12-04 09:40:44 +0000 | [diff] [blame] | 513 | Module *M = BB->getParent()->getParent(); |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 514 | Function *TheFn = Intrinsic::getDeclaration(M, Id, OverloadedTypes); |
Elena Demikhovsky | 84d1997 | 2014-12-30 14:28:14 +0000 | [diff] [blame] | 515 | return createCallHelper(TheFn, Ops, this, Name); |
Elena Demikhovsky | f1de34b | 2014-12-04 09:40:44 +0000 | [diff] [blame] | 516 | } |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 517 | |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 518 | /// Create a call to a Masked Gather intrinsic. |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 519 | /// \p Ptrs - vector of pointers for loading |
| 520 | /// \p Align - alignment for one element |
| 521 | /// \p Mask - vector of booleans which indicates what vector lanes should |
| 522 | /// be accessed in memory |
| 523 | /// \p PassThru - pass-through value that is used to fill the masked-off lanes |
| 524 | /// of the result |
| 525 | /// \p Name - name of the result variable |
Guillaume Chatelet | d0a7cc7 | 2020-01-24 17:40:17 +0100 | [diff] [blame] | 526 | CallInst *IRBuilderBase::CreateMaskedGather(Value *Ptrs, Align Alignment, |
| 527 | Value *Mask, Value *PassThru, |
| 528 | const Twine &Name) { |
Christopher Tetreault | 5a55e27 | 2020-08-27 10:39:18 -0700 | [diff] [blame] | 529 | auto *PtrsTy = cast<FixedVectorType>(Ptrs->getType()); |
| 530 | auto *PtrTy = cast<PointerType>(PtrsTy->getElementType()); |
Christopher Tetreault | 40ed21b | 2020-04-10 13:59:26 -0700 | [diff] [blame] | 531 | unsigned NumElts = PtrsTy->getNumElements(); |
Christopher Tetreault | 900f78a | 2020-06-03 13:35:41 -0700 | [diff] [blame] | 532 | auto *DataTy = FixedVectorType::get(PtrTy->getElementType(), NumElts); |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 533 | |
| 534 | if (!Mask) |
Christopher Tetreault | 900f78a | 2020-06-03 13:35:41 -0700 | [diff] [blame] | 535 | Mask = Constant::getAllOnesValue( |
| 536 | FixedVectorType::get(Type::getInt1Ty(Context), NumElts)); |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 537 | |
Amara Emerson | 4d33c86 | 2017-05-19 10:40:18 +0000 | [diff] [blame] | 538 | if (!PassThru) |
| 539 | PassThru = UndefValue::get(DataTy); |
| 540 | |
Elad Cohen | ef5798a | 2017-05-03 12:28:54 +0000 | [diff] [blame] | 541 | Type *OverloadedTypes[] = {DataTy, PtrsTy}; |
Guillaume Chatelet | d0a7cc7 | 2020-01-24 17:40:17 +0100 | [diff] [blame] | 542 | Value *Ops[] = {Ptrs, getInt32(Alignment.value()), Mask, PassThru}; |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 543 | |
| 544 | // We specify only one type when we create this intrinsic. Types of other |
| 545 | // arguments are derived from this type. |
Elad Cohen | ef5798a | 2017-05-03 12:28:54 +0000 | [diff] [blame] | 546 | return CreateMaskedIntrinsic(Intrinsic::masked_gather, Ops, OverloadedTypes, |
| 547 | Name); |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 548 | } |
| 549 | |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 550 | /// Create a call to a Masked Scatter intrinsic. |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 551 | /// \p Data - data to be stored, |
| 552 | /// \p Ptrs - the vector of pointers, where the \p Data elements should be |
| 553 | /// stored |
| 554 | /// \p Align - alignment for one element |
| 555 | /// \p Mask - vector of booleans which indicates what vector lanes should |
| 556 | /// be accessed in memory |
| 557 | CallInst *IRBuilderBase::CreateMaskedScatter(Value *Data, Value *Ptrs, |
Guillaume Chatelet | d0a7cc7 | 2020-01-24 17:40:17 +0100 | [diff] [blame] | 558 | Align Alignment, Value *Mask) { |
Christopher Tetreault | 5a55e27 | 2020-08-27 10:39:18 -0700 | [diff] [blame] | 559 | auto *PtrsTy = cast<FixedVectorType>(Ptrs->getType()); |
| 560 | auto *DataTy = cast<FixedVectorType>(Data->getType()); |
Christopher Tetreault | 40ed21b | 2020-04-10 13:59:26 -0700 | [diff] [blame] | 561 | unsigned NumElts = PtrsTy->getNumElements(); |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 562 | |
Tim Northover | 5a1a56c | 2016-02-17 21:16:59 +0000 | [diff] [blame] | 563 | #ifndef NDEBUG |
| 564 | auto PtrTy = cast<PointerType>(PtrsTy->getElementType()); |
Christopher Tetreault | 40ed21b | 2020-04-10 13:59:26 -0700 | [diff] [blame] | 565 | assert(NumElts == DataTy->getNumElements() && |
Tim Northover | 5a1a56c | 2016-02-17 21:16:59 +0000 | [diff] [blame] | 566 | PtrTy->getElementType() == DataTy->getElementType() && |
| 567 | "Incompatible pointer and data types"); |
| 568 | #endif |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 569 | |
| 570 | if (!Mask) |
Christopher Tetreault | 900f78a | 2020-06-03 13:35:41 -0700 | [diff] [blame] | 571 | Mask = Constant::getAllOnesValue( |
| 572 | FixedVectorType::get(Type::getInt1Ty(Context), NumElts)); |
Elad Cohen | ef5798a | 2017-05-03 12:28:54 +0000 | [diff] [blame] | 573 | |
| 574 | Type *OverloadedTypes[] = {DataTy, PtrsTy}; |
Guillaume Chatelet | d0a7cc7 | 2020-01-24 17:40:17 +0100 | [diff] [blame] | 575 | Value *Ops[] = {Data, Ptrs, getInt32(Alignment.value()), Mask}; |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 576 | |
| 577 | // We specify only one type when we create this intrinsic. Types of other |
| 578 | // arguments are derived from this type. |
Elad Cohen | ef5798a | 2017-05-03 12:28:54 +0000 | [diff] [blame] | 579 | return CreateMaskedIntrinsic(Intrinsic::masked_scatter, Ops, OverloadedTypes); |
Elena Demikhovsky | 88e76ca | 2016-02-17 19:23:04 +0000 | [diff] [blame] | 580 | } |
| 581 | |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 582 | template <typename T0> |
Sanjoy Das | a1d39ba | 2015-05-12 23:52:24 +0000 | [diff] [blame] | 583 | static std::vector<Value *> |
| 584 | getStatepointArgs(IRBuilderBase &B, uint64_t ID, uint32_t NumPatchBytes, |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 585 | Value *ActualCallee, uint32_t Flags, ArrayRef<T0> CallArgs) { |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 586 | std::vector<Value *> Args; |
Sanjoy Das | a1d39ba | 2015-05-12 23:52:24 +0000 | [diff] [blame] | 587 | Args.push_back(B.getInt64(ID)); |
| 588 | Args.push_back(B.getInt32(NumPatchBytes)); |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 589 | Args.push_back(ActualCallee); |
| 590 | Args.push_back(B.getInt32(CallArgs.size())); |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 591 | Args.push_back(B.getInt32(Flags)); |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 592 | Args.insert(Args.end(), CallArgs.begin(), CallArgs.end()); |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 593 | // GC Transition and Deopt args are now always handled via operand bundle. |
| 594 | // They will be removed from the signature of gc.statepoint shortly. |
| 595 | Args.push_back(B.getInt32(0)); |
| 596 | Args.push_back(B.getInt32(0)); |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 597 | // GC args are now encoded in the gc-live operand bundle |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 598 | return Args; |
| 599 | } |
| 600 | |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 601 | template<typename T1, typename T2, typename T3> |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 602 | static std::vector<OperandBundleDef> |
| 603 | getStatepointBundles(Optional<ArrayRef<T1>> TransitionArgs, |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 604 | Optional<ArrayRef<T2>> DeoptArgs, |
| 605 | ArrayRef<T3> GCArgs) { |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 606 | std::vector<OperandBundleDef> Rval; |
| 607 | if (DeoptArgs) { |
| 608 | SmallVector<Value*, 16> DeoptValues; |
| 609 | DeoptValues.insert(DeoptValues.end(), DeoptArgs->begin(), DeoptArgs->end()); |
| 610 | Rval.emplace_back("deopt", DeoptValues); |
| 611 | } |
| 612 | if (TransitionArgs) { |
| 613 | SmallVector<Value*, 16> TransitionValues; |
| 614 | TransitionValues.insert(TransitionValues.end(), |
| 615 | TransitionArgs->begin(), TransitionArgs->end()); |
| 616 | Rval.emplace_back("gc-transition", TransitionValues); |
| 617 | } |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 618 | if (GCArgs.size()) { |
| 619 | SmallVector<Value*, 16> LiveValues; |
| 620 | LiveValues.insert(LiveValues.end(), GCArgs.begin(), GCArgs.end()); |
| 621 | Rval.emplace_back("gc-live", LiveValues); |
| 622 | } |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 623 | return Rval; |
| 624 | } |
| 625 | |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 626 | template <typename T0, typename T1, typename T2, typename T3> |
| 627 | static CallInst *CreateGCStatepointCallCommon( |
| 628 | IRBuilderBase *Builder, uint64_t ID, uint32_t NumPatchBytes, |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 629 | Value *ActualCallee, uint32_t Flags, ArrayRef<T0> CallArgs, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 630 | Optional<ArrayRef<T1>> TransitionArgs, |
| 631 | Optional<ArrayRef<T2>> DeoptArgs, ArrayRef<T3> GCArgs, |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 632 | const Twine &Name) { |
Sanjoy Das | 63245b5 | 2015-05-06 02:36:34 +0000 | [diff] [blame] | 633 | // Extract out the type of the callee. |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 634 | auto *FuncPtrType = cast<PointerType>(ActualCallee->getType()); |
Sanjoy Das | 63245b5 | 2015-05-06 02:36:34 +0000 | [diff] [blame] | 635 | assert(isa<FunctionType>(FuncPtrType->getElementType()) && |
| 636 | "actual callee must be a callable value"); |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 637 | |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 638 | Module *M = Builder->GetInsertBlock()->getParent()->getParent(); |
Sanjoy Das | 63245b5 | 2015-05-06 02:36:34 +0000 | [diff] [blame] | 639 | // Fill in the one generic type'd argument (the function is also vararg) |
| 640 | Type *ArgTypes[] = { FuncPtrType }; |
| 641 | Function *FnStatepoint = |
| 642 | Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint, |
| 643 | ArgTypes); |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 644 | |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 645 | std::vector<Value *> Args = |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 646 | getStatepointArgs(*Builder, ID, NumPatchBytes, ActualCallee, Flags, |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 647 | CallArgs); |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 648 | |
| 649 | return Builder->CreateCall(FnStatepoint, Args, |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 650 | getStatepointBundles(TransitionArgs, DeoptArgs, |
| 651 | GCArgs), |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 652 | Name); |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 653 | } |
| 654 | |
| 655 | CallInst *IRBuilderBase::CreateGCStatepointCall( |
| 656 | uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 657 | ArrayRef<Value *> CallArgs, Optional<ArrayRef<Value *>> DeoptArgs, |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 658 | ArrayRef<Value *> GCArgs, const Twine &Name) { |
| 659 | return CreateGCStatepointCallCommon<Value *, Value *, Value *, Value *>( |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 660 | this, ID, NumPatchBytes, ActualCallee, uint32_t(StatepointFlags::None), |
| 661 | CallArgs, None /* No Transition Args */, DeoptArgs, GCArgs, Name); |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 662 | } |
| 663 | |
| 664 | CallInst *IRBuilderBase::CreateGCStatepointCall( |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 665 | uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, uint32_t Flags, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 666 | ArrayRef<Use> CallArgs, Optional<ArrayRef<Use>> TransitionArgs, |
| 667 | Optional<ArrayRef<Use>> DeoptArgs, ArrayRef<Value *> GCArgs, |
| 668 | const Twine &Name) { |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 669 | return CreateGCStatepointCallCommon<Use, Use, Use, Value *>( |
| 670 | this, ID, NumPatchBytes, ActualCallee, Flags, CallArgs, TransitionArgs, |
| 671 | DeoptArgs, GCArgs, Name); |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 672 | } |
| 673 | |
Sanjoy Das | a1d39ba | 2015-05-12 23:52:24 +0000 | [diff] [blame] | 674 | CallInst *IRBuilderBase::CreateGCStatepointCall( |
| 675 | uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 676 | ArrayRef<Use> CallArgs, Optional<ArrayRef<Value *>> DeoptArgs, |
Sanjoy Das | a1d39ba | 2015-05-12 23:52:24 +0000 | [diff] [blame] | 677 | ArrayRef<Value *> GCArgs, const Twine &Name) { |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 678 | return CreateGCStatepointCallCommon<Use, Value *, Value *, Value *>( |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 679 | this, ID, NumPatchBytes, ActualCallee, uint32_t(StatepointFlags::None), |
| 680 | CallArgs, None, DeoptArgs, GCArgs, Name); |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 681 | } |
| 682 | |
| 683 | template <typename T0, typename T1, typename T2, typename T3> |
| 684 | static InvokeInst *CreateGCStatepointInvokeCommon( |
| 685 | IRBuilderBase *Builder, uint64_t ID, uint32_t NumPatchBytes, |
| 686 | Value *ActualInvokee, BasicBlock *NormalDest, BasicBlock *UnwindDest, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 687 | uint32_t Flags, ArrayRef<T0> InvokeArgs, |
| 688 | Optional<ArrayRef<T1>> TransitionArgs, Optional<ArrayRef<T2>> DeoptArgs, |
| 689 | ArrayRef<T3> GCArgs, const Twine &Name) { |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 690 | // Extract out the type of the callee. |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 691 | auto *FuncPtrType = cast<PointerType>(ActualInvokee->getType()); |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 692 | assert(isa<FunctionType>(FuncPtrType->getElementType()) && |
| 693 | "actual callee must be a callable value"); |
| 694 | |
| 695 | Module *M = Builder->GetInsertBlock()->getParent()->getParent(); |
| 696 | // Fill in the one generic type'd argument (the function is also vararg) |
| 697 | Function *FnStatepoint = Intrinsic::getDeclaration( |
| 698 | M, Intrinsic::experimental_gc_statepoint, {FuncPtrType}); |
| 699 | |
Eugene Zelenko | 7fb5d41 | 2018-03-30 00:47:31 +0000 | [diff] [blame] | 700 | std::vector<Value *> Args = |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 701 | getStatepointArgs(*Builder, ID, NumPatchBytes, ActualInvokee, Flags, |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 702 | InvokeArgs); |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 703 | |
Nikita Popov | f6875c4 | 2020-02-18 20:35:16 +0100 | [diff] [blame] | 704 | return Builder->CreateInvoke(FnStatepoint, NormalDest, UnwindDest, Args, |
Philip Reames | 3d40c75 | 2020-06-04 15:22:07 -0700 | [diff] [blame] | 705 | getStatepointBundles(TransitionArgs, DeoptArgs, |
| 706 | GCArgs), |
Nikita Popov | f6875c4 | 2020-02-18 20:35:16 +0100 | [diff] [blame] | 707 | Name); |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 708 | } |
| 709 | |
| 710 | InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( |
Sanjoy Das | a1d39ba | 2015-05-12 23:52:24 +0000 | [diff] [blame] | 711 | uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, |
| 712 | BasicBlock *NormalDest, BasicBlock *UnwindDest, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 713 | ArrayRef<Value *> InvokeArgs, Optional<ArrayRef<Value *>> DeoptArgs, |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 714 | ArrayRef<Value *> GCArgs, const Twine &Name) { |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 715 | return CreateGCStatepointInvokeCommon<Value *, Value *, Value *, Value *>( |
| 716 | this, ID, NumPatchBytes, ActualInvokee, NormalDest, UnwindDest, |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 717 | uint32_t(StatepointFlags::None), InvokeArgs, None /* No Transition Args*/, |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 718 | DeoptArgs, GCArgs, Name); |
| 719 | } |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 720 | |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 721 | InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( |
| 722 | uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 723 | BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 724 | ArrayRef<Use> InvokeArgs, Optional<ArrayRef<Use>> TransitionArgs, |
| 725 | Optional<ArrayRef<Use>> DeoptArgs, ArrayRef<Value *> GCArgs, const Twine &Name) { |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 726 | return CreateGCStatepointInvokeCommon<Use, Use, Use, Value *>( |
| 727 | this, ID, NumPatchBytes, ActualInvokee, NormalDest, UnwindDest, Flags, |
| 728 | InvokeArgs, TransitionArgs, DeoptArgs, GCArgs, Name); |
Sanjoy Das | abe1c68 | 2015-05-06 23:53:09 +0000 | [diff] [blame] | 729 | } |
| 730 | |
| 731 | InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( |
Sanjoy Das | a1d39ba | 2015-05-12 23:52:24 +0000 | [diff] [blame] | 732 | uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, |
| 733 | BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs, |
Philip Reames | 587fa99 | 2020-05-28 10:11:08 -0700 | [diff] [blame] | 734 | Optional<ArrayRef<Value *>> DeoptArgs, ArrayRef<Value *> GCArgs, const Twine &Name) { |
Sanjoy Das | af6980c | 2015-10-07 19:52:12 +0000 | [diff] [blame] | 735 | return CreateGCStatepointInvokeCommon<Use, Value *, Value *, Value *>( |
| 736 | this, ID, NumPatchBytes, ActualInvokee, NormalDest, UnwindDest, |
Sanjoy Das | 4fd3d40 | 2015-10-08 23:18:33 +0000 | [diff] [blame] | 737 | uint32_t(StatepointFlags::None), InvokeArgs, None, DeoptArgs, GCArgs, |
| 738 | Name); |
Ramkumar Ramachandra | 3408f3e | 2015-02-26 00:35:56 +0000 | [diff] [blame] | 739 | } |
| 740 | |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 741 | CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint, |
| 742 | Type *ResultType, |
| 743 | const Twine &Name) { |
Ramkumar Ramachandra | 75a4f35 | 2015-01-22 20:14:38 +0000 | [diff] [blame] | 744 | Intrinsic::ID ID = Intrinsic::experimental_gc_result; |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 745 | Module *M = BB->getParent()->getParent(); |
| 746 | Type *Types[] = {ResultType}; |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 747 | Function *FnGCResult = Intrinsic::getDeclaration(M, ID, Types); |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 748 | |
| 749 | Value *Args[] = {Statepoint}; |
| 750 | return createCallHelper(FnGCResult, Args, this, Name); |
| 751 | } |
| 752 | |
| 753 | CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint, |
| 754 | int BaseOffset, |
| 755 | int DerivedOffset, |
| 756 | Type *ResultType, |
| 757 | const Twine &Name) { |
| 758 | Module *M = BB->getParent()->getParent(); |
| 759 | Type *Types[] = {ResultType}; |
James Y Knight | 7976eb5 | 2019-02-01 20:43:25 +0000 | [diff] [blame] | 760 | Function *FnGCRelocate = |
| 761 | Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_relocate, Types); |
Philip Reames | 4750dd1 | 2014-12-30 05:55:58 +0000 | [diff] [blame] | 762 | |
| 763 | Value *Args[] = {Statepoint, |
| 764 | getInt32(BaseOffset), |
| 765 | getInt32(DerivedOffset)}; |
| 766 | return createCallHelper(FnGCRelocate, Args, this, Name); |
| 767 | } |
Matt Arsenault | cdb468c | 2017-02-27 23:08:49 +0000 | [diff] [blame] | 768 | |
Neil Henning | 57f5d0a | 2018-10-08 10:32:33 +0000 | [diff] [blame] | 769 | CallInst *IRBuilderBase::CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V, |
| 770 | Instruction *FMFSource, |
| 771 | const Twine &Name) { |
| 772 | Module *M = BB->getModule(); |
| 773 | Function *Fn = Intrinsic::getDeclaration(M, ID, {V->getType()}); |
| 774 | return createCallHelper(Fn, {V}, this, Name, FMFSource); |
| 775 | } |
| 776 | |
| 777 | CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, |
| 778 | Value *RHS, |
| 779 | Instruction *FMFSource, |
Matt Arsenault | cdb468c | 2017-02-27 23:08:49 +0000 | [diff] [blame] | 780 | const Twine &Name) { |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 781 | Module *M = BB->getModule(); |
| 782 | Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() }); |
Neil Henning | 57f5d0a | 2018-10-08 10:32:33 +0000 | [diff] [blame] | 783 | return createCallHelper(Fn, {LHS, RHS}, this, Name, FMFSource); |
Matt Arsenault | cdb468c | 2017-02-27 23:08:49 +0000 | [diff] [blame] | 784 | } |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 785 | |
| 786 | CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID, |
Neil Henning | 57f5d0a | 2018-10-08 10:32:33 +0000 | [diff] [blame] | 787 | ArrayRef<Type *> Types, |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 788 | ArrayRef<Value *> Args, |
| 789 | Instruction *FMFSource, |
| 790 | const Twine &Name) { |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 791 | Module *M = BB->getModule(); |
Neil Henning | 57f5d0a | 2018-10-08 10:32:33 +0000 | [diff] [blame] | 792 | Function *Fn = Intrinsic::getDeclaration(M, ID, Types); |
Sanjay Patel | d32104e | 2018-02-23 21:16:12 +0000 | [diff] [blame] | 793 | return createCallHelper(Fn, Args, this, Name, FMFSource); |
| 794 | } |
Nikita Popov | 3eaa53e | 2020-02-16 17:10:09 +0100 | [diff] [blame] | 795 | |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 796 | CallInst *IRBuilderBase::CreateConstrainedFPBinOp( |
| 797 | Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource, |
| 798 | const Twine &Name, MDNode *FPMathTag, |
Serge Pavlov | c7ff5b3 | 2020-03-26 14:51:09 +0700 | [diff] [blame] | 799 | Optional<RoundingMode> Rounding, |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 800 | Optional<fp::ExceptionBehavior> Except) { |
| 801 | Value *RoundingV = getConstrainedFPRounding(Rounding); |
| 802 | Value *ExceptV = getConstrainedFPExcept(Except); |
| 803 | |
| 804 | FastMathFlags UseFMF = FMF; |
| 805 | if (FMFSource) |
| 806 | UseFMF = FMFSource->getFastMathFlags(); |
| 807 | |
| 808 | CallInst *C = CreateIntrinsic(ID, {L->getType()}, |
| 809 | {L, R, RoundingV, ExceptV}, nullptr, Name); |
| 810 | setConstrainedFPCallAttr(C); |
| 811 | setFPAttrs(C, FPMathTag, UseFMF); |
| 812 | return C; |
| 813 | } |
| 814 | |
| 815 | Value *IRBuilderBase::CreateNAryOp(unsigned Opc, ArrayRef<Value *> Ops, |
| 816 | const Twine &Name, MDNode *FPMathTag) { |
| 817 | if (Instruction::isBinaryOp(Opc)) { |
| 818 | assert(Ops.size() == 2 && "Invalid number of operands!"); |
| 819 | return CreateBinOp(static_cast<Instruction::BinaryOps>(Opc), |
| 820 | Ops[0], Ops[1], Name, FPMathTag); |
| 821 | } |
| 822 | if (Instruction::isUnaryOp(Opc)) { |
| 823 | assert(Ops.size() == 1 && "Invalid number of operands!"); |
| 824 | return CreateUnOp(static_cast<Instruction::UnaryOps>(Opc), |
| 825 | Ops[0], Name, FPMathTag); |
| 826 | } |
| 827 | llvm_unreachable("Unexpected opcode!"); |
| 828 | } |
| 829 | |
| 830 | CallInst *IRBuilderBase::CreateConstrainedFPCast( |
| 831 | Intrinsic::ID ID, Value *V, Type *DestTy, |
| 832 | Instruction *FMFSource, const Twine &Name, MDNode *FPMathTag, |
Serge Pavlov | c7ff5b3 | 2020-03-26 14:51:09 +0700 | [diff] [blame] | 833 | Optional<RoundingMode> Rounding, |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 834 | Optional<fp::ExceptionBehavior> Except) { |
| 835 | Value *ExceptV = getConstrainedFPExcept(Except); |
| 836 | |
| 837 | FastMathFlags UseFMF = FMF; |
| 838 | if (FMFSource) |
| 839 | UseFMF = FMFSource->getFastMathFlags(); |
| 840 | |
| 841 | CallInst *C; |
| 842 | bool HasRoundingMD = false; |
| 843 | switch (ID) { |
| 844 | default: |
| 845 | break; |
| 846 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ |
| 847 | case Intrinsic::INTRINSIC: \ |
| 848 | HasRoundingMD = ROUND_MODE; \ |
| 849 | break; |
| 850 | #include "llvm/IR/ConstrainedOps.def" |
| 851 | } |
| 852 | if (HasRoundingMD) { |
| 853 | Value *RoundingV = getConstrainedFPRounding(Rounding); |
| 854 | C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV}, |
| 855 | nullptr, Name); |
| 856 | } else |
| 857 | C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, ExceptV}, nullptr, |
| 858 | Name); |
| 859 | |
| 860 | setConstrainedFPCallAttr(C); |
| 861 | |
| 862 | if (isa<FPMathOperator>(C)) |
| 863 | setFPAttrs(C, FPMathTag, UseFMF); |
| 864 | return C; |
| 865 | } |
| 866 | |
| 867 | Value *IRBuilderBase::CreateFCmpHelper( |
| 868 | CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name, |
| 869 | MDNode *FPMathTag, bool IsSignaling) { |
| 870 | if (IsFPConstrained) { |
| 871 | auto ID = IsSignaling ? Intrinsic::experimental_constrained_fcmps |
| 872 | : Intrinsic::experimental_constrained_fcmp; |
| 873 | return CreateConstrainedFPCmp(ID, P, LHS, RHS, Name); |
| 874 | } |
| 875 | |
| 876 | if (auto *LC = dyn_cast<Constant>(LHS)) |
| 877 | if (auto *RC = dyn_cast<Constant>(RHS)) |
| 878 | return Insert(Folder.CreateFCmp(P, LC, RC), Name); |
| 879 | return Insert(setFPAttrs(new FCmpInst(P, LHS, RHS), FPMathTag, FMF), Name); |
| 880 | } |
| 881 | |
| 882 | CallInst *IRBuilderBase::CreateConstrainedFPCmp( |
| 883 | Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R, |
| 884 | const Twine &Name, Optional<fp::ExceptionBehavior> Except) { |
| 885 | Value *PredicateV = getConstrainedFPPredicate(P); |
| 886 | Value *ExceptV = getConstrainedFPExcept(Except); |
| 887 | |
| 888 | CallInst *C = CreateIntrinsic(ID, {L->getType()}, |
| 889 | {L, R, PredicateV, ExceptV}, nullptr, Name); |
| 890 | setConstrainedFPCallAttr(C); |
| 891 | return C; |
| 892 | } |
| 893 | |
| 894 | CallInst *IRBuilderBase::CreateConstrainedFPCall( |
| 895 | Function *Callee, ArrayRef<Value *> Args, const Twine &Name, |
Serge Pavlov | c7ff5b3 | 2020-03-26 14:51:09 +0700 | [diff] [blame] | 896 | Optional<RoundingMode> Rounding, |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 897 | Optional<fp::ExceptionBehavior> Except) { |
| 898 | llvm::SmallVector<Value *, 6> UseArgs; |
| 899 | |
| 900 | for (auto *OneArg : Args) |
| 901 | UseArgs.push_back(OneArg); |
| 902 | bool HasRoundingMD = false; |
| 903 | switch (Callee->getIntrinsicID()) { |
| 904 | default: |
| 905 | break; |
| 906 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ |
| 907 | case Intrinsic::INTRINSIC: \ |
| 908 | HasRoundingMD = ROUND_MODE; \ |
| 909 | break; |
| 910 | #include "llvm/IR/ConstrainedOps.def" |
| 911 | } |
| 912 | if (HasRoundingMD) |
| 913 | UseArgs.push_back(getConstrainedFPRounding(Rounding)); |
| 914 | UseArgs.push_back(getConstrainedFPExcept(Except)); |
| 915 | |
| 916 | CallInst *C = CreateCall(Callee, UseArgs, Name); |
| 917 | setConstrainedFPCallAttr(C); |
| 918 | return C; |
| 919 | } |
| 920 | |
| 921 | Value *IRBuilderBase::CreateSelect(Value *C, Value *True, Value *False, |
| 922 | const Twine &Name, Instruction *MDFrom) { |
| 923 | if (auto *CC = dyn_cast<Constant>(C)) |
| 924 | if (auto *TC = dyn_cast<Constant>(True)) |
| 925 | if (auto *FC = dyn_cast<Constant>(False)) |
| 926 | return Insert(Folder.CreateSelect(CC, TC, FC), Name); |
| 927 | |
| 928 | SelectInst *Sel = SelectInst::Create(C, True, False); |
| 929 | if (MDFrom) { |
| 930 | MDNode *Prof = MDFrom->getMetadata(LLVMContext::MD_prof); |
| 931 | MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable); |
| 932 | Sel = addBranchMetadata(Sel, Prof, Unpred); |
| 933 | } |
| 934 | if (isa<FPMathOperator>(Sel)) |
| 935 | setFPAttrs(Sel, nullptr /* MDNode* */, FMF); |
| 936 | return Insert(Sel, Name); |
| 937 | } |
| 938 | |
| 939 | Value *IRBuilderBase::CreatePtrDiff(Value *LHS, Value *RHS, |
| 940 | const Twine &Name) { |
| 941 | assert(LHS->getType() == RHS->getType() && |
| 942 | "Pointer subtraction operand types must match!"); |
| 943 | auto *ArgType = cast<PointerType>(LHS->getType()); |
| 944 | Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); |
| 945 | Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); |
| 946 | Value *Difference = CreateSub(LHS_int, RHS_int); |
| 947 | return CreateExactSDiv(Difference, |
| 948 | ConstantExpr::getSizeOf(ArgType->getElementType()), |
| 949 | Name); |
| 950 | } |
| 951 | |
| 952 | Value *IRBuilderBase::CreateLaunderInvariantGroup(Value *Ptr) { |
| 953 | assert(isa<PointerType>(Ptr->getType()) && |
| 954 | "launder.invariant.group only applies to pointers."); |
| 955 | // FIXME: we could potentially avoid casts to/from i8*. |
| 956 | auto *PtrType = Ptr->getType(); |
| 957 | auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); |
| 958 | if (PtrType != Int8PtrTy) |
| 959 | Ptr = CreateBitCast(Ptr, Int8PtrTy); |
| 960 | Module *M = BB->getParent()->getParent(); |
| 961 | Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration( |
| 962 | M, Intrinsic::launder_invariant_group, {Int8PtrTy}); |
| 963 | |
| 964 | assert(FnLaunderInvariantGroup->getReturnType() == Int8PtrTy && |
| 965 | FnLaunderInvariantGroup->getFunctionType()->getParamType(0) == |
| 966 | Int8PtrTy && |
| 967 | "LaunderInvariantGroup should take and return the same type"); |
| 968 | |
| 969 | CallInst *Fn = CreateCall(FnLaunderInvariantGroup, {Ptr}); |
| 970 | |
| 971 | if (PtrType != Int8PtrTy) |
| 972 | return CreateBitCast(Fn, PtrType); |
| 973 | return Fn; |
| 974 | } |
| 975 | |
| 976 | Value *IRBuilderBase::CreateStripInvariantGroup(Value *Ptr) { |
| 977 | assert(isa<PointerType>(Ptr->getType()) && |
| 978 | "strip.invariant.group only applies to pointers."); |
| 979 | |
| 980 | // FIXME: we could potentially avoid casts to/from i8*. |
| 981 | auto *PtrType = Ptr->getType(); |
| 982 | auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); |
| 983 | if (PtrType != Int8PtrTy) |
| 984 | Ptr = CreateBitCast(Ptr, Int8PtrTy); |
| 985 | Module *M = BB->getParent()->getParent(); |
| 986 | Function *FnStripInvariantGroup = Intrinsic::getDeclaration( |
| 987 | M, Intrinsic::strip_invariant_group, {Int8PtrTy}); |
| 988 | |
| 989 | assert(FnStripInvariantGroup->getReturnType() == Int8PtrTy && |
| 990 | FnStripInvariantGroup->getFunctionType()->getParamType(0) == |
| 991 | Int8PtrTy && |
| 992 | "StripInvariantGroup should take and return the same type"); |
| 993 | |
| 994 | CallInst *Fn = CreateCall(FnStripInvariantGroup, {Ptr}); |
| 995 | |
| 996 | if (PtrType != Int8PtrTy) |
| 997 | return CreateBitCast(Fn, PtrType); |
| 998 | return Fn; |
| 999 | } |
| 1000 | |
| 1001 | Value *IRBuilderBase::CreateVectorSplat(unsigned NumElts, Value *V, |
| 1002 | const Twine &Name) { |
Mehdi Amini | a407ec9 | 2020-08-19 17:26:36 +0000 | [diff] [blame] | 1003 | auto EC = ElementCount::getFixed(NumElts); |
Simon Pilgrim | e202236 | 2020-08-02 16:55:16 +0100 | [diff] [blame] | 1004 | return CreateVectorSplat(EC, V, Name); |
| 1005 | } |
| 1006 | |
| 1007 | Value *IRBuilderBase::CreateVectorSplat(ElementCount EC, Value *V, |
| 1008 | const Twine &Name) { |
David Sherwood | f4257c5 | 2020-08-14 12:15:59 +0100 | [diff] [blame] | 1009 | assert(EC.isNonZero() && "Cannot splat to an empty vector!"); |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1010 | |
| 1011 | // First insert it into an undef vector so we can shuffle it. |
| 1012 | Type *I32Ty = getInt32Ty(); |
Simon Pilgrim | e202236 | 2020-08-02 16:55:16 +0100 | [diff] [blame] | 1013 | Value *Undef = UndefValue::get(VectorType::get(V->getType(), EC)); |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1014 | V = CreateInsertElement(Undef, V, ConstantInt::get(I32Ty, 0), |
| 1015 | Name + ".splatinsert"); |
| 1016 | |
| 1017 | // Shuffle the value across the desired number of elements. |
Simon Pilgrim | e202236 | 2020-08-02 16:55:16 +0100 | [diff] [blame] | 1018 | Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, EC)); |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1019 | return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); |
| 1020 | } |
| 1021 | |
| 1022 | Value *IRBuilderBase::CreateExtractInteger( |
| 1023 | const DataLayout &DL, Value *From, IntegerType *ExtractedTy, |
| 1024 | uint64_t Offset, const Twine &Name) { |
| 1025 | auto *IntTy = cast<IntegerType>(From->getType()); |
| 1026 | assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= |
| 1027 | DL.getTypeStoreSize(IntTy) && |
| 1028 | "Element extends past full value"); |
| 1029 | uint64_t ShAmt = 8 * Offset; |
| 1030 | Value *V = From; |
| 1031 | if (DL.isBigEndian()) |
| 1032 | ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - |
| 1033 | DL.getTypeStoreSize(ExtractedTy) - Offset); |
| 1034 | if (ShAmt) { |
| 1035 | V = CreateLShr(V, ShAmt, Name + ".shift"); |
| 1036 | } |
| 1037 | assert(ExtractedTy->getBitWidth() <= IntTy->getBitWidth() && |
| 1038 | "Cannot extract to a larger integer!"); |
| 1039 | if (ExtractedTy != IntTy) { |
| 1040 | V = CreateTrunc(V, ExtractedTy, Name + ".trunc"); |
| 1041 | } |
| 1042 | return V; |
| 1043 | } |
| 1044 | |
| 1045 | Value *IRBuilderBase::CreatePreserveArrayAccessIndex( |
| 1046 | Type *ElTy, Value *Base, unsigned Dimension, unsigned LastIndex, |
| 1047 | MDNode *DbgInfo) { |
| 1048 | assert(isa<PointerType>(Base->getType()) && |
| 1049 | "Invalid Base ptr type for preserve.array.access.index."); |
| 1050 | auto *BaseType = Base->getType(); |
| 1051 | |
| 1052 | Value *LastIndexV = getInt32(LastIndex); |
| 1053 | Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); |
| 1054 | SmallVector<Value *, 4> IdxList; |
| 1055 | for (unsigned I = 0; I < Dimension; ++I) |
| 1056 | IdxList.push_back(Zero); |
| 1057 | IdxList.push_back(LastIndexV); |
| 1058 | |
| 1059 | Type *ResultType = |
| 1060 | GetElementPtrInst::getGEPReturnType(ElTy, Base, IdxList); |
| 1061 | |
| 1062 | Module *M = BB->getParent()->getParent(); |
| 1063 | Function *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration( |
| 1064 | M, Intrinsic::preserve_array_access_index, {ResultType, BaseType}); |
| 1065 | |
| 1066 | Value *DimV = getInt32(Dimension); |
| 1067 | CallInst *Fn = |
| 1068 | CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); |
| 1069 | if (DbgInfo) |
| 1070 | Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); |
| 1071 | |
| 1072 | return Fn; |
| 1073 | } |
| 1074 | |
| 1075 | Value *IRBuilderBase::CreatePreserveUnionAccessIndex( |
| 1076 | Value *Base, unsigned FieldIndex, MDNode *DbgInfo) { |
| 1077 | assert(isa<PointerType>(Base->getType()) && |
| 1078 | "Invalid Base ptr type for preserve.union.access.index."); |
| 1079 | auto *BaseType = Base->getType(); |
| 1080 | |
| 1081 | Module *M = BB->getParent()->getParent(); |
| 1082 | Function *FnPreserveUnionAccessIndex = Intrinsic::getDeclaration( |
| 1083 | M, Intrinsic::preserve_union_access_index, {BaseType, BaseType}); |
| 1084 | |
| 1085 | Value *DIIndex = getInt32(FieldIndex); |
| 1086 | CallInst *Fn = |
| 1087 | CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex}); |
| 1088 | if (DbgInfo) |
| 1089 | Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); |
| 1090 | |
| 1091 | return Fn; |
| 1092 | } |
| 1093 | |
| 1094 | Value *IRBuilderBase::CreatePreserveStructAccessIndex( |
| 1095 | Type *ElTy, Value *Base, unsigned Index, unsigned FieldIndex, |
| 1096 | MDNode *DbgInfo) { |
| 1097 | assert(isa<PointerType>(Base->getType()) && |
| 1098 | "Invalid Base ptr type for preserve.struct.access.index."); |
| 1099 | auto *BaseType = Base->getType(); |
| 1100 | |
| 1101 | Value *GEPIndex = getInt32(Index); |
| 1102 | Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); |
| 1103 | Type *ResultType = |
| 1104 | GetElementPtrInst::getGEPReturnType(ElTy, Base, {Zero, GEPIndex}); |
| 1105 | |
| 1106 | Module *M = BB->getParent()->getParent(); |
| 1107 | Function *FnPreserveStructAccessIndex = Intrinsic::getDeclaration( |
| 1108 | M, Intrinsic::preserve_struct_access_index, {ResultType, BaseType}); |
| 1109 | |
| 1110 | Value *DIIndex = getInt32(FieldIndex); |
| 1111 | CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, |
| 1112 | {Base, GEPIndex, DIIndex}); |
| 1113 | if (DbgInfo) |
| 1114 | Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); |
| 1115 | |
| 1116 | return Fn; |
| 1117 | } |
| 1118 | |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 1119 | CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper(const DataLayout &DL, |
| 1120 | Value *PtrValue, |
| 1121 | Value *AlignValue, |
| 1122 | Value *OffsetValue) { |
| 1123 | SmallVector<Value *, 4> Vals({PtrValue, AlignValue}); |
| 1124 | if (OffsetValue) |
| 1125 | Vals.push_back(OffsetValue); |
| 1126 | OperandBundleDefT<Value *> AlignOpB("align", Vals); |
| 1127 | return CreateAssumption(ConstantInt::getTrue(getContext()), {AlignOpB}); |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1128 | } |
| 1129 | |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 1130 | CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, |
| 1131 | Value *PtrValue, |
| 1132 | unsigned Alignment, |
| 1133 | Value *OffsetValue) { |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1134 | assert(isa<PointerType>(PtrValue->getType()) && |
| 1135 | "trying to create an alignment assumption on a non-pointer?"); |
| 1136 | assert(Alignment != 0 && "Invalid Alignment"); |
| 1137 | auto *PtrTy = cast<PointerType>(PtrValue->getType()); |
| 1138 | Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 1139 | Value *AlignValue = ConstantInt::get(IntPtrTy, Alignment); |
| 1140 | return CreateAlignmentAssumptionHelper(DL, PtrValue, AlignValue, OffsetValue); |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1141 | } |
| 1142 | |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 1143 | CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, |
| 1144 | Value *PtrValue, |
| 1145 | Value *Alignment, |
| 1146 | Value *OffsetValue) { |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1147 | assert(isa<PointerType>(PtrValue->getType()) && |
| 1148 | "trying to create an alignment assumption on a non-pointer?"); |
Tyker | 78de729 | 2020-09-12 13:36:45 +0200 | [diff] [blame] | 1149 | return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue); |
Nikita Popov | b90ea4f | 2020-04-02 21:35:24 +0200 | [diff] [blame] | 1150 | } |
| 1151 | |
Nikita Popov | 3eaa53e | 2020-02-16 17:10:09 +0100 | [diff] [blame] | 1152 | IRBuilderDefaultInserter::~IRBuilderDefaultInserter() {} |
| 1153 | IRBuilderCallbackInserter::~IRBuilderCallbackInserter() {} |
| 1154 | IRBuilderFolder::~IRBuilderFolder() {} |
| 1155 | void ConstantFolder::anchor() {} |
| 1156 | void NoFolder::anchor() {} |