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 iterator_range<DbgVariableIntrinsic::location_op_iterator> 42 DbgVariableIntrinsic::location_ops() const { 43 auto *MD = getRawLocation(); 44 assert(MD && "First operand of DbgVariableIntrinsic should be non-null."); 45 46 // If operand is ValueAsMetadata, return a range over just that operand. 47 if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) { 48 return {location_op_iterator(VAM), location_op_iterator(VAM + 1)}; 49 } 50 // If operand is DIArgList, return a range over its args. 51 if (auto *AL = dyn_cast<DIArgList>(MD)) 52 return {location_op_iterator(AL->args_begin()), 53 location_op_iterator(AL->args_end())}; 54 // Operand must be an empty metadata tuple, so return empty iterator. 55 return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), 56 location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; 57 } 58 59 Value *DbgVariableIntrinsic::getVariableLocationOp(unsigned OpIdx) const { 60 auto *MD = getRawLocation(); 61 assert(MD && "First operand of DbgVariableIntrinsic should be non-null."); 62 if (auto *AL = dyn_cast<DIArgList>(MD)) 63 return AL->getArgs()[OpIdx]->getValue(); 64 if (isa<MDNode>(MD)) 65 return nullptr; 66 assert( 67 isa<ValueAsMetadata>(MD) && 68 "Attempted to get location operand from DbgVariableIntrinsic with none."); 69 auto *V = cast<ValueAsMetadata>(MD); 70 assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a " 71 "single location operand."); 72 return V->getValue(); 73 } 74 75 static ValueAsMetadata *getAsMetadata(Value *V) { 76 return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>( 77 cast<MetadataAsValue>(V)->getMetadata()) 78 : ValueAsMetadata::get(V); 79 } 80 81 void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue, 82 Value *NewValue) { 83 assert(NewValue && "Values must be non-null"); 84 auto Locations = location_ops(); 85 auto OldIt = find(Locations, OldValue); 86 assert(OldIt != Locations.end() && "OldValue must be a current location"); 87 if (!hasArgList()) { 88 Value *NewOperand = isa<MetadataAsValue>(NewValue) 89 ? NewValue 90 : MetadataAsValue::get( 91 getContext(), ValueAsMetadata::get(NewValue)); 92 return setArgOperand(0, NewOperand); 93 } 94 SmallVector<ValueAsMetadata *, 4> MDs; 95 ValueAsMetadata *NewOperand = getAsMetadata(NewValue); 96 for (auto *VMD : Locations) 97 MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD)); 98 setArgOperand( 99 0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs))); 100 } 101 void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx, 102 Value *NewValue) { 103 assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index"); 104 if (!hasArgList()) { 105 Value *NewOperand = isa<MetadataAsValue>(NewValue) 106 ? NewValue 107 : MetadataAsValue::get( 108 getContext(), ValueAsMetadata::get(NewValue)); 109 return setArgOperand(0, NewOperand); 110 } 111 SmallVector<ValueAsMetadata *, 4> MDs; 112 ValueAsMetadata *NewOperand = getAsMetadata(NewValue); 113 for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx) 114 MDs.push_back(Idx == OpIdx ? NewOperand 115 : getAsMetadata(getVariableLocationOp(Idx))); 116 setArgOperand( 117 0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs))); 118 } 119 120 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const { 121 if (auto Fragment = getExpression()->getFragmentInfo()) 122 return Fragment->SizeInBits; 123 return getVariable()->getSizeInBits(); 124 } 125 126 int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable, 127 StringRef Name) { 128 assert(Name.startswith("llvm.")); 129 130 // Do successive binary searches of the dotted name components. For 131 // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of 132 // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then 133 // "llvm.gc.experimental.statepoint", and then we will stop as the range is 134 // size 1. During the search, we can skip the prefix that we already know is 135 // identical. By using strncmp we consider names with differing suffixes to 136 // be part of the equal range. 137 size_t CmpEnd = 4; // Skip the "llvm" component. 138 const char *const *Low = NameTable.begin(); 139 const char *const *High = NameTable.end(); 140 const char *const *LastLow = Low; 141 while (CmpEnd < Name.size() && High - Low > 0) { 142 size_t CmpStart = CmpEnd; 143 CmpEnd = Name.find('.', CmpStart + 1); 144 CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd; 145 auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) { 146 return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0; 147 }; 148 LastLow = Low; 149 std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp); 150 } 151 if (High - Low > 0) 152 LastLow = Low; 153 154 if (LastLow == NameTable.end()) 155 return -1; 156 StringRef NameFound = *LastLow; 157 if (Name == NameFound || 158 (Name.startswith(NameFound) && Name[NameFound.size()] == '.')) 159 return LastLow - NameTable.begin(); 160 return -1; 161 } 162 163 Value *InstrProfIncrementInst::getStep() const { 164 if (InstrProfIncrementInstStep::classof(this)) { 165 return const_cast<Value *>(getArgOperand(4)); 166 } 167 const Module *M = getModule(); 168 LLVMContext &Context = M->getContext(); 169 return ConstantInt::get(Type::getInt64Ty(Context), 1); 170 } 171 172 Optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const { 173 unsigned NumOperands = getNumArgOperands(); 174 Metadata *MD = 175 cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata(); 176 if (!MD || !isa<MDString>(MD)) 177 return None; 178 return StrToRoundingMode(cast<MDString>(MD)->getString()); 179 } 180 181 Optional<fp::ExceptionBehavior> 182 ConstrainedFPIntrinsic::getExceptionBehavior() const { 183 unsigned NumOperands = getNumArgOperands(); 184 Metadata *MD = 185 cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata(); 186 if (!MD || !isa<MDString>(MD)) 187 return None; 188 return StrToExceptionBehavior(cast<MDString>(MD)->getString()); 189 } 190 191 FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const { 192 Metadata *MD = cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); 193 if (!MD || !isa<MDString>(MD)) 194 return FCmpInst::BAD_FCMP_PREDICATE; 195 return StringSwitch<FCmpInst::Predicate>(cast<MDString>(MD)->getString()) 196 .Case("oeq", FCmpInst::FCMP_OEQ) 197 .Case("ogt", FCmpInst::FCMP_OGT) 198 .Case("oge", FCmpInst::FCMP_OGE) 199 .Case("olt", FCmpInst::FCMP_OLT) 200 .Case("ole", FCmpInst::FCMP_OLE) 201 .Case("one", FCmpInst::FCMP_ONE) 202 .Case("ord", FCmpInst::FCMP_ORD) 203 .Case("uno", FCmpInst::FCMP_UNO) 204 .Case("ueq", FCmpInst::FCMP_UEQ) 205 .Case("ugt", FCmpInst::FCMP_UGT) 206 .Case("uge", FCmpInst::FCMP_UGE) 207 .Case("ult", FCmpInst::FCMP_ULT) 208 .Case("ule", FCmpInst::FCMP_ULE) 209 .Case("une", FCmpInst::FCMP_UNE) 210 .Default(FCmpInst::BAD_FCMP_PREDICATE); 211 } 212 213 bool ConstrainedFPIntrinsic::isUnaryOp() const { 214 switch (getIntrinsicID()) { 215 default: 216 return false; 217 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 218 case Intrinsic::INTRINSIC: \ 219 return NARG == 1; 220 #include "llvm/IR/ConstrainedOps.def" 221 } 222 } 223 224 bool ConstrainedFPIntrinsic::isTernaryOp() const { 225 switch (getIntrinsicID()) { 226 default: 227 return false; 228 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 229 case Intrinsic::INTRINSIC: \ 230 return NARG == 3; 231 #include "llvm/IR/ConstrainedOps.def" 232 } 233 } 234 235 bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) { 236 switch (I->getIntrinsicID()) { 237 #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ 238 case Intrinsic::INTRINSIC: 239 #include "llvm/IR/ConstrainedOps.def" 240 return true; 241 default: 242 return false; 243 } 244 } 245 246 ElementCount VPIntrinsic::getStaticVectorLength() const { 247 auto GetVectorLengthOfType = [](const Type *T) -> ElementCount { 248 auto VT = cast<VectorType>(T); 249 auto ElemCount = VT->getElementCount(); 250 return ElemCount; 251 }; 252 253 auto VPMask = getMaskParam(); 254 return GetVectorLengthOfType(VPMask->getType()); 255 } 256 257 Value *VPIntrinsic::getMaskParam() const { 258 auto maskPos = GetMaskParamPos(getIntrinsicID()); 259 if (maskPos) 260 return getArgOperand(maskPos.getValue()); 261 return nullptr; 262 } 263 264 Value *VPIntrinsic::getVectorLengthParam() const { 265 auto vlenPos = GetVectorLengthParamPos(getIntrinsicID()); 266 if (vlenPos) 267 return getArgOperand(vlenPos.getValue()); 268 return nullptr; 269 } 270 271 Optional<int> VPIntrinsic::GetMaskParamPos(Intrinsic::ID IntrinsicID) { 272 switch (IntrinsicID) { 273 default: 274 return None; 275 276 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 277 case Intrinsic::VPID: \ 278 return MASKPOS; 279 #include "llvm/IR/VPIntrinsics.def" 280 } 281 } 282 283 Optional<int> VPIntrinsic::GetVectorLengthParamPos(Intrinsic::ID IntrinsicID) { 284 switch (IntrinsicID) { 285 default: 286 return None; 287 288 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 289 case Intrinsic::VPID: \ 290 return VLENPOS; 291 #include "llvm/IR/VPIntrinsics.def" 292 } 293 } 294 295 bool VPIntrinsic::IsVPIntrinsic(Intrinsic::ID ID) { 296 switch (ID) { 297 default: 298 return false; 299 300 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, MASKPOS, VLENPOS) \ 301 case Intrinsic::VPID: \ 302 break; 303 #include "llvm/IR/VPIntrinsics.def" 304 } 305 return true; 306 } 307 308 // Equivalent non-predicated opcode 309 unsigned VPIntrinsic::GetFunctionalOpcodeForVP(Intrinsic::ID ID) { 310 unsigned FunctionalOC = Instruction::Call; 311 switch (ID) { 312 default: 313 break; 314 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID: 315 #define HANDLE_VP_TO_OPC(OPC) FunctionalOC = Instruction::OPC; 316 #define END_REGISTER_VP_INTRINSIC(...) break; 317 #include "llvm/IR/VPIntrinsics.def" 318 } 319 320 return FunctionalOC; 321 } 322 323 Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned IROPC) { 324 switch (IROPC) { 325 default: 326 return Intrinsic::not_intrinsic; 327 328 #define HANDLE_VP_TO_OPC(OPC) case Instruction::OPC: 329 #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID; 330 #include "llvm/IR/VPIntrinsics.def" 331 } 332 } 333 334 bool VPIntrinsic::canIgnoreVectorLengthParam() const { 335 using namespace PatternMatch; 336 337 ElementCount EC = getStaticVectorLength(); 338 339 // No vlen param - no lanes masked-off by it. 340 auto *VLParam = getVectorLengthParam(); 341 if (!VLParam) 342 return true; 343 344 // Note that the VP intrinsic causes undefined behavior if the Explicit Vector 345 // Length parameter is strictly greater-than the number of vector elements of 346 // the operation. This function returns true when this is detected statically 347 // in the IR. 348 349 // Check whether "W == vscale * EC.getKnownMinValue()" 350 if (EC.isScalable()) { 351 // Undig the DL 352 auto ParMod = this->getModule(); 353 if (!ParMod) 354 return false; 355 const auto &DL = ParMod->getDataLayout(); 356 357 // Compare vscale patterns 358 uint64_t VScaleFactor; 359 if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL)))) 360 return VScaleFactor >= EC.getKnownMinValue(); 361 return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale(DL)); 362 } 363 364 // standard SIMD operation 365 auto VLConst = dyn_cast<ConstantInt>(VLParam); 366 if (!VLConst) 367 return false; 368 369 uint64_t VLNum = VLConst->getZExtValue(); 370 if (VLNum >= EC.getKnownMinValue()) 371 return true; 372 373 return false; 374 } 375 376 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { 377 switch (getIntrinsicID()) { 378 case Intrinsic::uadd_with_overflow: 379 case Intrinsic::sadd_with_overflow: 380 case Intrinsic::uadd_sat: 381 case Intrinsic::sadd_sat: 382 return Instruction::Add; 383 case Intrinsic::usub_with_overflow: 384 case Intrinsic::ssub_with_overflow: 385 case Intrinsic::usub_sat: 386 case Intrinsic::ssub_sat: 387 return Instruction::Sub; 388 case Intrinsic::umul_with_overflow: 389 case Intrinsic::smul_with_overflow: 390 return Instruction::Mul; 391 default: 392 llvm_unreachable("Invalid intrinsic"); 393 } 394 } 395 396 bool BinaryOpIntrinsic::isSigned() const { 397 switch (getIntrinsicID()) { 398 case Intrinsic::sadd_with_overflow: 399 case Intrinsic::ssub_with_overflow: 400 case Intrinsic::smul_with_overflow: 401 case Intrinsic::sadd_sat: 402 case Intrinsic::ssub_sat: 403 return true; 404 default: 405 return false; 406 } 407 } 408 409 unsigned BinaryOpIntrinsic::getNoWrapKind() const { 410 if (isSigned()) 411 return OverflowingBinaryOperator::NoSignedWrap; 412 else 413 return OverflowingBinaryOperator::NoUnsignedWrap; 414 } 415