1 //===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===// 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 implements methods that make it really easy to deal with intrinsic 10 // functions. 11 // 12 // All intrinsic function calls are instances of the call instruction, so these 13 // are all subclasses of the CallInst class. Note that none of these classes 14 // has state or virtual methods, which is an important part of this gross/neat 15 // hack working. 16 // 17 // In some cases, arguments to intrinsics need to be generic and are defined as 18 // type pointer to empty struct { }*. To access the real item of interest the 19 // cast instruction needs to be stripped away. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "llvm/IR/IntrinsicInst.h" 24 #include "llvm/ADT/StringSwitch.h" 25 #include "llvm/IR/Constants.h" 26 #include "llvm/IR/DebugInfoMetadata.h" 27 #include "llvm/IR/GlobalVariable.h" 28 #include "llvm/IR/Metadata.h" 29 #include "llvm/IR/Module.h" 30 #include "llvm/IR/Operator.h" 31 #include "llvm/IR/PatternMatch.h" 32 33 #include "llvm/Support/raw_ostream.h" 34 using namespace llvm; 35 36 //===----------------------------------------------------------------------===// 37 /// DbgVariableIntrinsic - This is the common base class for debug info 38 /// intrinsics for variables. 39 /// 40 41 Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const { 42 Value *Op = getArgOperand(0); 43 if (AllowNullOp && !Op) 44 return nullptr; 45 46 auto *MD = cast<MetadataAsValue>(Op)->getMetadata(); 47 if (auto *V = dyn_cast<ValueAsMetadata>(MD)) 48 return V->getValue(); 49 50 // When the value goes to null, it gets replaced by an empty MDNode. 51 assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode"); 52 return nullptr; 53 } 54 55 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const { 56 if (auto Fragment = getExpression()->getFragmentInfo()) 57 return Fragment->SizeInBits; 58 return getVariable()->getSizeInBits(); 59 } 60 61 int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable, 62 StringRef Name) { 63 assert(Name.startswith("llvm.")); 64 65 // Do successive binary searches of the dotted name components. For 66 // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of 67 // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then 68 // "llvm.gc.experimental.statepoint", and then we will stop as the range is 69 // size 1. During the search, we can skip the prefix that we already know is 70 // identical. By using strncmp we consider names with differing suffixes to 71 // be part of the equal range. 72 size_t CmpEnd = 4; // Skip the "llvm" component. 73 const char *const *Low = NameTable.begin(); 74 const char *const *High = NameTable.end(); 75 const char *const *LastLow = Low; 76 while (CmpEnd < Name.size() && High - Low > 0) { 77 size_t CmpStart = CmpEnd; 78 CmpEnd = Name.find('.', CmpStart + 1); 79 CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd; 80 auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) { 81 return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0; 82 }; 83 LastLow = Low; 84 std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp); 85 } 86 if (High - Low > 0) 87 LastLow = Low; 88 89 if (LastLow == NameTable.end()) 90 return -1; 91 StringRef NameFound = *LastLow; 92 if (Name == NameFound || 93 (Name.startswith(NameFound) && Name[NameFound.size()] == '.')) 94 return LastLow - NameTable.begin(); 95 return -1; 96 } 97 98 Value *InstrProfIncrementInst::getStep() const { 99 if (InstrProfIncrementInstStep::classof(this)) { 100 return const_cast<Value *>(getArgOperand(4)); 101 } 102 const Module *M = getModule(); 103 LLVMContext &Context = M->getContext(); 104 return ConstantInt::get(Type::getInt64Ty(Context), 1); 105 } 106 107 Optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const { 108 unsigned NumOperands = getNumArgOperands(); 109 Metadata *MD = 110 cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata(); 111 if (!MD || !isa<MDString>(MD)) 112 return None; 113 return StrToRoundingMode(cast<MDString>(MD)->getString()); 114 } 115 116 Optional<fp::ExceptionBehavior> 117 ConstrainedFPIntrinsic::getExceptionBehavior() const { 118 unsigned NumOperands = getNumArgOperands(); 119 Metadata *MD = 120 cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata(); 121 if (!MD || !isa<MDString>(MD)) 122 return None; 123 return StrToExceptionBehavior(cast<MDString>(MD)->getString()); 124 } 125 126 FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const { 127 Metadata *MD = cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); 128 if (!MD || !isa<MDString>(MD)) 129 return FCmpInst::BAD_FCMP_PREDICATE; 130 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString()) 131 .Case("oeq", FCmpInst::FCMP_OEQ) 132 .Case("ogt", FCmpInst::FCMP_OGT) 133 .Case("oge", FCmpInst::FCMP_OGE) 134 .Case("olt", FCmpInst::FCMP_OLT) 135 .Case("ole", FCmpInst::FCMP_OLE) 136 .Case("one", FCmpInst::FCMP_ONE) 137 .Case("ord", FCmpInst::FCMP_ORD) 138 .Case("uno", FCmpInst::FCMP_UNO) 139 .Case("ueq", FCmpInst::FCMP_UEQ) 140 .Case("ugt", FCmpInst::FCMP_UGT) 141 .Case("uge", FCmpInst::FCMP_UGE) 142 .Case("ult", FCmpInst::FCMP_ULT) 143 .Case("ule", FCmpInst::FCMP_ULE) 144 .Case("une", FCmpInst::FCMP_UNE) 145 .Default(FCmpInst::BAD_FCMP_PREDICATE); 146 } 147 148 bool ConstrainedFPIntrinsic::isUnaryOp() const { 149 switch (getIntrinsicID()) { 150 default: 151 return false; 152 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 153 case Intrinsic::INTRINSIC: \ 154 return NARG == 1; 155 #include "llvm/IR/ConstrainedOps.def" 156 } 157 } 158 159 bool ConstrainedFPIntrinsic::isTernaryOp() const { 160 switch (getIntrinsicID()) { 161 default: 162 return false; 163 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 164 case Intrinsic::INTRINSIC: \ 165 return NARG == 3; 166 #include "llvm/IR/ConstrainedOps.def" 167 } 168 } 169 170 bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) { 171 switch (I->getIntrinsicID()) { 172 #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ 173 case Intrinsic::INTRINSIC: 174 #include "llvm/IR/ConstrainedOps.def" 175 return true; 176 default: 177 return false; 178 } 179 } 180 181 ElementCount VPIntrinsic::getStaticVectorLength() const { 182 auto GetVectorLengthOfType = [](const Type *T) -> ElementCount { 183 auto VT = cast<VectorType>(T); 184 auto ElemCount = VT->getElementCount(); 185 return ElemCount; 186 }; 187 188 auto VPMask = getMaskParam(); 189 return GetVectorLengthOfType(VPMask->getType()); 190 } 191 192 Value *VPIntrinsic::getMaskParam() const { 193 auto maskPos = GetMaskParamPos(getIntrinsicID()); 194 if (maskPos) 195 return getArgOperand(maskPos.getValue()); 196 return nullptr; 197 } 198 199 Value *VPIntrinsic::getVectorLengthParam() const { 200 auto vlenPos = GetVectorLengthParamPos(getIntrinsicID()); 201 if (vlenPos) 202 return getArgOperand(vlenPos.getValue()); 203 return nullptr; 204 } 205 206 Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) { 207 switch (IntrinsicID) { 208 default: 209 return None; 210 211 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 212 case Intrinsic::VPID: \ 213 return MASKPOS; 214 #include "llvm/IR/VPIntrinsics.def" 215 } 216 } 217 218 Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) { 219 switch (IntrinsicID) { 220 default: 221 return None; 222 223 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 224 case Intrinsic::VPID: \ 225 return VLENPOS; 226 #include "llvm/IR/VPIntrinsics.def" 227 } 228 } 229 230 bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) { 231 switch (ID) { 232 default: 233 return false; 234 235 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 236 case Intrinsic::VPID: \ 237 break; 238 #include "llvm/IR/VPIntrinsics.def" 239 } 240 return true; 241 } 242 243 // Equivalent non-predicated opcode 244 unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) { 245 switch (ID) { 246 default: 247 return Instruction::Call; 248 249 #define HANDLE_VP_TO_OC(VPID, OC) \ 250 case Intrinsic::VPID: \ 251 return Instruction::OC; 252 #include "llvm/IR/VPIntrinsics.def" 253 } 254 } 255 256 Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned OC) { 257 switch (OC) { 258 default: 259 return Intrinsic::not_intrinsic; 260 261 #define HANDLE_VP_TO_OC(VPID, OC) \ 262 case Instruction::OC: \ 263 return Intrinsic::VPID; 264 #include "llvm/IR/VPIntrinsics.def" 265 } 266 } 267 268 bool VPIntrinsic::canIgnoreVectorLengthParam() const { 269 using namespace PatternMatch; 270 271 ElementCount EC = getStaticVectorLength(); 272 273 // No vlen param - no lanes masked-off by it. 274 auto *VLParam = getVectorLengthParam(); 275 if (!VLParam) 276 return true; 277 278 // Note that the VP intrinsic causes undefined behavior if the Explicit Vector 279 // Length parameter is strictly greater-than the number of vector elements of 280 // the operation. This function returns true when this is detected statically 281 // in the IR. 282 283 // Check whether "W == vscale * EC.Min" 284 if (EC.Scalable) { 285 // Undig the DL 286 auto ParMod = this->getModule(); 287 if (!ParMod) 288 return false; 289 const auto &DL = ParMod->getDataLayout(); 290 291 // Compare vscale patterns 292 uint64_t VScaleFactor; 293 if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL)))) 294 return VScaleFactor >= EC.Min; 295 return (EC.Min == 1) && match(VLParam, m_VScale(DL)); 296 } 297 298 // standard SIMD operation 299 auto VLConst = dyn_cast<ConstantInt>(VLParam); 300 if (!VLConst) 301 return false; 302 303 uint64_t VLNum = VLConst->getZExtValue(); 304 if (VLNum >= EC.Min) 305 return true; 306 307 return false; 308 } 309 310 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { 311 switch (getIntrinsicID()) { 312 case Intrinsic::uadd_with_overflow: 313 case Intrinsic::sadd_with_overflow: 314 case Intrinsic::uadd_sat: 315 case Intrinsic::sadd_sat: 316 return Instruction::Add; 317 case Intrinsic::usub_with_overflow: 318 case Intrinsic::ssub_with_overflow: 319 case Intrinsic::usub_sat: 320 case Intrinsic::ssub_sat: 321 return Instruction::Sub; 322 case Intrinsic::umul_with_overflow: 323 case Intrinsic::smul_with_overflow: 324 return Instruction::Mul; 325 default: 326 llvm_unreachable("Invalid intrinsic"); 327 } 328 } 329 330 bool BinaryOpIntrinsic::isSigned() const { 331 switch (getIntrinsicID()) { 332 case Intrinsic::sadd_with_overflow: 333 case Intrinsic::ssub_with_overflow: 334 case Intrinsic::smul_with_overflow: 335 case Intrinsic::sadd_sat: 336 case Intrinsic::ssub_sat: 337 return true; 338 default: 339 return false; 340 } 341 } 342 343 unsigned BinaryOpIntrinsic::getNoWrapKind() const { 344 if (isSigned()) 345 return OverflowingBinaryOperator::NoSignedWrap; 346 else 347 return OverflowingBinaryOperator::NoUnsignedWrap; 348 } 349