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
),
32 return iscon(i
->arg
[1], 1, fn
);
40 return iscon(i
->arg
[1], 0, fn
);
44 if (!isext(i
->op
) || rtype(r
) != RTmp
)
46 if (i
->op
== Oextsw
|| i
->op
== Oextuw
)
51 assert(KBASE(t
->cls
) == 0);
52 if (i
->cls
== Kl
&& t
->cls
== Kw
)
55 return (BIT(Wsb
+ (i
->op
-Oextsb
)) & b
) != 0;
59 copyof(Ref r
, Ref
*cpy
)
61 if (rtype(r
) == RTmp
&& !req(cpy
[r
.val
], R
))
66 /* detects a cluster of phis/copies redundant with 'r';
67 * the algorithm is inspired by Section 3.2 of "Simple
68 * and Efficient SSA Construction" by Braun M. et al.
71 phisimpl(Phi
*p
, Ref r
, Ref
*cpy
, Use
***pstk
, BSet
*ts
, BSet
*as
, Fn
*fn
)
81 p0
= &(Phi
){.narg
= 0};
84 stk
[0] = &(Use
){.type
= UPhi
, .u
.phi
= p
};
87 if (u
->type
== UIns
&& iscopy(u
->u
.ins
, r
, fn
)) {
91 else if (u
->type
== UPhi
) {
100 for (a
=0; a
<p
->narg
; a
++) {
101 r1
= copyof(p
->arg
[a
], cpy
);
104 if (rtype(r1
) != RTmp
)
109 u1
= &u
[fn
->tmp
[t
].nuse
];
110 vgrow(pstk
, nstk
+(u1
-u
));
117 for (t
=0; bsiter(ts
, &t
); t
++)
122 subst(Ref
*pr
, Ref
*cpy
)
124 assert(rtype(*pr
) != RTmp
|| !req(cpy
[pr
->val
], R
));
125 *pr
= copyof(*pr
, cpy
);
128 /* requires use and dom, breaks use */
141 bsinit(ts
, fn
->ntmp
);
142 bsinit(as
, fn
->ntmp
);
143 cpy
= emalloc(fn
->ntmp
* sizeof cpy
[0]);
144 stk
= vnew(10, sizeof stk
[0], PHeap
);
146 /* 1. build the copy-of map */
147 for (n
=0; n
<fn
->nblk
; n
++) {
149 for (p
=b
->phi
; p
; p
=p
->link
) {
150 assert(rtype(p
->to
) == RTmp
);
151 if (!req(cpy
[p
->to
.val
], R
))
155 for (a
=0; a
<p
->narg
; a
++)
156 if (p
->blk
[a
]->id
< n
) {
157 r1
= copyof(p
->arg
[a
], cpy
);
158 if (req(r
, R
) || req(r
, UNDEF
))
160 if (req(r1
, r
) || req(r1
, UNDEF
))
165 && !dom(fn
->rpo
[fn
->tmp
[r
.val
].bid
], b
))
166 cpy
[p
->to
.val
] = p
->to
;
167 else if (eq
== p
->narg
)
170 cpy
[p
->to
.val
] = p
->to
;
171 phisimpl(p
, r
, cpy
, &stk
, ts
, as
, fn
);
174 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++) {
175 assert(rtype(i
->to
) <= RTmp
);
176 if (!req(cpy
[i
->to
.val
], R
))
178 r
= copyof(i
->arg
[0], cpy
);
179 if (iscopy(i
, r
, fn
))
182 cpy
[i
->to
.val
] = i
->to
;
186 /* 2. remove redundant phis/copies
187 * and rewrite their uses */
188 for (b
=fn
->start
; b
; b
=b
->link
) {
189 for (pp
=&b
->phi
; (p
=*pp
);) {
191 if (!req(r
, p
->to
)) {
195 for (a
=0; a
<p
->narg
; a
++)
196 subst(&p
->arg
[a
], cpy
);
199 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++) {
201 if (!req(r
, i
->to
)) {
202 *i
= (Ins
){.op
= Onop
};
205 subst(&i
->arg
[0], cpy
);
206 subst(&i
->arg
[1], cpy
);
208 subst(&b
->jmp
.arg
, cpy
);
212 fprintf(stderr
, "\n> Copy information:");
213 for (t
=Tmp0
; t
<fn
->ntmp
; t
++) {
214 if (req(cpy
[t
], R
)) {
215 fprintf(stderr
, "\n%10s not seen!",
218 else if (!req(cpy
[t
], TMP(t
))) {
219 fprintf(stderr
, "\n%10s copy of ",
221 printref(cpy
[t
], fn
, stderr
);
224 fprintf(stderr
, "\n\n> After copy elimination:\n");