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/IR/Operator.h" 25 #include "llvm/ADT/StringSwitch.h" 26 #include "llvm/IR/Constants.h" 27 #include "llvm/IR/DebugInfoMetadata.h" 28 #include "llvm/IR/GlobalVariable.h" 29 #include "llvm/IR/Metadata.h" 30 #include "llvm/IR/Module.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<fp::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 127 ConstrainedFPCmpIntrinsic::getPredicate() const { 128 Metadata *MD = 129 cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); 130 if (!MD || !isa<MDString>(MD)) 131 return FCmpInst::BAD_FCMP_PREDICATE; 132 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString()) 133 .Case("oeq", FCmpInst::FCMP_OEQ) 134 .Case("ogt", FCmpInst::FCMP_OGT) 135 .Case("oge", FCmpInst::FCMP_OGE) 136 .Case("olt", FCmpInst::FCMP_OLT) 137 .Case("ole", FCmpInst::FCMP_OLE) 138 .Case("one", FCmpInst::FCMP_ONE) 139 .Case("ord", FCmpInst::FCMP_ORD) 140 .Case("uno", FCmpInst::FCMP_UNO) 141 .Case("ueq", FCmpInst::FCMP_UEQ) 142 .Case("ugt", FCmpInst::FCMP_UGT) 143 .Case("uge", FCmpInst::FCMP_UGE) 144 .Case("ult", FCmpInst::FCMP_ULT) 145 .Case("ule", FCmpInst::FCMP_ULE) 146 .Case("une", FCmpInst::FCMP_UNE) 147 .Default(FCmpInst::BAD_FCMP_PREDICATE); 148 } 149 150 bool ConstrainedFPIntrinsic::isUnaryOp() const { 151 switch (getIntrinsicID()) { 152 default: 153 return false; 154 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 155 case Intrinsic::INTRINSIC: \ 156 return NARG == 1; 157 #include "llvm/IR/ConstrainedOps.def" 158 } 159 } 160 161 bool ConstrainedFPIntrinsic::isTernaryOp() const { 162 switch (getIntrinsicID()) { 163 default: 164 return false; 165 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 166 case Intrinsic::INTRINSIC: \ 167 return NARG == 3; 168 #include "llvm/IR/ConstrainedOps.def" 169 } 170 } 171 172 bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) { 173 switch (I->getIntrinsicID()) { 174 #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ 175 case Intrinsic::INTRINSIC: 176 #include "llvm/IR/ConstrainedOps.def" 177 return true; 178 default: 179 return false; 180 } 181 } 182 183 ElementCount VPIntrinsic::getStaticVectorLength() const { 184 auto GetVectorLengthOfType = [](const Type *T) -> ElementCount { 185 auto VT = cast<VectorType>(T); 186 auto ElemCount = VT->getElementCount(); 187 return ElemCount; 188 }; 189 190 auto VPMask = getMaskParam(); 191 return GetVectorLengthOfType(VPMask->getType()); 192 } 193 194 Value *VPIntrinsic::getMaskParam() const { 195 auto maskPos = GetMaskParamPos(getIntrinsicID()); 196 if (maskPos) 197 return getArgOperand(maskPos.getValue()); 198 return nullptr; 199 } 200 201 Value *VPIntrinsic::getVectorLengthParam() const { 202 auto vlenPos = GetVectorLengthParamPos(getIntrinsicID()); 203 if (vlenPos) 204 return getArgOperand(vlenPos.getValue()); 205 return nullptr; 206 } 207 208 Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) { 209 switch (IntrinsicID) { 210 default: 211 return None; 212 213 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 214 case Intrinsic::VPID: \ 215 return MASKPOS; 216 #include "llvm/IR/VPIntrinsics.def" 217 } 218 } 219 220 Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) { 221 switch (IntrinsicID) { 222 default: 223 return None; 224 225 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 226 case Intrinsic::VPID: \ 227 return VLENPOS; 228 #include "llvm/IR/VPIntrinsics.def" 229 } 230 } 231 232 bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) { 233 switch (ID) { 234 default: 235 return false; 236 237 #define REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 238 case Intrinsic::VPID: \ 239 break; 240 #include "llvm/IR/VPIntrinsics.def" 241 } 242 return true; 243 } 244 245 // Equivalent non-predicated opcode 246 unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) { 247 switch (ID) { 248 default: 249 return Instruction::Call; 250 251 #define HANDLE_VP_TO_OC(VPID, OC) \ 252 case Intrinsic::VPID: \ 253 return Instruction::OC; 254 #include "llvm/IR/VPIntrinsics.def" 255 } 256 } 257 258 Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned OC) { 259 switch (OC) { 260 default: 261 return Intrinsic::not_intrinsic; 262 263 #define HANDLE_VP_TO_OC(VPID, OC) \ 264 case Instruction::OC: \ 265 return Intrinsic::VPID; 266 #include "llvm/IR/VPIntrinsics.def" 267 } 268 } 269 270 bool VPIntrinsic::canIgnoreVectorLengthParam() const { 271 using namespace PatternMatch; 272 273 ElementCount EC = getStaticVectorLength(); 274 275 // No vlen param - no lanes masked-off by it. 276 auto *VLParam = getVectorLengthParam(); 277 if (!VLParam) 278 return true; 279 280 // Note that the VP intrinsic causes undefined behavior if the Explicit Vector 281 // Length parameter is strictly greater-than the number of vector elements of 282 // the operation. This function returns true when this is detected statically 283 // in the IR. 284 285 // Check whether "W == vscale * EC.Min" 286 if (EC.Scalable) { 287 // Undig the DL 288 auto ParMod = this->getModule(); 289 if (!ParMod) 290 return false; 291 const auto &DL = ParMod->getDataLayout(); 292 293 // Compare vscale patterns 294 uint64_t ParamFactor; 295 if (EC.Min > 1 && 296 match(VLParam, m_c_BinOp(m_ConstantInt(ParamFactor), m_VScale(DL)))) { 297 return ParamFactor >= EC.Min; 298 } 299 if (match(VLParam, m_VScale(DL))) { 300 return ParamFactor; 301 } 302 return false; 303 } 304 305 // standard SIMD operation 306 auto VLConst = dyn_cast<ConstantInt>(VLParam); 307 if (!VLConst) 308 return false; 309 310 uint64_t VLNum = VLConst->getZExtValue(); 311 if (VLNum >= EC.Min) 312 return true; 313 314 return false; 315 } 316 317 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { 318 switch (getIntrinsicID()) { 319 case Intrinsic::uadd_with_overflow: 320 case Intrinsic::sadd_with_overflow: 321 case Intrinsic::uadd_sat: 322 case Intrinsic::sadd_sat: 323 return Instruction::Add; 324 case Intrinsic::usub_with_overflow: 325 case Intrinsic::ssub_with_overflow: 326 case Intrinsic::usub_sat: 327 case Intrinsic::ssub_sat: 328 return Instruction::Sub; 329 case Intrinsic::umul_with_overflow: 330 case Intrinsic::smul_with_overflow: 331 return Instruction::Mul; 332 default: 333 llvm_unreachable("Invalid intrinsic"); 334 } 335 } 336 337 bool BinaryOpIntrinsic::isSigned() const { 338 switch (getIntrinsicID()) { 339 case Intrinsic::sadd_with_overflow: 340 case Intrinsic::ssub_with_overflow: 341 case Intrinsic::smul_with_overflow: 342 case Intrinsic::sadd_sat: 343 case Intrinsic::ssub_sat: 344 return true; 345 default: 346 return false; 347 } 348 } 349 350 unsigned BinaryOpIntrinsic::getNoWrapKind() const { 351 if (isSigned()) 352 return OverflowingBinaryOperator::NoSignedWrap; 353 else 354 return OverflowingBinaryOperator::NoUnsignedWrap; 355 } 356