Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/lib/Analysis/MemoryLocation.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MemoryLocation.cpp - Memory location descriptions -------------------==//
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
#include "llvm/Analysis/MemoryLocation.h"
10
#include "llvm/Analysis/TargetLibraryInfo.h"
11
#include "llvm/IR/DataLayout.h"
12
#include "llvm/IR/Instructions.h"
13
#include "llvm/IR/IntrinsicInst.h"
14
#include "llvm/IR/IntrinsicsARM.h"
15
#include "llvm/IR/Module.h"
16
#include "llvm/IR/Type.h"
17
#include <optional>
18
using namespace llvm;
19
20
0
void LocationSize::print(raw_ostream &OS) const {
21
0
  OS << "LocationSize::";
22
0
  if (*this == beforeOrAfterPointer())
23
0
    OS << "beforeOrAfterPointer";
24
0
  else if (*this == afterPointer())
25
0
    OS << "afterPointer";
26
0
  else if (*this == mapEmpty())
27
0
    OS << "mapEmpty";
28
0
  else if (*this == mapTombstone())
29
0
    OS << "mapTombstone";
30
0
  else if (isPrecise())
31
0
    OS << "precise(" << getValue() << ')';
32
0
  else
33
0
    OS << "upperBound(" << getValue() << ')';
34
0
}
35
36
3.30M
MemoryLocation MemoryLocation::get(const LoadInst *LI) {
37
3.30M
  const auto &DL = LI->getModule()->getDataLayout();
38
39
3.30M
  return MemoryLocation(
40
3.30M
      LI->getPointerOperand(),
41
3.30M
      LocationSize::precise(DL.getTypeStoreSize(LI->getType())),
42
3.30M
      LI->getAAMetadata());
43
3.30M
}
44
45
20.4M
MemoryLocation MemoryLocation::get(const StoreInst *SI) {
46
20.4M
  const auto &DL = SI->getModule()->getDataLayout();
47
48
20.4M
  return MemoryLocation(SI->getPointerOperand(),
49
20.4M
                        LocationSize::precise(DL.getTypeStoreSize(
50
20.4M
                            SI->getValueOperand()->getType())),
51
20.4M
                        SI->getAAMetadata());
52
20.4M
}
53
54
0
MemoryLocation MemoryLocation::get(const VAArgInst *VI) {
55
0
  return MemoryLocation(VI->getPointerOperand(),
56
0
                        LocationSize::afterPointer(), VI->getAAMetadata());
57
0
}
58
59
2
MemoryLocation MemoryLocation::get(const AtomicCmpXchgInst *CXI) {
60
2
  const auto &DL = CXI->getModule()->getDataLayout();
61
62
2
  return MemoryLocation(CXI->getPointerOperand(),
63
2
                        LocationSize::precise(DL.getTypeStoreSize(
64
2
                            CXI->getCompareOperand()->getType())),
65
2
                        CXI->getAAMetadata());
66
2
}
67
68
24
MemoryLocation MemoryLocation::get(const AtomicRMWInst *RMWI) {
69
24
  const auto &DL = RMWI->getModule()->getDataLayout();
70
71
24
  return MemoryLocation(RMWI->getPointerOperand(),
72
24
                        LocationSize::precise(DL.getTypeStoreSize(
73
24
                            RMWI->getValOperand()->getType())),
74
24
                        RMWI->getAAMetadata());
75
24
}
76
77
std::optional<MemoryLocation>
78
8.15M
MemoryLocation::getOrNone(const Instruction *Inst) {
79
8.15M
  switch (Inst->getOpcode()) {
80
277k
  case Instruction::Load:
81
277k
    return get(cast<LoadInst>(Inst));
82
7.87M
  case Instruction::Store:
83
7.87M
    return get(cast<StoreInst>(Inst));
84
0
  case Instruction::VAArg:
85
0
    return get(cast<VAArgInst>(Inst));
86
0
  case Instruction::AtomicCmpXchg:
87
0
    return get(cast<AtomicCmpXchgInst>(Inst));
88
0
  case Instruction::AtomicRMW:
89
0
    return get(cast<AtomicRMWInst>(Inst));
90
77
  default:
91
77
    return std::nullopt;
92
8.15M
  }
93
8.15M
}
94
95
0
MemoryLocation MemoryLocation::getForSource(const MemTransferInst *MTI) {
96
0
  return getForSource(cast<AnyMemTransferInst>(MTI));
97
0
}
98
99
0
MemoryLocation MemoryLocation::getForSource(const AtomicMemTransferInst *MTI) {
100
0
  return getForSource(cast<AnyMemTransferInst>(MTI));
101
0
}
102
103
0
MemoryLocation MemoryLocation::getForSource(const AnyMemTransferInst *MTI) {
104
0
  assert(MTI->getRawSource() == MTI->getArgOperand(1));
105
0
  return getForArgument(MTI, 1, nullptr);
106
0
}
107
108
0
MemoryLocation MemoryLocation::getForDest(const MemIntrinsic *MI) {
109
0
  return getForDest(cast<AnyMemIntrinsic>(MI));
110
0
}
111
112
0
MemoryLocation MemoryLocation::getForDest(const AtomicMemIntrinsic *MI) {
113
0
  return getForDest(cast<AnyMemIntrinsic>(MI));
114
0
}
115
116
0
MemoryLocation MemoryLocation::getForDest(const AnyMemIntrinsic *MI) {
117
0
  assert(MI->getRawDest() == MI->getArgOperand(0));
118
0
  return getForArgument(MI, 0, nullptr);
119
0
}
120
121
std::optional<MemoryLocation>
122
11
MemoryLocation::getForDest(const CallBase *CB, const TargetLibraryInfo &TLI) {
123
11
  if (!CB->onlyAccessesArgMemory())
124
0
    return std::nullopt;
125
126
11
  if (CB->hasOperandBundles())
127
    // TODO: remove implementation restriction
128
0
    return std::nullopt;
129
130
11
  Value *UsedV = nullptr;
131
11
  std::optional<unsigned> UsedIdx;
132
49
  for (unsigned i = 0; i < CB->arg_size(); i++) {
133
38
    if (!CB->getArgOperand(i)->getType()->isPointerTy())
134
16
      continue;
135
22
    if (CB->onlyReadsMemory(i))
136
11
      continue;
137
11
    if (!UsedV) {
138
      // First potentially writing parameter
139
11
      UsedV = CB->getArgOperand(i);
140
11
      UsedIdx = i;
141
11
      continue;
142
11
    }
143
0
    UsedIdx = std::nullopt;
144
0
    if (UsedV != CB->getArgOperand(i))
145
      // Can't describe writing to two distinct locations.
146
      // TODO: This results in an inprecision when two values derived from the
147
      // same object are passed as arguments to the same function.
148
0
      return std::nullopt;
149
0
  }
150
11
  if (!UsedV)
151
    // We don't currently have a way to represent a "does not write" result
152
    // and thus have to be conservative and return unknown.
153
0
    return std::nullopt;
154
155
11
  if (UsedIdx)
156
11
    return getForArgument(CB, *UsedIdx, &TLI);
157
0
  return MemoryLocation::getBeforeOrAfter(UsedV, CB->getAAMetadata());
158
11
}
159
160
MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
161
                                              unsigned ArgIdx,
162
10.6k
                                              const TargetLibraryInfo *TLI) {
163
10.6k
  AAMDNodes AATags = Call->getAAMetadata();
164
10.6k
  const Value *Arg = Call->getArgOperand(ArgIdx);
165
166
  // We may be able to produce an exact size for known intrinsics.
167
10.6k
  if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call)) {
168
10.5k
    const DataLayout &DL = II->getModule()->getDataLayout();
169
170
10.5k
    switch (II->getIntrinsicID()) {
171
2.35k
    default:
172
2.35k
      break;
173
4.80k
    case Intrinsic::memset:
174
5.79k
    case Intrinsic::memcpy:
175
5.79k
    case Intrinsic::memcpy_inline:
176
5.86k
    case Intrinsic::memmove:
177
5.92k
    case Intrinsic::memcpy_element_unordered_atomic:
178
5.95k
    case Intrinsic::memmove_element_unordered_atomic:
179
5.97k
    case Intrinsic::memset_element_unordered_atomic:
180
5.97k
      assert((ArgIdx == 0 || ArgIdx == 1) &&
181
5.97k
             "Invalid argument index for memory intrinsic");
182
5.97k
      if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))
183
5.34k
        return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
184
5.34k
                              AATags);
185
636
      return MemoryLocation::getAfter(Arg, AATags);
186
187
294
    case Intrinsic::lifetime_start:
188
1.47k
    case Intrinsic::lifetime_end:
189
1.71k
    case Intrinsic::invariant_start:
190
1.71k
      assert(ArgIdx == 1 && "Invalid argument index");
191
0
      return MemoryLocation(
192
1.71k
          Arg,
193
1.71k
          LocationSize::precise(
194
1.71k
              cast<ConstantInt>(II->getArgOperand(0))->getZExtValue()),
195
1.71k
          AATags);
196
197
41
    case Intrinsic::masked_load:
198
41
      assert(ArgIdx == 0 && "Invalid argument index");
199
0
      return MemoryLocation(
200
41
          Arg,
201
41
          LocationSize::upperBound(DL.getTypeStoreSize(II->getType())),
202
41
          AATags);
203
204
219
    case Intrinsic::masked_store:
205
219
      assert(ArgIdx == 1 && "Invalid argument index");
206
0
      return MemoryLocation(
207
219
          Arg,
208
219
          LocationSize::upperBound(
209
219
              DL.getTypeStoreSize(II->getArgOperand(0)->getType())),
210
219
          AATags);
211
212
230
    case Intrinsic::invariant_end:
213
      // The first argument to an invariant.end is a "descriptor" type (e.g. a
214
      // pointer to a empty struct) which is never actually dereferenced.
215
230
      if (ArgIdx == 0)
216
115
        return MemoryLocation(Arg, LocationSize::precise(0), AATags);
217
115
      assert(ArgIdx == 2 && "Invalid argument index");
218
0
      return MemoryLocation(
219
115
          Arg,
220
115
          LocationSize::precise(
221
115
              cast<ConstantInt>(II->getArgOperand(1))->getZExtValue()),
222
115
          AATags);
223
224
2
    case Intrinsic::arm_neon_vld1:
225
2
      assert(ArgIdx == 0 && "Invalid argument index");
226
      // LLVM's vld1 and vst1 intrinsics currently only support a single
227
      // vector register.
228
0
      return MemoryLocation(
229
2
          Arg, LocationSize::precise(DL.getTypeStoreSize(II->getType())),
230
2
          AATags);
231
232
0
    case Intrinsic::arm_neon_vst1:
233
0
      assert(ArgIdx == 0 && "Invalid argument index");
234
0
      return MemoryLocation(Arg,
235
0
                            LocationSize::precise(DL.getTypeStoreSize(
236
0
                                II->getArgOperand(1)->getType())),
237
0
                            AATags);
238
10.5k
    }
239
240
2.35k
    assert(
241
2.35k
        !isa<AnyMemTransferInst>(II) &&
242
2.35k
        "all memory transfer intrinsics should be handled by the switch above");
243
2.35k
  }
244
245
  // We can bound the aliasing properties of memset_pattern16 just as we can
246
  // for memcpy/memset.  This is particularly important because the
247
  // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
248
  // whenever possible.
249
2.50k
  LibFunc F;
250
2.50k
  if (TLI && TLI->getLibFunc(*Call, F) && TLI->has(F)) {
251
15
    switch (F) {
252
3
    case LibFunc_strcpy:
253
7
    case LibFunc_strcat:
254
7
    case LibFunc_strncat:
255
7
      assert((ArgIdx == 0 || ArgIdx == 1) && "Invalid argument index for str function");
256
0
      return MemoryLocation::getAfter(Arg, AATags);
257
258
0
    case LibFunc_memset_chk:
259
0
      assert(ArgIdx == 0 && "Invalid argument index for memset_chk");
260
0
      [[fallthrough]];
261
0
    case LibFunc_memcpy_chk: {
262
0
      assert((ArgIdx == 0 || ArgIdx == 1) &&
263
0
             "Invalid argument index for memcpy_chk");
264
0
      LocationSize Size = LocationSize::afterPointer();
265
0
      if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
266
        // memset_chk writes at most Len bytes, memcpy_chk reads/writes at most
267
        // Len bytes. They may read/write less, if Len exceeds the specified max
268
        // size and aborts.
269
0
        Size = LocationSize::upperBound(Len->getZExtValue());
270
0
      }
271
0
      return MemoryLocation(Arg, Size, AATags);
272
0
    }
273
0
    case LibFunc_strncpy: {
274
0
      assert((ArgIdx == 0 || ArgIdx == 1) &&
275
0
             "Invalid argument index for strncpy");
276
0
      LocationSize Size = LocationSize::afterPointer();
277
0
      if (const auto *Len = dyn_cast<ConstantInt>(Call->getArgOperand(2))) {
278
        // strncpy is guaranteed to write Len bytes, but only reads up to Len
279
        // bytes.
280
0
        Size = ArgIdx == 0 ? LocationSize::precise(Len->getZExtValue())
281
0
                           : LocationSize::upperBound(Len->getZExtValue());
282
0
      }
283
0
      return MemoryLocation(Arg, Size, AATags);
284
0
    }
285
0
    case LibFunc_memset_pattern16:
286
0
    case LibFunc_memset_pattern4:
287
0
    case LibFunc_memset_pattern8:
288
0
      assert((ArgIdx == 0 || ArgIdx == 1) &&
289
0
             "Invalid argument index for memset_pattern16");
290
0
      if (ArgIdx == 1) {
291
0
        unsigned Size = 16;
292
0
        if (F == LibFunc_memset_pattern4)
293
0
          Size = 4;
294
0
        else if (F == LibFunc_memset_pattern8)
295
0
          Size = 8;
296
0
        return MemoryLocation(Arg, LocationSize::precise(Size), AATags);
297
0
      }
298
0
      if (const ConstantInt *LenCI =
299
0
              dyn_cast<ConstantInt>(Call->getArgOperand(2)))
300
0
        return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
301
0
                              AATags);
302
0
      return MemoryLocation::getAfter(Arg, AATags);
303
0
    case LibFunc_bcmp:
304
0
    case LibFunc_memcmp:
305
0
      assert((ArgIdx == 0 || ArgIdx == 1) &&
306
0
             "Invalid argument index for memcmp/bcmp");
307
0
      if (const ConstantInt *LenCI =
308
0
              dyn_cast<ConstantInt>(Call->getArgOperand(2)))
309
0
        return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
310
0
                              AATags);
311
0
      return MemoryLocation::getAfter(Arg, AATags);
312
0
    case LibFunc_memchr:
313
0
      assert((ArgIdx == 0) && "Invalid argument index for memchr");
314
0
      if (const ConstantInt *LenCI =
315
0
              dyn_cast<ConstantInt>(Call->getArgOperand(2)))
316
0
        return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
317
0
                              AATags);
318
0
      return MemoryLocation::getAfter(Arg, AATags);
319
8
    case LibFunc_memccpy:
320
8
      assert((ArgIdx == 0 || ArgIdx == 1) &&
321
8
             "Invalid argument index for memccpy");
322
      // We only know an upper bound on the number of bytes read/written.
323
8
      if (const ConstantInt *LenCI =
324
8
              dyn_cast<ConstantInt>(Call->getArgOperand(3)))
325
8
        return MemoryLocation(
326
8
            Arg, LocationSize::upperBound(LenCI->getZExtValue()), AATags);
327
0
      return MemoryLocation::getAfter(Arg, AATags);
328
0
    default:
329
0
      break;
330
15
    };
331
0
  }
332
333
2.49k
  return MemoryLocation::getBeforeOrAfter(Call->getArgOperand(ArgIdx), AATags);
334
2.50k
}