Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/NVPTX/NVVMIntrRange.cpp
Line
Count
Source
1
//===- NVVMIntrRange.cpp - Set !range metadata for NVVM intrinsics --------===//
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 pass adds appropriate !range metadata for calls to NVVM
10
// intrinsics that return a limited range of values.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "NVPTX.h"
15
#include "llvm/IR/Constants.h"
16
#include "llvm/IR/InstIterator.h"
17
#include "llvm/IR/Instructions.h"
18
#include "llvm/IR/Intrinsics.h"
19
20
using namespace llvm;
21
22
#define DEBUG_TYPE "nvvm-intr-range"
23
24
namespace llvm { void initializeNVVMIntrRangePass(PassRegistry &); }
25
26
// Add !range metadata based on limits of given SM variant.
27
static cl::opt<unsigned> NVVMIntrRangeSM("nvvm-intr-range-sm", cl::init(20),
28
                                         cl::Hidden, cl::desc("SM variant"));
29
30
namespace {
31
class NVVMIntrRange : public FunctionPass {
32
 private:
33
   struct {
34
     unsigned x, y, z;
35
   } MaxBlockSize, MaxGridSize;
36
37
 public:
38
   static char ID;
39
2
   NVVMIntrRange() : NVVMIntrRange(NVVMIntrRangeSM) {}
40
127
   NVVMIntrRange(unsigned int SmVersion) : FunctionPass(ID) {
41
127
     MaxBlockSize.x = 1024;
42
127
     MaxBlockSize.y = 1024;
43
127
     MaxBlockSize.z = 64;
44
127
45
127
     MaxGridSize.x = SmVersion >= 30 ? 
0x7fffffff20
:
0xffff107
;
46
127
     MaxGridSize.y = 0xffff;
47
127
     MaxGridSize.z = 0xffff;
48
127
49
127
     initializeNVVMIntrRangePass(*PassRegistry::getPassRegistry());
50
127
   }
51
52
   bool runOnFunction(Function &) override;
53
};
54
}
55
56
125
FunctionPass *llvm::createNVVMIntrRangePass(unsigned int SmVersion) {
57
125
  return new NVVMIntrRange(SmVersion);
58
125
}
59
60
char NVVMIntrRange::ID = 0;
61
INITIALIZE_PASS(NVVMIntrRange, "nvvm-intr-range",
62
                "Add !range metadata to NVVM intrinsics.", false, false)
63
64
// Adds the passed-in [Low,High) range information as metadata to the
65
// passed-in call instruction.
66
1.39k
static bool addRangeMetadata(uint64_t Low, uint64_t High, CallInst *C) {
67
1.39k
  // This call already has range metadata, nothing to do.
68
1.39k
  if (C->getMetadata(LLVMContext::MD_range))
69
2
    return false;
70
1.38k
71
1.38k
  LLVMContext &Context = C->getParent()->getContext();
72
1.38k
  IntegerType *Int32Ty = Type::getInt32Ty(Context);
73
1.38k
  Metadata *LowAndHigh[] = {
74
1.38k
      ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Low)),
75
1.38k
      ConstantAsMetadata::get(ConstantInt::get(Int32Ty, High))};
76
1.38k
  C->setMetadata(LLVMContext::MD_range, MDNode::get(Context, LowAndHigh));
77
1.38k
  return true;
78
1.38k
}
79
80
1.92k
bool NVVMIntrRange::runOnFunction(Function &F) {
81
1.92k
  // Go through the calls in this function.
82
1.92k
  bool Changed = false;
83
92.8k
  for (Instruction &I : instructions(F)) {
84
92.8k
    CallInst *Call = dyn_cast<CallInst>(&I);
85
92.8k
    if (!Call)
86
84.8k
      continue;
87
7.99k
88
7.99k
    if (Function *Callee = Call->getCalledFunction()) {
89
7.91k
      switch (Callee->getIntrinsicID()) {
90
7.91k
      // Index within block
91
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_tid_x:
92
189
        Changed |= addRangeMetadata(0, MaxBlockSize.x, Call);
93
189
        break;
94
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_tid_y:
95
6
        Changed |= addRangeMetadata(0, MaxBlockSize.y, Call);
96
6
        break;
97
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_tid_z:
98
6
        Changed |= addRangeMetadata(0, MaxBlockSize.z, Call);
99
6
        break;
100
7.91k
101
7.91k
      // Block size
102
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_ntid_x:
103
917
        Changed |= addRangeMetadata(1, MaxBlockSize.x+1, Call);
104
917
        break;
105
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_ntid_y:
106
6
        Changed |= addRangeMetadata(1, MaxBlockSize.y+1, Call);
107
6
        break;
108
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_ntid_z:
109
6
        Changed |= addRangeMetadata(1, MaxBlockSize.z+1, Call);
110
6
        break;
111
7.91k
112
7.91k
      // Index within grid
113
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_ctaid_x:
114
6
        Changed |= addRangeMetadata(0, MaxGridSize.x, Call);
115
6
        break;
116
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_ctaid_y:
117
6
        Changed |= addRangeMetadata(0, MaxGridSize.y, Call);
118
6
        break;
119
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_ctaid_z:
120
6
        Changed |= addRangeMetadata(0, MaxGridSize.z, Call);
121
6
        break;
122
7.91k
123
7.91k
      // Grid size
124
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_nctaid_x:
125
8
        Changed |= addRangeMetadata(1, MaxGridSize.x+1, Call);
126
8
        break;
127
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_nctaid_y:
128
6
        Changed |= addRangeMetadata(1, MaxGridSize.y+1, Call);
129
6
        break;
130
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_nctaid_z:
131
6
        Changed |= addRangeMetadata(1, MaxGridSize.z+1, Call);
132
6
        break;
133
7.91k
134
7.91k
      // warp size is constant 32.
135
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_warpsize:
136
218
        Changed |= addRangeMetadata(32, 32+1, Call);
137
218
        break;
138
7.91k
139
7.91k
      // Lane ID is [0..warpsize)
140
7.91k
      case Intrinsic::nvvm_read_ptx_sreg_laneid:
141
5
        Changed |= addRangeMetadata(0, 32, Call);
142
5
        break;
143
7.91k
144
7.91k
      default:
145
6.51k
        break;
146
7.91k
      }
147
7.91k
    }
148
7.99k
  }
149
1.92k
150
1.92k
  return Changed;
151
1.92k
}