1 #include "CodeGen_GPU_Dev.h"
2 #include "Bounds.h"
3 #include "IRVisitor.h"
4
5 namespace Halide {
6 namespace Internal {
7
~CodeGen_GPU_Dev()8 CodeGen_GPU_Dev::~CodeGen_GPU_Dev() {
9 }
10
is_gpu_var(const std::string & name)11 bool CodeGen_GPU_Dev::is_gpu_var(const std::string &name) {
12 return is_gpu_block_var(name) || is_gpu_thread_var(name);
13 }
14
is_gpu_block_var(const std::string & name)15 bool CodeGen_GPU_Dev::is_gpu_block_var(const std::string &name) {
16 return (ends_with(name, ".__block_id_x") ||
17 ends_with(name, ".__block_id_y") ||
18 ends_with(name, ".__block_id_z") ||
19 ends_with(name, ".__block_id_w"));
20 }
21
is_gpu_thread_var(const std::string & name)22 bool CodeGen_GPU_Dev::is_gpu_thread_var(const std::string &name) {
23 return (ends_with(name, ".__thread_id_x") ||
24 ends_with(name, ".__thread_id_y") ||
25 ends_with(name, ".__thread_id_z") ||
26 ends_with(name, ".__thread_id_w"));
27 }
28
29 namespace {
30 // Check to see if an expression is uniform within a block.
31 // This is done by checking to see if the expression depends on any GPU
32 // thread indices.
33 class IsBlockUniform : public IRVisitor {
34 using IRVisitor::visit;
35
visit(const Variable * op)36 void visit(const Variable *op) override {
37 if (CodeGen_GPU_Dev::is_gpu_thread_var(op->name)) {
38 result = false;
39 }
40 }
41
42 public:
43 bool result;
44
IsBlockUniform()45 IsBlockUniform()
46 : result(true) {
47 }
48 };
49 } // namespace
50
is_block_uniform(const Expr & expr)51 bool CodeGen_GPU_Dev::is_block_uniform(const Expr &expr) {
52 IsBlockUniform v;
53 expr.accept(&v);
54 return v.result;
55 }
56
57 namespace {
58 // Check to see if a buffer is a candidate for constant memory storage.
59 // A buffer is a candidate for constant memory if it is never written to,
60 // and loads are uniform within the workgroup.
61 class IsBufferConstant : public IRVisitor {
62 using IRVisitor::visit;
63
visit(const Store * op)64 void visit(const Store *op) override {
65 if (op->name == buffer) {
66 result = false;
67 }
68 if (result) {
69 IRVisitor::visit(op);
70 }
71 }
72
visit(const Load * op)73 void visit(const Load *op) override {
74 if (op->name == buffer &&
75 !CodeGen_GPU_Dev::is_block_uniform(op->index)) {
76 result = false;
77 }
78 if (result) {
79 IRVisitor::visit(op);
80 }
81 }
82
83 public:
84 bool result;
85 const std::string &buffer;
86
IsBufferConstant(const std::string & b)87 IsBufferConstant(const std::string &b)
88 : result(true), buffer(b) {
89 }
90 };
91 } // namespace
92
is_buffer_constant(const Stmt & kernel,const std::string & buffer)93 bool CodeGen_GPU_Dev::is_buffer_constant(const Stmt &kernel,
94 const std::string &buffer) {
95 IsBufferConstant v(buffer);
96 kernel.accept(&v);
97 return v.result;
98 }
99
100 } // namespace Internal
101 } // namespace Halide
102