File: irrelevant_value_facts.cpp

package info (click to toggle)
spirv-tools 2020.6-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 21,636 kB
  • sloc: cpp: 366,576; javascript: 5,849; python: 2,551; ansic: 387; sh: 327; ruby: 88; makefile: 19; lisp: 9
file content (133 lines) | stat: -rw-r--r-- 4,536 bytes parent folder | download | duplicates (18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/fuzz/fact_manager/irrelevant_value_facts.h"

#include "source/fuzz/data_descriptor.h"
#include "source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h"
#include "source/fuzz/fact_manager/dead_block_facts.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/opt/ir_context.h"

namespace spvtools {
namespace fuzz {
namespace fact_manager {

IrrelevantValueFacts::IrrelevantValueFacts(opt::IRContext* ir_context)
    : ir_context_(ir_context) {}

bool IrrelevantValueFacts::MaybeAddFact(
    const protobufs::FactPointeeValueIsIrrelevant& fact,
    const DataSynonymAndIdEquationFacts& data_synonym_and_id_equation_facts) {
  const auto* inst = ir_context_->get_def_use_mgr()->GetDef(fact.pointer_id());
  if (!inst || !inst->type_id()) {
    // The id must exist in the module and have type id.
    return false;
  }

  if (!ir_context_->get_type_mgr()->GetType(inst->type_id())->AsPointer()) {
    // The id must be a pointer.
    return false;
  }

  if (!data_synonym_and_id_equation_facts.GetSynonymsForId(fact.pointer_id())
           .empty()) {
    // Irrelevant id cannot participate in DataSynonym facts.
    return false;
  }

  pointers_to_irrelevant_pointees_ids_.insert(fact.pointer_id());
  return true;
}

bool IrrelevantValueFacts::MaybeAddFact(
    const protobufs::FactIdIsIrrelevant& fact,
    const DataSynonymAndIdEquationFacts& data_synonym_and_id_equation_facts) {
  const auto* inst = ir_context_->get_def_use_mgr()->GetDef(fact.result_id());
  if (!inst || !inst->type_id()) {
    // The id must exist in the module and have type id.
    return false;
  }

  if (ir_context_->get_type_mgr()->GetType(inst->type_id())->AsPointer()) {
    // The id may not be a pointer.
    return false;
  }

  if (!data_synonym_and_id_equation_facts.GetSynonymsForId(fact.result_id())
           .empty()) {
    // Irrelevant id cannot participate in DataSynonym facts.
    return false;
  }

  irrelevant_ids_.insert(fact.result_id());
  return true;
}

bool IrrelevantValueFacts::PointeeValueIsIrrelevant(uint32_t pointer_id) const {
  return pointers_to_irrelevant_pointees_ids_.count(pointer_id) != 0;
}

bool IrrelevantValueFacts::IdIsIrrelevant(
    uint32_t result_id, const DeadBlockFacts& dead_block_facts) const {
  // The id is irrelevant if it has been declared irrelevant.
  if (irrelevant_ids_.count(result_id)) {
    return true;
  }

  // The id must have a non-pointer type to be irrelevant.
  auto def = ir_context_->get_def_use_mgr()->GetDef(result_id);
  if (!def) {
    return false;
  }
  auto type = ir_context_->get_type_mgr()->GetType(def->type_id());
  if (!type || type->AsPointer()) {
    return false;
  }

  // The id is irrelevant if it is in a dead block.
  return ir_context_->get_instr_block(result_id) &&
         dead_block_facts.BlockIsDead(
             ir_context_->get_instr_block(result_id)->id());
}

std::unordered_set<uint32_t> IrrelevantValueFacts::GetIrrelevantIds(
    const DeadBlockFacts& dead_block_facts) const {
  // Get all the ids that have been declared irrelevant.
  auto irrelevant_ids = irrelevant_ids_;

  // Get all the non-pointer ids declared in dead blocks that have a type.
  for (uint32_t block_id : dead_block_facts.GetDeadBlocks()) {
    auto block = fuzzerutil::MaybeFindBlock(ir_context_, block_id);
    // It is possible and allowed for the block not to exist, e.g. it could have
    // been merged with another block.
    if (!block) {
      continue;
    }
    block->ForEachInst([this, &irrelevant_ids](opt::Instruction* inst) {
      // The instruction must have a result id and a type, and it must not be a
      // pointer.
      if (inst->HasResultId() && inst->type_id() &&
          !ir_context_->get_type_mgr()->GetType(inst->type_id())->AsPointer()) {
        irrelevant_ids.emplace(inst->result_id());
      }
    });
  }

  return irrelevant_ids;
}

}  // namespace fact_manager
}  // namespace fuzz
}  // namespace spvtools