Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- AMDGPULowerIntrinsics.cpp -----------------------------------------===//
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 "AMDGPU.h"
10
#include "AMDGPUSubtarget.h"
11
#include "llvm/CodeGen/TargetPassConfig.h"
12
#include "llvm/Analysis/TargetTransformInfo.h"
13
#include "llvm/IR/Constants.h"
14
#include "llvm/IR/Instructions.h"
15
#include "llvm/IR/IntrinsicInst.h"
16
#include "llvm/IR/Module.h"
17
#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
18
19
#define DEBUG_TYPE "amdgpu-lower-intrinsics"
20
21
using namespace llvm;
22
23
namespace {
24
25
const unsigned MaxStaticSize = 1024;
26
27
class AMDGPULowerIntrinsics : public ModulePass {
28
private:
29
  bool makeLIDRangeMetadata(Function &F) const;
30
31
public:
32
  static char ID;
33
34
2.72k
  AMDGPULowerIntrinsics() : ModulePass(ID) {}
35
36
  bool runOnModule(Module &M) override;
37
  bool expandMemIntrinsicUses(Function &F);
38
0
  StringRef getPassName() const override {
39
0
    return "AMDGPU Lower Intrinsics";
40
0
  }
41
42
2.70k
  void getAnalysisUsage(AnalysisUsage &AU) const override {
43
2.70k
    AU.addRequired<TargetTransformInfoWrapperPass>();
44
2.70k
  }
45
};
46
47
}
48
49
char AMDGPULowerIntrinsics::ID = 0;
50
51
char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID;
52
53
INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false,
54
                false)
55
56
// TODO: Should refine based on estimated number of accesses (e.g. does it
57
// require splitting based on alignment)
58
101
static bool shouldExpandOperationWithSize(Value *Size) {
59
101
  ConstantInt *CI = dyn_cast<ConstantInt>(Size);
60
101
  return !CI || 
(CI->getZExtValue() > MaxStaticSize)95
;
61
101
}
62
63
16
bool AMDGPULowerIntrinsics::expandMemIntrinsicUses(Function &F) {
64
16
  Intrinsic::ID ID = F.getIntrinsicID();
65
16
  bool Changed = false;
66
16
67
117
  for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
68
101
    Instruction *Inst = cast<Instruction>(*I);
69
101
    ++I;
70
101
71
101
    switch (ID) {
72
101
    case Intrinsic::memcpy: {
73
95
      auto *Memcpy = cast<MemCpyInst>(Inst);
74
95
      if (shouldExpandOperationWithSize(Memcpy->getLength())) {
75
7
        Function *ParentFunc = Memcpy->getParent()->getParent();
76
7
        const TargetTransformInfo &TTI =
77
7
            getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*ParentFunc);
78
7
        expandMemCpyAsLoop(Memcpy, TTI);
79
7
        Changed = true;
80
7
        Memcpy->eraseFromParent();
81
7
      }
82
95
83
95
      break;
84
101
    }
85
101
    case Intrinsic::memmove: {
86
2
      auto *Memmove = cast<MemMoveInst>(Inst);
87
2
      if (shouldExpandOperationWithSize(Memmove->getLength())) {
88
1
        expandMemMoveAsLoop(Memmove);
89
1
        Changed = true;
90
1
        Memmove->eraseFromParent();
91
1
      }
92
2
93
2
      break;
94
101
    }
95
101
    case Intrinsic::memset: {
96
4
      auto *Memset = cast<MemSetInst>(Inst);
97
4
      if (shouldExpandOperationWithSize(Memset->getLength())) {
98
3
        expandMemSetAsLoop(Memset);
99
3
        Changed = true;
100
3
        Memset->eraseFromParent();
101
3
      }
102
4
103
4
      break;
104
101
    }
105
101
    default:
106
0
      break;
107
101
    }
108
101
  }
109
16
110
16
  return Changed;
111
16
}
112
113
681
bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
114
681
  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
115
681
  if (!TPC)
116
0
    return false;
117
681
118
681
  const TargetMachine &TM = TPC->getTM<TargetMachine>();
119
681
  bool Changed = false;
120
681
121
3.96k
  for (auto *U : F.users()) {
122
3.96k
    auto *CI = dyn_cast<CallInst>(U);
123
3.96k
    if (!CI)
124
0
      continue;
125
3.96k
126
3.96k
    Changed |= AMDGPUSubtarget::get(TM, F).makeLIDRangeMetadata(CI);
127
3.96k
  }
128
681
  return Changed;
129
681
}
130
131
2.70k
bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
132
2.70k
  bool Changed = false;
133
2.70k
134
32.9k
  for (Function &F : M) {
135
32.9k
    if (!F.isDeclaration())
136
27.5k
      continue;
137
5.40k
138
5.40k
    switch (F.getIntrinsicID()) {
139
5.40k
    case Intrinsic::memcpy:
140
16
    case Intrinsic::memmove:
141
16
    case Intrinsic::memset:
142
16
      if (expandMemIntrinsicUses(F))
143
6
        Changed = true;
144
16
      break;
145
16
146
681
    case Intrinsic::amdgcn_workitem_id_x:
147
681
    case Intrinsic::r600_read_tidig_x:
148
681
    case Intrinsic::amdgcn_workitem_id_y:
149
681
    case Intrinsic::r600_read_tidig_y:
150
681
    case Intrinsic::amdgcn_workitem_id_z:
151
681
    case Intrinsic::r600_read_tidig_z:
152
681
    case Intrinsic::r600_read_local_size_x:
153
681
    case Intrinsic::r600_read_local_size_y:
154
681
    case Intrinsic::r600_read_local_size_z:
155
681
      Changed |= makeLIDRangeMetadata(F);
156
681
      break;
157
681
158
4.70k
    default:
159
4.70k
      break;
160
5.40k
    }
161
5.40k
  }
162
2.70k
163
2.70k
  return Changed;
164
2.70k
}
165
166
2.72k
ModulePass *llvm::createAMDGPULowerIntrinsicsPass() {
167
2.72k
  return new AMDGPULowerIntrinsics();
168
2.72k
}