remove tail recursion, simplify
Unified · Split
| @@ -4906,35 +4906,9 @@ static int gcase(struct case_t **base, int len, int case_reg, int *bsym) · 4905 unmodified lines | ||
| 4906 | 4906 | { |
| 4907 | 4907 | struct case_t *p; |
| 4908 | 4908 | int e; |
| 4909 | − if (len <= 4) { | |
| 4910 | − while (len--) { | |
| 4911 | − p = *base++; | |
| 4912 | − vseti(case_reg, 0); | |
| 4913 | − vdup(); | |
| 4914 | − vpushi(p->v2); | |
| 4915 | − if (p->v1 == p->v2) { | |
| 4916 | − gen_op(TOK_EQ); | |
| 4917 | − gtst_addr(0, p->sym); | |
| 4918 | − case_reg = gv(RC_INT); | |
| 4919 | − vpop(); | |
| 4920 | − } else { | |
| 4921 | − gen_op(TOK_LE); | |
| 4922 | − e = gtst(1, 0); | |
| 4923 | − case_reg = gv(RC_INT); | |
| 4924 | − vpop(); | |
| 4925 | − vseti(case_reg, 0); | |
| 4926 | − vdup(); | |
| 4927 | − vpushi(p->v1); | |
| 4928 | − gen_op(TOK_GE); | |
| 4929 | − gtst_addr(0, p->sym); | |
| 4930 | − case_reg = gv(RC_INT); | |
| 4931 | − vpop(); | |
| 4932 | − gsym(e); | |
| 4933 | − } | |
| 4934 | − } | |
| 4935 | − } else { | |
| 4909 | + while (len > 4) { | |
| 4910 | + /* binary search */ | |
| 4936 | 4911 | p = base[len/2]; |
| 4937 | − /* mid */ | |
| 4938 | 4912 | vseti(case_reg, 0); |
| 4939 | 4913 | vdup(); |
| 4940 | 4914 | vpushi(p->v2); |
| @@ -4946,19 +4920,43 @@ static int gcase(struct case_t **base, int len, int case_reg, int *bsym) · 5 unmodified lines | ||
| 4946 | 4920 | vdup(); |
| 4947 | 4921 | vpushi(p->v1); |
| 4948 | 4922 | gen_op(TOK_GE); |
| 4949 | − gtst_addr(0, p->sym); | |
| 4923 | + gtst_addr(0, p->sym); /* v1 <= x <= v2 */ | |
| 4950 | 4924 | case_reg = gv(RC_INT); |
| 4951 | 4925 | vpop(); |
| 4952 | − /* left */ | |
| 4926 | + /* x < v1 */ | |
| 4953 | 4927 | case_reg = gcase(base, len/2, case_reg, bsym); |
| 4954 | 4928 | if (cur_switch->def_sym) |
| 4955 | 4929 | gjmp_addr(cur_switch->def_sym); |
| 4956 | 4930 | else |
| 4957 | 4931 | *bsym = gjmp(*bsym); |
| 4958 | − /* right */ | |
| 4932 | + /* x > v2 */ | |
| 4959 | 4933 | gsym(e); |
| 4960 | 4934 | e = len/2 + 1; |
| 4961 | − case_reg = gcase(base + e, len - e, case_reg, bsym); | |
| 4935 | + base += e; len -= e; | |
| 4936 | + } | |
| 4937 | + /* linear scan */ | |
| 4938 | + while (len--) { | |
| 4939 | + p = *base++; | |
| 4940 | + vseti(case_reg, 0); | |
| 4941 | + vdup(); | |
| 4942 | + vpushi(p->v2); | |
| 4943 | + if (p->v1 == p->v2) { | |
| 4944 | + gen_op(TOK_EQ); | |
| 4945 | + gtst_addr(0, p->sym); | |
| 4946 | + } else { | |
| 4947 | + gen_op(TOK_LE); | |
| 4948 | + e = gtst(1, 0); | |
| 4949 | + case_reg = gv(RC_INT); | |
| 4950 | + vpop(); | |
| 4951 | + vseti(case_reg, 0); | |
| 4952 | + vdup(); | |
| 4953 | + vpushi(p->v1); | |
| 4954 | + gen_op(TOK_GE); | |
| 4955 | + gtst_addr(0, p->sym); | |
| 4956 | + gsym(e); | |
| 4957 | + } | |
| 4958 | + case_reg = gv(RC_INT); | |
| 4959 | + vpop(); | |
| 4962 | 4960 | } |
| 4963 | 4961 | return case_reg; |
| 4964 | 4962 | } |
| @@ -5245,7 +5243,8 @@ static void block(int *bsym, int *csym, int is_expr) · 280 unmodified lines | ||
| 5245 | 5243 | b = gjmp(0); /* jump to first case */ |
| 5246 | 5244 | sw.p = NULL; sw.n = 0; sw.def_sym = 0; |
| 5247 | 5245 | saved = cur_switch; |
| 5248 | − cur_switch = &sw; block(&a, csym, 0); | |
| 5246 | + cur_switch = &sw; | |
| 5247 | + block(&a, csym, 0); | |
| 5249 | 5248 | a = gjmp(a); /* add implicit break */ |
| 5250 | 5249 | /* case lookup */ |
| 5251 | 5250 | gsym(b); |