summaryrefslogtreecommitdiff
path: root/gcc/gimple-predicate-analysis.h
blob: 09ceebc55a229b67409e1e94e814abcb2132226a (plain)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* Support for simple predicate analysis.

   Copyright (C) 2021-2023 Free Software Foundation, Inc.
   Contributed by Martin Sebor <msebor@redhat.com>

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   GCC is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  */

#ifndef GIMPLE_PREDICATE_ANALYSIS_H_INCLUDED
#define GIMPLE_PREDICATE_ANALYSIS_H_INCLUDED


/* Represents a simple Boolean predicate.  */
struct pred_info
{
  tree pred_lhs;
  tree pred_rhs;
  enum tree_code cond_code;
  bool invert;
};

/* The type to represent a sequence of predicates grouped
   with .AND. operation.  */
typedef vec<pred_info, va_heap, vl_ptr> pred_chain;

/* The type to represent a sequence of pred_chains grouped
   with .OR. operation.  */
typedef vec<pred_chain, va_heap, vl_ptr> pred_chain_union;

/* Represents a complex Boolean predicate expression.  */
class predicate
{
 public:
  /* Construct with the specified EVAL object.  */
  predicate (bool empty_val) : m_preds (vNULL), m_cval (empty_val) { }

  /* Copy.  */
  predicate (const predicate &rhs) : m_preds (vNULL) { *this = rhs; }

  ~predicate ();

  /* Assign.  */
  predicate& operator= (const predicate &);

  bool is_empty () const
  {
    return m_preds.is_empty ();
  }

  bool is_true () const
  {
    return is_empty () && m_cval;
  }

  bool is_false () const
  {
    return is_empty () && !m_cval;
  }

  bool empty_val () const
  {
    return m_cval;
  }

  const pred_chain_union chain () const
  {
    return m_preds;
  }

  void init_from_control_deps (const vec<edge> *, unsigned, bool);

  void dump (FILE *) const;
  void dump (FILE *, gimple *, const char *) const;
  void debug () const;

  void normalize (gimple * = NULL, bool = false);
  void simplify (gimple * = NULL, bool = false);

  bool superset_of (const predicate &) const;

private:

  bool includes (const pred_chain &) const;
  void push_pred (const pred_info &);

  /* Normalization functions.  */
  void normalize (pred_chain *, pred_info, tree_code, pred_chain *,
		  hash_set<tree> *);
  void normalize (const pred_info &);
  void normalize (const pred_chain &);

  /* Simplification functions.  */
  bool simplify_2 ();
  bool simplify_3 ();
  bool simplify_4 ();

  /* Representation of the predicate expression(s).  The predicate is
     m_cval || m_preds[0] || ...  */
  pred_chain_union m_preds;
  bool m_cval;
};

/* Represents a complex Boolean predicate expression.  */
class uninit_analysis
{
 public:
  /* Base function object type used to determine whether an expression
     is of interest.  */
  struct func_t
  {
    typedef unsigned phi_arg_set_t;

    /* Return a bitset of PHI arguments of interest.  By default returns
       bitset with a bit set for each argument.  Should be called in
       the overriden function first and, if nonzero, the result then
       refined as appropriate.  */
    virtual phi_arg_set_t phi_arg_set (gphi *);

    /* Maximum number of PHI arguments supported by phi_arg_set().  */
    static constexpr unsigned max_phi_args =
      sizeof (phi_arg_set_t) * CHAR_BIT;
  };

  /* Construct with the specified EVAL object.  */
  uninit_analysis (func_t &eval)
    : m_phi_def_preds (false), m_eval (eval) { }

  /* Copy.  */
  uninit_analysis (const uninit_analysis &rhs) = delete;

  /* Assign.  */
  uninit_analysis& operator= (const uninit_analysis&) = delete;

  /* Return true if the use by a statement in the basic block of
     a PHI operand is ruled out (i.e., guarded) by *THIS.  */
  bool is_use_guarded (gimple *, basic_block, gphi *, unsigned);

private:
  bool is_use_guarded (gimple *, basic_block, gphi *, unsigned,
		       hash_set<gphi *> *);
  bool prune_phi_opnds (gphi *, unsigned, gphi *, tree, tree_code,
			hash_set<gphi *> *, bitmap *);
  bool overlap (gphi *, unsigned, hash_set<gphi *> *, const predicate &);

  void collect_phi_def_edges (gphi *, basic_block, vec<edge> *,
			      hash_set<gimple *> *);
  bool init_from_phi_def (gphi *);
  bool init_use_preds (predicate &, basic_block, basic_block);


  /* Representation of the predicate expression(s).  */
  predicate m_phi_def_preds;
  /* Callback to evaluate an operand.  Return true if it's interesting.  */
  func_t &m_eval;
};

/* Bit mask handling macros.  */
#define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
#define MASK_TEST_BIT(mask, pos) (mask & (1 << pos))
#define MASK_EMPTY(mask) (mask == 0)

#endif // GIMPLE_PREDICATE_ANALYSIS_H_INCLUDED