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/Support/raw_ostream.h" 32 using namespace llvm; 33 34 //===----------------------------------------------------------------------===// 35 /// DbgVariableIntrinsic - This is the common base class for debug info 36 /// intrinsics for variables. 37 /// 38 39 Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const { 40 Value *Op = getArgOperand(0); 41 if (AllowNullOp && !Op) 42 return nullptr; 43 44 auto *MD = cast<MetadataAsValue>(Op)->getMetadata(); 45 if (auto *V = dyn_cast<ValueAsMetadata>(MD)) 46 return V->getValue(); 47 48 // When the value goes to null, it gets replaced by an empty MDNode. 49 assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode"); 50 return nullptr; 51 } 52 53 Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const { 54 if (auto Fragment = getExpression()->getFragmentInfo()) 55 return Fragment->SizeInBits; 56 return getVariable()->getSizeInBits(); 57 } 58 59 int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable, 60 StringRef Name) { 61 assert(Name.startswith("llvm.")); 62 63 // Do successive binary searches of the dotted name components. For 64 // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of 65 // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then 66 // "llvm.gc.experimental.statepoint", and then we will stop as the range is 67 // size 1. During the search, we can skip the prefix that we already know is 68 // identical. By using strncmp we consider names with differing suffixes to 69 // be part of the equal range. 70 size_t CmpEnd = 4; // Skip the "llvm" component. 71 const char *const *Low = NameTable.begin(); 72 const char *const *High = NameTable.end(); 73 const char *const *LastLow = Low; 74 while (CmpEnd < Name.size() && High - Low > 0) { 75 size_t CmpStart = CmpEnd; 76 CmpEnd = Name.find('.', CmpStart + 1); 77 CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd; 78 auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) { 79 return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0; 80 }; 81 LastLow = Low; 82 std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp); 83 } 84 if (High - Low > 0) 85 LastLow = Low; 86 87 if (LastLow == NameTable.end()) 88 return -1; 89 StringRef NameFound = *LastLow; 90 if (Name == NameFound || 91 (Name.startswith(NameFound) && Name[NameFound.size()] == '.')) 92 return LastLow - NameTable.begin(); 93 return -1; 94 } 95 96 Value *InstrProfIncrementInst::getStep() const { 97 if (InstrProfIncrementInstStep::classof(this)) { 98 return const_cast<Value *>(getArgOperand(4)); 99 } 100 const Module *M = getModule(); 101 LLVMContext &Context = M->getContext(); 102 return ConstantInt::get(Type::getInt64Ty(Context), 1); 103 } 104 105 Optional<fp::RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const { 106 unsigned NumOperands = getNumArgOperands(); 107 Metadata *MD = 108 cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata(); 109 if (!MD || !isa<MDString>(MD)) 110 return None; 111 return StrToRoundingMode(cast<MDString>(MD)->getString()); 112 } 113 114 Optional<fp::ExceptionBehavior> 115 ConstrainedFPIntrinsic::getExceptionBehavior() const { 116 unsigned NumOperands = getNumArgOperands(); 117 Metadata *MD = 118 cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata(); 119 if (!MD || !isa<MDString>(MD)) 120 return None; 121 return StrToExceptionBehavior(cast<MDString>(MD)->getString()); 122 } 123 124 FCmpInst::Predicate 125 ConstrainedFPCmpIntrinsic::getPredicate() const { 126 Metadata *MD = 127 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, DAGN) \ 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, DAGN) \ 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, DAGN) \ 173 case Intrinsic::INTRINSIC: 174 #include "llvm/IR/ConstrainedOps.def" 175 return true; 176 default: 177 return false; 178 } 179 } 180 181 Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { 182 switch (getIntrinsicID()) { 183 case Intrinsic::uadd_with_overflow: 184 case Intrinsic::sadd_with_overflow: 185 case Intrinsic::uadd_sat: 186 case Intrinsic::sadd_sat: 187 return Instruction::Add; 188 case Intrinsic::usub_with_overflow: 189 case Intrinsic::ssub_with_overflow: 190 case Intrinsic::usub_sat: 191 case Intrinsic::ssub_sat: 192 return Instruction::Sub; 193 case Intrinsic::umul_with_overflow: 194 case Intrinsic::smul_with_overflow: 195 return Instruction::Mul; 196 default: 197 llvm_unreachable("Invalid intrinsic"); 198 } 199 } 200 201 bool BinaryOpIntrinsic::isSigned() const { 202 switch (getIntrinsicID()) { 203 case Intrinsic::sadd_with_overflow: 204 case Intrinsic::ssub_with_overflow: 205 case Intrinsic::smul_with_overflow: 206 case Intrinsic::sadd_sat: 207 case Intrinsic::ssub_sat: 208 return true; 209 default: 210 return false; 211 } 212 } 213 214 unsigned BinaryOpIntrinsic::getNoWrapKind() const { 215 if (isSigned()) 216 return OverflowingBinaryOperator::NoSignedWrap; 217 else 218 return OverflowingBinaryOperator::NoUnsignedWrap; 219 } 220