4 iscon(Ref r
, int64_t bits
, Fn
*fn
)
6 return rtype(r
) == RCon
7 && fn
->con
[r
.val
].type
== CBits
8 && fn
->con
[r
.val
].bits
.i
== bits
;
12 iscopy(Ins
*i
, Ref r
, Fn
*fn
)
14 static bits extcpy
[] = {
16 [Wsb
] = BIT(Wsb
) | BIT(Wsh
) | BIT(Wsw
),
17 [Wub
] = BIT(Wub
) | BIT(Wuh
) | BIT(Wuw
),
18 [Wsh
] = BIT(Wsh
) | BIT(Wsw
),
19 [Wuh
] = BIT(Wuh
) | BIT(Wuw
),
30 if (op
->hasid
&& KBASE(i
->cls
) == 0)
31 return iscon(i
->arg
[1], op
->idval
, fn
);
32 if (!isext(i
->op
) || rtype(r
) != RTmp
)
34 if (i
->op
== Oextsw
|| i
->op
== Oextuw
)
39 assert(KBASE(t
->cls
) == 0);
40 if (i
->cls
== Kl
&& t
->cls
== Kw
)
43 return (BIT(Wsb
+ (i
->op
-Oextsb
)) & b
) != 0;
47 copyof(Ref r
, Ref
*cpy
)
49 if (rtype(r
) == RTmp
&& !req(cpy
[r
.val
], R
))
54 /* detects a cluster of phis/copies redundant with 'r';
55 * the algorithm is inspired by Section 3.2 of "Simple
56 * and Efficient SSA Construction" by Braun M. et al.
59 phisimpl(Phi
*p
, Ref r
, Ref
*cpy
, Use
***pstk
, BSet
*ts
, BSet
*as
, Fn
*fn
)
69 p0
= &(Phi
){.narg
= 0};
72 stk
[0] = &(Use
){.type
= UPhi
, .u
.phi
= p
};
75 if (u
->type
== UIns
&& iscopy(u
->u
.ins
, r
, fn
)) {
79 else if (u
->type
== UPhi
) {
88 for (a
=0; a
<p
->narg
; a
++) {
89 r1
= copyof(p
->arg
[a
], cpy
);
92 if (rtype(r1
) != RTmp
)
97 u1
= &u
[fn
->tmp
[t
].nuse
];
98 vgrow(pstk
, nstk
+(u1
-u
));
105 for (t
=0; bsiter(ts
, &t
); t
++)
110 subst(Ref
*pr
, Ref
*cpy
)
112 assert(rtype(*pr
) != RTmp
|| !req(cpy
[pr
->val
], R
));
113 *pr
= copyof(*pr
, cpy
);
116 /* requires use and dom, breaks use */
129 bsinit(ts
, fn
->ntmp
);
130 bsinit(as
, fn
->ntmp
);
131 cpy
= emalloc(fn
->ntmp
* sizeof cpy
[0]);
132 stk
= vnew(10, sizeof stk
[0], PHeap
);
134 /* 1. build the copy-of map */
135 for (n
=0; n
<fn
->nblk
; n
++) {
137 for (p
=b
->phi
; p
; p
=p
->link
) {
138 assert(rtype(p
->to
) == RTmp
);
139 if (!req(cpy
[p
->to
.val
], R
))
143 for (a
=0; a
<p
->narg
; a
++)
144 if (p
->blk
[a
]->id
< n
) {
145 r1
= copyof(p
->arg
[a
], cpy
);
146 if (req(r
, R
) || req(r
, UNDEF
))
148 if (req(r1
, r
) || req(r1
, UNDEF
))
153 && !dom(fn
->rpo
[fn
->tmp
[r
.val
].bid
], b
))
154 cpy
[p
->to
.val
] = p
->to
;
155 else if (eq
== p
->narg
)
158 cpy
[p
->to
.val
] = p
->to
;
159 phisimpl(p
, r
, cpy
, &stk
, ts
, as
, fn
);
162 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++) {
163 assert(rtype(i
->to
) <= RTmp
);
164 if (!req(cpy
[i
->to
.val
], R
))
166 r
= copyof(i
->arg
[0], cpy
);
167 if (iscopy(i
, r
, fn
))
170 cpy
[i
->to
.val
] = i
->to
;
174 /* 2. remove redundant phis/copies
175 * and rewrite their uses */
176 for (b
=fn
->start
; b
; b
=b
->link
) {
177 for (pp
=&b
->phi
; (p
=*pp
);) {
179 if (!req(r
, p
->to
)) {
183 for (a
=0; a
<p
->narg
; a
++)
184 subst(&p
->arg
[a
], cpy
);
187 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++) {
189 if (!req(r
, i
->to
)) {
190 *i
= (Ins
){.op
= Onop
};
193 subst(&i
->arg
[0], cpy
);
194 subst(&i
->arg
[1], cpy
);
196 subst(&b
->jmp
.arg
, cpy
);
200 fprintf(stderr
, "\n> Copy information:");
201 for (t
=Tmp0
; t
<fn
->ntmp
; t
++) {
202 if (req(cpy
[t
], R
)) {
203 fprintf(stderr
, "\n%10s not seen!",
206 else if (!req(cpy
[t
], TMP(t
))) {
207 fprintf(stderr
, "\n%10s copy of ",
209 printref(cpy
[t
], fn
, stderr
);
212 fprintf(stderr
, "\n\n> After copy elimination:\n");