@@ -29,7 +29,7 @@ IR_ALWAYS_INLINE ir_ref ir_sccp_identity(ir_insn *_values, ir_ref a)
29
29
{
30
30
if (a > 0 && _values [a ].op == IR_COPY ) {
31
31
a = _values [a ].op1 ;
32
- IR_ASSERT (a <= 0 || _values [a ].op != IR_COPY );
32
+ IR_ASSERT (a > 0 && _values [a ].op != IR_COPY );
33
33
}
34
34
return a ;
35
35
}
@@ -69,16 +69,23 @@ static ir_ref ir_sccp_fold(ir_ctx *ctx, ir_insn *_values, ir_ref res, uint32_t o
69
69
if (IR_IS_CONST_OP (insn -> op )) {
70
70
/* pass */
71
71
#if IR_COMBO_COPY_PROPAGATION
72
- } else if (IR_IS_TOP ( res ) ) {
72
+ } else if (_values [ res ]. optx == IR_TOP ) {
73
73
_values [res ].optx = IR_OPT (IR_COPY , insn -> type );
74
74
_values [res ].op1 = op1 ;
75
75
return 1 ;
76
76
} else if (_values [res ].op == IR_COPY && _values [res ].op1 == op1 ) {
77
77
return 0 ; /* not changed */
78
- #endif
78
+ } else {
79
+ IR_ASSERT (_values [res ].optx != IR_BOTTOM );
80
+ /* we don't check for widening */
81
+ _values [res ].optx = IR_OPT (IR_COPY , insn -> type );
82
+ _values [res ].op1 = op1 ;
83
+ return 1 ;
84
+ #else
79
85
} else {
80
86
IR_MAKE_BOTTOM (res );
81
87
return 1 ;
88
+ #endif
82
89
}
83
90
break ;
84
91
case IR_FOLD_DO_CONST :
@@ -100,36 +107,148 @@ static ir_ref ir_sccp_fold(ir_ctx *ctx, ir_insn *_values, ir_ref res, uint32_t o
100
107
return 0 ; /* not changed */
101
108
}
102
109
103
- static bool ir_sccp_join_values (ir_ctx * ctx , ir_insn * _values , ir_ref a , ir_ref b )
110
+ static bool ir_sccp_meet_phi (ir_ctx * ctx , ir_insn * _values , ir_ref i , ir_insn * insn , ir_bitqueue * worklist )
104
111
{
105
- ir_insn * v ;
112
+ ir_ref j , n , input , * merge_input , * p ;
113
+ ir_insn * v , * new_const = NULL ;
114
+ #if IR_COMBO_COPY_PROPAGATION
115
+ ir_ref new_copy ;
116
+ #endif
117
+
118
+ if (!IR_IS_FEASIBLE (insn -> op1 )) {
119
+ return 0 ;
120
+ }
121
+ n = insn -> inputs_count ;
122
+ if (n > 3 && _values [i ].optx == IR_TOP ) {
123
+ for (j = 0 ; j < (n >>2 ); j ++ ) {
124
+ _values [i + j + 1 ].optx = IR_BOTTOM ; /* keep the tail of a long multislot instruction */
125
+ }
126
+ }
127
+
128
+ p = insn -> ops + 2 ;
129
+ merge_input = ctx -> ir_base [insn -> op1 ].ops + 1 ;
130
+ for (; -- n > 0 ; p ++ , merge_input ++ ) {
131
+ IR_ASSERT (* merge_input > 0 );
132
+ if (_values [* merge_input ].optx == IR_TOP ) {
133
+ continue ;
134
+ }
106
135
107
- if (!IR_IS_BOTTOM (a ) && !IR_IS_TOP (b )) {
108
- b = ir_sccp_identity (_values , b );
109
- v = IR_IS_CONST_REF (b ) ? & ctx -> ir_base [b ] : & _values [b ];
110
- if (IR_IS_TOP (a )) {
136
+ input = * p ;
137
+ if (IR_IS_CONST_REF (input )) {
138
+ v = & ctx -> ir_base [input ];
139
+ } else if (input == i ) {
140
+ continue ;
141
+ } else {
142
+ v = & _values [input ];
143
+ if (v -> op == IR_TOP ) {
144
+ /* do backward propagaton only once */
145
+ if (!v -> op1 ) {
146
+ v -> op1 = 1 ;
147
+ ir_bitqueue_add (worklist , input );
148
+ }
149
+ continue ;
111
150
#if IR_COMBO_COPY_PROPAGATION
112
- if (v -> op == IR_BOTTOM ) {
113
- _values [a ].optx = IR_OPT (IR_COPY , ctx -> ir_base [b ].type );
114
- _values [a ].op1 = b ;
151
+ } else if (v -> op == IR_COPY ) {
152
+ input = v -> op1 ;
153
+ IR_ASSERT (input > 0 && _values [input ].op != IR_COPY );
154
+ new_copy = input ;
155
+ goto next ;
156
+ } else if (v -> op == IR_BOTTOM ) {
157
+ new_copy = input ;
158
+ goto next ;
159
+ #else
160
+ } else if (v -> op == IR_BOTTOM ) {
161
+ IR_MAKE_BOTTOM (i );
115
162
return 1 ;
116
- }
117
163
#endif
118
- _values [a ].optx = v -> opt ;
119
- _values [a ].val .u64 = v -> val .u64 ;
120
- return 1 ;
121
- } else if (_values [a ].opt == v -> opt && _values [a ].val .u64 == v -> val .u64 ) {
122
- /* pass */
164
+ }
165
+ }
166
+ new_copy = IR_UNUSED ;
167
+ new_const = v ;
168
+ goto next ;
169
+ }
170
+
171
+ IR_ASSERT (_values [i ].optx == IR_TOP );
172
+ return 0 ;
173
+
174
+ next :
175
+ p ++ ;
176
+ merge_input ++ ;
177
+ /* for all live merge inputs */
178
+ for (; -- n > 0 ; p ++ , merge_input ++ ) {
179
+ IR_ASSERT (* merge_input > 0 );
180
+ if (_values [* merge_input ].optx == IR_TOP ) {
181
+ continue ;
182
+ }
183
+
184
+ input = * p ;
185
+ if (IR_IS_CONST_REF (input )) {
186
+ v = & ctx -> ir_base [input ];
187
+ } else if (input == i ) {
188
+ continue ;
189
+ } else {
190
+ v = & _values [input ];
191
+ if (v -> op == IR_TOP ) {
192
+ /* do backward propagaton only once */
193
+ if (!v -> op1 ) {
194
+ v -> op1 = 1 ;
195
+ ir_bitqueue_add (worklist , input );
196
+ }
197
+ continue ;
123
198
#if IR_COMBO_COPY_PROPAGATION
124
- } else if (_values [a ].op == IR_COPY && _values [a ].op1 == b ) {
125
- /* pass */
199
+ } else if (v -> op == IR_COPY ) {
200
+ input = v -> op1 ;
201
+ IR_ASSERT (input > 0 && _values [input ].op != IR_COPY );
202
+ if (new_copy == input ) {
203
+ continue ;
204
+ } else {
205
+ IR_MAKE_BOTTOM (i );
206
+ return 1 ;
207
+ }
208
+ } else if (v -> op == IR_BOTTOM ) {
209
+ if (new_copy == input ) {
210
+ continue ;
211
+ } else {
212
+ IR_MAKE_BOTTOM (i );
213
+ return 1 ;
214
+ }
215
+ #else
216
+ } else if (v -> op == IR_BOTTOM ) {
217
+ IR_MAKE_BOTTOM (i );
218
+ return 1 ;
126
219
#endif
220
+ }
221
+ }
222
+ if (!new_const || new_const -> opt != v -> opt || new_const -> val .u64 != v -> val .u64 ) {
223
+ IR_MAKE_BOTTOM (i );
224
+ return 1 ;
225
+ }
226
+ }
227
+
228
+ #if IR_COMBO_COPY_PROPAGATION
229
+ if (new_copy ) {
230
+ if (_values [i ].op == IR_COPY && _values [i ].op1 == new_copy ) {
231
+ return 0 ; /* not changed */
127
232
} else {
128
- IR_MAKE_BOTTOM (a );
233
+ IR_ASSERT (_values [i ].optx != IR_BOTTOM );
234
+ /* we don't check for widening */
235
+ _values [i ].optx = IR_OPT (IR_COPY , ctx -> ir_base [new_copy ].type );
236
+ _values [i ].op1 = new_copy ;
129
237
return 1 ;
130
238
}
131
239
}
132
- return 0 ;
240
+ #endif
241
+
242
+ if (_values [i ].optx == IR_TOP ) {
243
+ _values [i ].optx = new_const -> opt ;
244
+ _values [i ].val .u64 = new_const -> val .u64 ;
245
+ return 1 ;
246
+ } else if (_values [i ].opt == new_const -> opt && _values [i ].val .u64 == new_const -> val .u64 ) {
247
+ return 0 ;
248
+ } else {
249
+ IR_MAKE_BOTTOM (i );
250
+ return 1 ;
251
+ }
133
252
}
134
253
135
254
static bool ir_sccp_is_true (ir_ctx * ctx , ir_insn * _values , ir_ref a )
@@ -585,38 +704,7 @@ int ir_sccp(ir_ctx *ctx)
585
704
flags = ir_op_flags [insn -> op ];
586
705
if (flags & IR_OP_FLAG_DATA ) {
587
706
if (insn -> op == IR_PHI ) {
588
- ir_insn * merge_insn = & ctx -> ir_base [insn -> op1 ];
589
- bool changed = 0 ;
590
-
591
- if (!IR_IS_FEASIBLE (insn -> op1 )) {
592
- continue ;
593
- }
594
- n = merge_insn -> inputs_count + 1 ;
595
- if (n > 3 && _values [i ].optx == IR_TOP ) {
596
- for (j = 0 ; j < (n >>2 ); j ++ ) {
597
- _values [i + j + 1 ].optx = IR_BOTTOM ; /* keep the tail of a long multislot instruction */
598
- }
599
- }
600
- /* for all live merge inputs */
601
- for (j = 1 ; j < n ; j ++ ) {
602
- ir_ref merge_input = ir_insn_op (merge_insn , j );
603
-
604
- IR_ASSERT (merge_input > 0 );
605
- if (_values [merge_input ].optx != IR_TOP ) {
606
- ir_ref input = ir_insn_op (insn , j + 1 );
607
-
608
- if (input > 0 && IR_IS_TOP (input )) {
609
- /* do backward propagaton only once */
610
- if (!_values [input ].op1 ) {
611
- _values [input ].op1 = 1 ;
612
- ir_bitqueue_add (& worklist , input );
613
- }
614
- } else if (ir_sccp_join_values (ctx , _values , i , input )) {
615
- changed = 1 ;
616
- }
617
- }
618
- }
619
- if (!changed ) {
707
+ if (!ir_sccp_meet_phi (ctx , _values , i , insn , & worklist )) {
620
708
continue ;
621
709
}
622
710
} else if (ctx -> use_lists [i ].count == 0 ) {
0 commit comments