Line data Source code
1 : //===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements methods that make it really easy to deal with intrinsic
11 : // functions.
12 : //
13 : // All intrinsic function calls are instances of the call instruction, so these
14 : // are all subclasses of the CallInst class. Note that none of these classes
15 : // has state or virtual methods, which is an important part of this gross/neat
16 : // hack working.
17 : //
18 : // In some cases, arguments to intrinsics need to be generic and are defined as
19 : // type pointer to empty struct { }*. To access the real item of interest the
20 : // cast instruction needs to be stripped away.
21 : //
22 : //===----------------------------------------------------------------------===//
23 :
24 : #include "llvm/IR/IntrinsicInst.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 3036492 : Value *DbgVariableIntrinsic::getVariableLocation(bool AllowNullOp) const {
40 3036492 : Value *Op = getArgOperand(0);
41 3036492 : if (AllowNullOp && !Op)
42 : return nullptr;
43 :
44 3036492 : auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
45 : if (auto *V = dyn_cast<ValueAsMetadata>(MD))
46 3019332 : 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 34289 : Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
54 34289 : if (auto Fragment = getExpression()->getFragmentInfo())
55 : return Fragment->SizeInBits;
56 33997 : return getVariable()->getSizeInBits();
57 : }
58 :
59 111689 : 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 CmpStart = 0;
71 : size_t CmpEnd = 4; // Skip the "llvm" component.
72 111689 : const char *const *Low = NameTable.begin();
73 111689 : const char *const *High = NameTable.end();
74 : const char *const *LastLow = Low;
75 416907 : while (CmpEnd < Name.size() && High - Low > 0) {
76 : CmpStart = CmpEnd;
77 397813 : CmpEnd = Name.find('.', CmpStart + 1);
78 212623 : CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd;
79 : auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
80 2963297 : return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0;
81 : };
82 : LastLow = Low;
83 305218 : std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp);
84 : }
85 111689 : if (High - Low > 0)
86 : LastLow = Low;
87 :
88 111689 : if (LastLow == NameTable.end())
89 : return -1;
90 111689 : StringRef NameFound = *LastLow;
91 : if (Name == NameFound ||
92 36875 : (Name.startswith(NameFound) && Name[NameFound.size()] == '.'))
93 107055 : return LastLow - NameTable.begin();
94 : return -1;
95 : }
96 :
97 844 : Value *InstrProfIncrementInst::getStep() const {
98 844 : if (InstrProfIncrementInstStep::classof(this)) {
99 2 : return const_cast<Value *>(getArgOperand(4));
100 : }
101 842 : const Module *M = getModule();
102 842 : LLVMContext &Context = M->getContext();
103 842 : return ConstantInt::get(Type::getInt64Ty(Context), 1);
104 : }
105 :
106 : ConstrainedFPIntrinsic::RoundingMode
107 753 : ConstrainedFPIntrinsic::getRoundingMode() const {
108 753 : unsigned NumOperands = getNumArgOperands();
109 : Metadata *MD =
110 753 : dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
111 753 : if (!MD || !isa<MDString>(MD))
112 : return rmInvalid;
113 753 : StringRef RoundingArg = cast<MDString>(MD)->getString();
114 :
115 : // For dynamic rounding mode, we use round to nearest but we will set the
116 : // 'exact' SDNodeFlag so that the value will not be rounded.
117 753 : return StringSwitch<RoundingMode>(RoundingArg)
118 : .Case("round.dynamic", rmDynamic)
119 : .Case("round.tonearest", rmToNearest)
120 : .Case("round.downward", rmDownward)
121 : .Case("round.upward", rmUpward)
122 : .Case("round.towardzero", rmTowardZero)
123 : .Default(rmInvalid);
124 : }
125 :
126 : ConstrainedFPIntrinsic::ExceptionBehavior
127 751 : ConstrainedFPIntrinsic::getExceptionBehavior() const {
128 751 : unsigned NumOperands = getNumArgOperands();
129 : Metadata *MD =
130 751 : dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
131 751 : if (!MD || !isa<MDString>(MD))
132 : return ebInvalid;
133 751 : StringRef ExceptionArg = cast<MDString>(MD)->getString();
134 751 : return StringSwitch<ExceptionBehavior>(ExceptionArg)
135 : .Case("fpexcept.ignore", ebIgnore)
136 : .Case("fpexcept.maytrap", ebMayTrap)
137 : .Case("fpexcept.strict", ebStrict)
138 : .Default(ebInvalid);
139 : }
140 :
141 625 : bool ConstrainedFPIntrinsic::isUnaryOp() const {
142 : switch (getIntrinsicID()) {
143 : default:
144 : return false;
145 : case Intrinsic::experimental_constrained_sqrt:
146 : case Intrinsic::experimental_constrained_sin:
147 : case Intrinsic::experimental_constrained_cos:
148 : case Intrinsic::experimental_constrained_exp:
149 : case Intrinsic::experimental_constrained_exp2:
150 : case Intrinsic::experimental_constrained_log:
151 : case Intrinsic::experimental_constrained_log10:
152 : case Intrinsic::experimental_constrained_log2:
153 : case Intrinsic::experimental_constrained_rint:
154 : case Intrinsic::experimental_constrained_nearbyint:
155 : return true;
156 : }
157 : }
158 :
159 163 : bool ConstrainedFPIntrinsic::isTernaryOp() const {
160 163 : switch (getIntrinsicID()) {
161 : default:
162 : return false;
163 75 : case Intrinsic::experimental_constrained_fma:
164 75 : return true;
165 : }
166 : }
167 :
|