aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdmund Grimley Evans <Edmund.Grimley.Evans@gmail.com>2015-03-07 11:25:27 +0000
committerEdmund Grimley Evans <Edmund.Grimley.Evans@gmail.com>2015-03-07 17:32:39 +0000
commitac70e6b84040dc24a065013cdf30ff44d98cc670 (patch)
treec3a6654bda699e940172a64a04d0f9bb5d0bcb6b
parent916339347642b7b22d3cfa18bf5058ffbfe74679 (diff)
downloadtinycc-ac70e6b84040dc24a065013cdf30ff44d98cc670.tar.gz
tinycc-ac70e6b84040dc24a065013cdf30ff44d98cc670.tar.bz2
tccgen.c: Optimise 0<<x, 0>>x, -1>>x, x&0, x*0, x|-1, x%1.
More precisely, treat (0 << x) and so on as constant expressions, but not if const_wanted as we do not want to allow "case (x*0):", ... Do not optimise (0 / x) and (0 % x) here as x might be zero, though for an architecture that does not generate an exception for division by zero the back end might choose to optimise those.
-rw-r--r--tccgen.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/tccgen.c b/tccgen.c
index 9a6f3c9..adc5005 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -1476,16 +1476,31 @@ static void gen_opic(int op)
c2 = c1; //c = c1, c1 = c2, c2 = c;
l2 = l1; //l = l1, l1 = l2, l2 = l;
}
- /* Filter out NOP operations like x*1, x-0, x&-1... */
- if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
- op == TOK_PDIV) &&
- l2 == 1) ||
- ((op == '+' || op == '-' || op == '|' || op == '^' ||
- op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
- l2 == 0) ||
- (op == '&' &&
- l2 == -1))) {
- /* nothing to do */
+ if (!const_wanted &&
+ c1 && ((l1 == 0 &&
+ (op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) ||
+ (l1 == -1 && op == TOK_SAR))) {
+ /* treat (0 << x), (0 >> x) and (-1 >> x) as constant */
+ vtop--;
+ } else if (!const_wanted &&
+ c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
+ (l2 == -1 && op == '|') ||
+ (l2 == 0xffffffff && t2 != VT_LLONG && op == '|') ||
+ (l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
+ /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */
+ if (l2 == 1)
+ vtop->c.ll = 0;
+ vswap();
+ vtop--;
+ } else if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
+ op == TOK_PDIV) &&
+ l2 == 1) ||
+ ((op == '+' || op == '-' || op == '|' || op == '^' ||
+ op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
+ l2 == 0) ||
+ (op == '&' &&
+ l2 == -1))) {
+ /* filter out NOP operations like x*1, x-0, x&-1... */
vtop--;
} else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
/* try to use shifts instead of muls or divs */