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 BEGIN_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 BEGIN_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 BEGIN_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 unsigned FunctionalOC = Instruction::Call; 246 switch (ID) { 247 default: 248 break; 249 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID: 250 #define HANDLE_VP_TO_OPC(OPC) FunctionalOC = Instruction::OPC; 251 #define END_REGISTER_VP_INTRINSIC(...) break; 252 #include "llvm/IR/VPIntrinsics.def" 253 } 254 255 return FunctionalOC; 256 } 257 258 Intrinsic::ID VPIntrinsic::GetForOpcode(unsigned IROPC) { 259 switch (IROPC) { 260 default: 261 return Intrinsic::not_intrinsic; 262 263 #define HANDLE_VP_TO_OPC(OPC) case Instruction::OPC: 264 #define END_REGISTER_VP_INTRINSIC(VPID) return Intrinsic::VPID; 265 #include "llvm/IR/VPIntrinsics.def" 266 } 267 } 268 269 bool VPIntrinsic::canIgnoreVectorLengthParam() const { 270 using namespace PatternMatch; 271 272 ElementCount EC = getStaticVectorLength(); 273 274 // No vlen param - no lanes masked-off by it. 275 auto *VLParam = getVectorLengthParam(); 276 if (!VLParam) 277 return true; 278 279 // Note that the VP intrinsic causes undefined behavior if the Explicit Vector 280 // Length parameter is strictly greater-than the number of vector elements of 281 // the operation. This function returns true when this is detected statically 282 // in the IR. 283 284 // Check whether "W == vscale * EC.getKnownMinValue()" 285 if (EC.isScalable()) { 286 // Undig the DL 287 auto ParMod = this->getModule(); 288 if (!ParMod) 289 return false; 290 const auto &DL = ParMod->getDataLayout(); 291 292 // Compare vscale patterns 293 uint64_t VScaleFactor; 294 if (match(VLParam, m_c_Mul(m_ConstantInt(VScaleFactor), m_VScale(DL)))) 295 return VScaleFactor >= EC.getKnownMinValue(); 296 return (EC.getKnownMinValue() == 1) && match(VLParam, m_VScale(DL)); 297 } 298 299 // standard SIMD operation 300 auto VLConst = dyn_cast<ConstantInt>(VLParam); 301 if (!VLConst) 302 return false; 303 304 uint64_t VLNum = VLConst->getZExtValue(); 305 if (VLNum >= EC.getKnownMinValue()) 306 return true; 307 308 return false; 309 } 310 311 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { 312 switch (getIntrinsicID()) { 313 case Intrinsic::uadd_with_overflow: 314 case Intrinsic::sadd_with_overflow: 315 case Intrinsic::uadd_sat: 316 case Intrinsic::sadd_sat: 317 return Instruction::Add; 318 case Intrinsic::usub_with_overflow: 319 case Intrinsic::ssub_with_overflow: 320 case Intrinsic::usub_sat: 321 case Intrinsic::ssub_sat: 322 return Instruction::Sub; 323 case Intrinsic::umul_with_overflow: 324 case Intrinsic::smul_with_overflow: 325 return Instruction::Mul; 326 default: 327 llvm_unreachable("Invalid intrinsic"); 328 } 329 } 330 331 bool BinaryOpIntrinsic::isSigned() const { 332 switch (getIntrinsicID()) { 333 case Intrinsic::sadd_with_overflow: 334 case Intrinsic::ssub_with_overflow: 335 case Intrinsic::smul_with_overflow: 336 case Intrinsic::sadd_sat: 337 case Intrinsic::ssub_sat: 338 return true; 339 default: 340 return false; 341 } 342 } 343 344 unsigned BinaryOpIntrinsic::getNoWrapKind() const { 345 if (isSigned()) 346 return OverflowingBinaryOperator::NoSignedWrap; 347 else 348 return OverflowingBinaryOperator::NoUnsignedWrap; 349 } 350