IntrinsicInst.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. #include "llvm/IR/IntrinsicInst.h"
  23. #include "llvm/IR/Operator.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/Support/raw_ostream.h"
  31. using namespace llvm;
  32. //===----------------------------------------------------------------------===//
  33. /// DbgVariableIntrinsic - This is the common base class for debug info
  34. /// intrinsics for variables.
  35. ///
  36. Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
  37. Value *Op = getArgOperand(0);
  38. if (AllowNullOp && !Op)
  39. return nullptr;
  40. auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
  41. if (auto *V = dyn_cast<ValueAsMetadata>(MD))
  42. return V->getValue();
  43. // When the value goes to null, it gets replaced by an empty MDNode.
  44. assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
  45. return nullptr;
  46. }
  47. Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
  48. if (auto Fragment = getExpression()->getFragmentInfo())
  49. return Fragment->SizeInBits;
  50. return getVariable()->getSizeInBits();
  51. }
  52. int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
  53. StringRef Name) {
  54. assert(Name.startswith("llvm."));
  55. // Do successive binary searches of the dotted name components. For
  56. // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of
  57. // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then
  58. // "llvm.gc.experimental.statepoint", and then we will stop as the range is
  59. // size 1. During the search, we can skip the prefix that we already know is
  60. // identical. By using strncmp we consider names with differing suffixes to
  61. // be part of the equal range.
  62. size_t CmpStart = 0;
  63. size_t CmpEnd = 4; // Skip the "llvm" component.
  64. const char *const *Low = NameTable.begin();
  65. const char *const *High = NameTable.end();
  66. const char *const *LastLow = Low;
  67. while (CmpEnd < Name.size() && High - Low > 0) {
  68. CmpStart = CmpEnd;
  69. CmpEnd = Name.find('.', CmpStart + 1);
  70. CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
  71. auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
  72. return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
  73. };
  74. LastLow = Low;
  75. std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
  76. }
  77. if (High - Low > 0)
  78. LastLow = Low;
  79. if (LastLow == NameTable.end())
  80. return -1;
  81. StringRef NameFound = *LastLow;
  82. if (Name == NameFound ||
  83. (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
  84. return LastLow - NameTable.begin();
  85. return -1;
  86. }
  87. Value *InstrProfIncrementInst::getStep() const {
  88. if (InstrProfIncrementInstStep::classof(this)) {
  89. return const_cast<Value *>(getArgOperand(4));
  90. }
  91. const Module *M = getModule();
  92. LLVMContext &Context = M->getContext();
  93. return ConstantInt::get(Type::getInt64Ty(Context), 1);
  94. }
  95. Optional<ConstrainedFPIntrinsic::RoundingMode>
  96. ConstrainedFPIntrinsic::getRoundingMode() const {
  97. unsigned NumOperands = getNumArgOperands();
  98. Metadata *MD =
  99. dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
  100. if (!MD || !isa<MDString>(MD))
  101. return None;
  102. return StrToRoundingMode(cast<MDString>(MD)->getString());
  103. }
  104. Optional<ConstrainedFPIntrinsic::RoundingMode>
  105. ConstrainedFPIntrinsic::StrToRoundingMode(StringRef RoundingArg) {
  106. // For dynamic rounding mode, we use round to nearest but we will set the
  107. // 'exact' SDNodeFlag so that the value will not be rounded.
  108. return StringSwitch<Optional<RoundingMode>>(RoundingArg)
  109. .Case("round.dynamic", rmDynamic)
  110. .Case("round.tonearest", rmToNearest)
  111. .Case("round.downward", rmDownward)
  112. .Case("round.upward", rmUpward)
  113. .Case("round.towardzero", rmTowardZero)
  114. .Default(None);
  115. }
  116. Optional<StringRef>
  117. ConstrainedFPIntrinsic::RoundingModeToStr(RoundingMode UseRounding) {
  118. Optional<StringRef> RoundingStr = None;
  119. switch (UseRounding) {
  120. case ConstrainedFPIntrinsic::rmDynamic:
  121. RoundingStr = "round.dynamic";
  122. break;
  123. case ConstrainedFPIntrinsic::rmToNearest:
  124. RoundingStr = "round.tonearest";
  125. break;
  126. case ConstrainedFPIntrinsic::rmDownward:
  127. RoundingStr = "round.downward";
  128. break;
  129. case ConstrainedFPIntrinsic::rmUpward:
  130. RoundingStr = "round.upward";
  131. break;
  132. case ConstrainedFPIntrinsic::rmTowardZero:
  133. RoundingStr = "round.towardzero";
  134. break;
  135. }
  136. return RoundingStr;
  137. }
  138. Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
  139. ConstrainedFPIntrinsic::getExceptionBehavior() const {
  140. unsigned NumOperands = getNumArgOperands();
  141. Metadata *MD =
  142. dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
  143. if (!MD || !isa<MDString>(MD))
  144. return None;
  145. return StrToExceptionBehavior(cast<MDString>(MD)->getString());
  146. }
  147. Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
  148. ConstrainedFPIntrinsic::StrToExceptionBehavior(StringRef ExceptionArg) {
  149. return StringSwitch<Optional<ExceptionBehavior>>(ExceptionArg)
  150. .Case("fpexcept.ignore", ebIgnore)
  151. .Case("fpexcept.maytrap", ebMayTrap)
  152. .Case("fpexcept.strict", ebStrict)
  153. .Default(None);
  154. }
  155. Optional<StringRef>
  156. ConstrainedFPIntrinsic::ExceptionBehaviorToStr(ExceptionBehavior UseExcept) {
  157. Optional<StringRef> ExceptStr = None;
  158. switch (UseExcept) {
  159. case ConstrainedFPIntrinsic::ebStrict:
  160. ExceptStr = "fpexcept.strict";
  161. break;
  162. case ConstrainedFPIntrinsic::ebIgnore:
  163. ExceptStr = "fpexcept.ignore";
  164. break;
  165. case ConstrainedFPIntrinsic::ebMayTrap:
  166. ExceptStr = "fpexcept.maytrap";
  167. break;
  168. }
  169. return ExceptStr;
  170. }
  171. bool ConstrainedFPIntrinsic::isUnaryOp() const {
  172. switch (getIntrinsicID()) {
  173. default:
  174. return false;
  175. case Intrinsic::experimental_constrained_fptosi:
  176. case Intrinsic::experimental_constrained_fptoui:
  177. case Intrinsic::experimental_constrained_fptrunc:
  178. case Intrinsic::experimental_constrained_fpext:
  179. case Intrinsic::experimental_constrained_sqrt:
  180. case Intrinsic::experimental_constrained_sin:
  181. case Intrinsic::experimental_constrained_cos:
  182. case Intrinsic::experimental_constrained_exp:
  183. case Intrinsic::experimental_constrained_exp2:
  184. case Intrinsic::experimental_constrained_log:
  185. case Intrinsic::experimental_constrained_log10:
  186. case Intrinsic::experimental_constrained_log2:
  187. case Intrinsic::experimental_constrained_rint:
  188. case Intrinsic::experimental_constrained_nearbyint:
  189. case Intrinsic::experimental_constrained_ceil:
  190. case Intrinsic::experimental_constrained_floor:
  191. case Intrinsic::experimental_constrained_round:
  192. case Intrinsic::experimental_constrained_trunc:
  193. return true;
  194. }
  195. }
  196. bool ConstrainedFPIntrinsic::isTernaryOp() const {
  197. switch (getIntrinsicID()) {
  198. default:
  199. return false;
  200. case Intrinsic::experimental_constrained_fma:
  201. return true;
  202. }
  203. }
  204. Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const {
  205. switch (getIntrinsicID()) {
  206. case Intrinsic::uadd_with_overflow:
  207. case Intrinsic::sadd_with_overflow:
  208. case Intrinsic::uadd_sat:
  209. case Intrinsic::sadd_sat:
  210. return Instruction::Add;
  211. case Intrinsic::usub_with_overflow:
  212. case Intrinsic::ssub_with_overflow:
  213. case Intrinsic::usub_sat:
  214. case Intrinsic::ssub_sat:
  215. return Instruction::Sub;
  216. case Intrinsic::umul_with_overflow:
  217. case Intrinsic::smul_with_overflow:
  218. return Instruction::Mul;
  219. default:
  220. llvm_unreachable("Invalid intrinsic");
  221. }
  222. }
  223. bool BinaryOpIntrinsic::isSigned() const {
  224. switch (getIntrinsicID()) {
  225. case Intrinsic::sadd_with_overflow:
  226. case Intrinsic::ssub_with_overflow:
  227. case Intrinsic::smul_with_overflow:
  228. case Intrinsic::sadd_sat:
  229. case Intrinsic::ssub_sat:
  230. return true;
  231. default:
  232. return false;
  233. }
  234. }
  235. unsigned BinaryOpIntrinsic::getNoWrapKind() const {
  236. if (isSigned())
  237. return OverflowingBinaryOperator::NoSignedWrap;
  238. else
  239. return OverflowingBinaryOperator::NoUnsignedWrap;
  240. }