Skip to content

Commit 35b8a3a

Browse files
committed
Avoid promote-to-int on comparison
Suppress unnecessary cast. Still needed if signed-ness are different.
1 parent 2263cfc commit 35b8a3a

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

src/cc/frontend/expr.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,23 @@ static bool cast_numbers(Expr **pLhs, Expr **pRhs, bool make_int) {
188188
enum FixnumKind rkind = rtype->fixnum.kind;
189189
bool changed = false;
190190
if (ltype->fixnum.kind >= FX_ENUM) {
191-
ltype = &tyInt;
192-
lkind = FX_INT;
191+
if (make_int) {
192+
ltype = &tyInt;
193+
lkind = FX_INT;
194+
} else {
195+
ltype = get_fixnum_type_from_size(type_size(ltype));
196+
lkind = ltype->fixnum.kind;
197+
}
193198
changed = true;
194199
}
195200
if (rtype->fixnum.kind >= FX_ENUM) {
196-
rtype = &tyInt;
197-
rkind = FX_INT;
201+
if (make_int) {
202+
rtype = &tyInt;
203+
rkind = FX_INT;
204+
} else {
205+
rtype = get_fixnum_type_from_size(type_size(rtype));
206+
rkind = rtype->fixnum.kind;
207+
}
198208
changed = true;
199209
}
200210

@@ -1179,6 +1189,7 @@ Expr *make_expr_cmp(enum ExprKind kind, const Token *tok, Expr *lhs, Expr *rhs)
11791189
{
11801190
Type *lt = lhs->type, *rt = rhs->type;
11811191
if (is_number(lt) && is_number(rt)) {
1192+
bool make_int = false;
11821193
if (is_fixnum(lt) && is_fixnum(rt)) {
11831194
if (lc || rc) {
11841195
Expr **pLhs = &lhs, **pRhs = &rhs;
@@ -1197,14 +1208,37 @@ Expr *make_expr_cmp(enum ExprKind kind, const Token *tok, Expr *lhs, Expr *rhs)
11971208
// Cast constant as non-const type.
11981209
*pRhs = make_cast(dst_type, (*pRhs)->token, *pRhs, false);
11991210
} else {
1200-
if (lt->fixnum.kind < FX_INT)
1201-
lhs = promote_to_int(lhs);
1202-
if (rt->fixnum.kind < FX_INT)
1203-
rhs = promote_to_int(rhs);
1211+
bool lu = lt->fixnum.is_unsigned;
1212+
bool ru = rt->fixnum.is_unsigned;
1213+
make_int = lu != ru;
1214+
if (lu != ru) {
1215+
size_t ls = type_size(lt), rs = type_size(rt);
1216+
if (MAX(ls, rs) >= type_size(&tyInt)) {
1217+
make_int = true;
1218+
} else {
1219+
// Avoid promote-to-int
1220+
// Cast to larger signed type.
1221+
if (ls >= rs) {
1222+
if (lt->fixnum.is_unsigned) {
1223+
lt = get_fixnum_type_from_size(ls);
1224+
lhs = make_cast(lt, lhs->token, lhs, false);
1225+
}
1226+
rhs = make_cast(lt, rhs->token, rhs, false);
1227+
rt = lt;
1228+
} else {
1229+
if (rt->fixnum.is_unsigned) {
1230+
rt = get_fixnum_type_from_size(ls);
1231+
rhs = make_cast(rt, rhs->token, rhs, false);
1232+
}
1233+
lhs = make_cast(rt, lhs->token, lhs, false);
1234+
lt = rt;
1235+
}
1236+
}
1237+
}
12041238
}
12051239
}
12061240
if (!(is_fixnum(lt) && is_fixnum(rt)) || !(lc || rc)) {
1207-
if (!cast_numbers(&lhs, &rhs, false)) {
1241+
if (!cast_numbers(&lhs, &rhs, make_int)) {
12081242
parse_error(PE_NOFATAL, tok, "cannot compare except numbers");
12091243
return new_expr_fixlit(&tyBool, tok, 0);
12101244
}

0 commit comments

Comments
 (0)