don't convert to 1/0 prematurely, we can save enough info in the VT_CMP metadata to be usable for the gtst branch expansion.
Unified · Split
| @@ -285,8 +285,42 @@ ST_FUNC void load(int r, SValue *sv) · 284 unmodified lines | ||
| 285 | 285 | o(0x53 | (rr << 7) | ((is_freg(v) ? freg(v) : ireg(v)) << 15) |
| 286 | 286 | | (func7 << 25)); // fmv.{w.x, x.w, d.x, x.d} RR, VR |
| 287 | 287 | } |
| 288 | − } else if (v == VT_CMP) { // we rely on cmp_r to be the correct result | |
| 289 | − EI(0x13, 0, rr, vtop->cmp_r, 0); // mv RR, CMP_R | |
| 288 | + } else if (v == VT_CMP) { | |
| 289 | + int op = vtop->cmp_op; | |
| 290 | + int a = vtop->cmp_r & 0xff; | |
| 291 | + int b = (vtop->cmp_r >> 8) & 0xff; | |
| 292 | + int inv = 0; | |
| 293 | + switch (op) { | |
| 294 | + case TOK_ULT: | |
| 295 | + case TOK_UGE: | |
| 296 | + case TOK_ULE: | |
| 297 | + case TOK_UGT: | |
| 298 | + case TOK_LT: | |
| 299 | + case TOK_GE: | |
| 300 | + case TOK_LE: | |
| 301 | + case TOK_GT: | |
| 302 | + if (op & 1) { // remove [U]GE,GT | |
| 303 | + inv = 1; | |
| 304 | + op--; | |
| 305 | + } | |
| 306 | + if ((op & 7) == 6) { // [U]LE | |
| 307 | + int t = a; a = b; b = t; | |
| 308 | + inv ^= 1; | |
| 309 | + } | |
| 310 | + ER(0x33, (op > TOK_UGT) ? 2 : 3, rr, a, b, 0); // slt[u] d, a, b | |
| 311 | + if (inv) | |
| 312 | + EI(0x13, 4, rr, rr, 1); // xori d, d, 1 | |
| 313 | + break; | |
| 314 | + case TOK_NE: | |
| 315 | + case TOK_EQ: | |
| 316 | + if (rr != a || b) | |
| 317 | + ER(0x33, 0, rr, a, b, 0x20); // sub d, a, b | |
| 318 | + if (op == TOK_NE) | |
| 319 | + ER(0x33, 3, rr, 0, rr, 0); // sltu d, x0, d == snez d,d | |
| 320 | + else | |
| 321 | + EI(0x13, 3, rr, rr, 1); // sltiu d, d, 1 == seqz d,d | |
| 322 | + break; | |
| 323 | + } | |
| 290 | 324 | } else if ((v & ~1) == VT_JMP) { |
| 291 | 325 | int t = v & 1; |
| 292 | 326 | assert(is_ireg(r)); |
| @@ -775,10 +809,22 @@ ST_FUNC void gjmp_addr(int a) · 482 unmodified lines | ||
| 775 | 809 | |
| 776 | 810 | ST_FUNC int gjmp_cond(int op, int t) |
| 777 | 811 | { |
| 778 | − int inv = op & 1; | |
| 779 | − assert(op == TOK_EQ || op == TOK_NE); | |
| 780 | − assert(vtop->cmp_r >= 10 && vtop->cmp_r < 18); | |
| 781 | − o(0x63 | (!inv << 12) | (vtop->cmp_r << 15) | (8 << 7)); // bne/beq x0,r,+4 | |
| 812 | + int tmp; | |
| 813 | + int a = vtop->cmp_r & 0xff; | |
| 814 | + int b = (vtop->cmp_r >> 8) & 0xff; | |
| 815 | + switch (op) { | |
| 816 | + case TOK_ULT: op = 6; break; | |
| 817 | + case TOK_UGE: op = 7; break; | |
| 818 | + case TOK_ULE: op = 7; tmp = a; a = b; b = tmp; break; | |
| 819 | + case TOK_UGT: op = 6; tmp = a; a = b; b = tmp; break; | |
| 820 | + case TOK_LT: op = 4; break; | |
| 821 | + case TOK_GE: op = 5; break; | |
| 822 | + case TOK_LE: op = 5; tmp = a; a = b; b = tmp; break; | |
| 823 | + case TOK_GT: op = 4; tmp = a; a = b; b = tmp; break; | |
| 824 | + case TOK_NE: op = 1; break; | |
| 825 | + case TOK_EQ: op = 0; break; | |
| 826 | + } | |
| 827 | + o(0x63 | (op ^ 1) << 12 | a << 15 | b << 20 | 8 << 7); // bOP a,b,+4 | |
| 782 | 828 | return gjmp(t); |
| 783 | 829 | } |
| 784 | 830 | |
| @@ -799,7 +845,6 @@ ST_FUNC int gjmp_append(int n, int t) · 14 unmodified lines | ||
| 799 | 845 | static void gen_opil(int op, int ll) |
| 800 | 846 | { |
| 801 | 847 | int a, b, d; |
| 802 | − int inv = 0; | |
| 803 | 848 | int func3 = 0; |
| 804 | 849 | ll = ll ? 0 : 8; |
| 805 | 850 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| @@ -823,7 +868,11 @@ static void gen_opil(int op, int ll) · 17 unmodified lines | ||
| 823 | 868 | do_cop: |
| 824 | 869 | EI(0x13 | cll, func3, ireg(d), a, fc); |
| 825 | 870 | --vtop; |
| 826 | − vtop[0].r = d; | |
| 871 | + if (op >= TOK_ULT && op <= TOK_GT) { | |
| 872 | + vset_VT_CMP(TOK_NE); | |
| 873 | + vtop->cmp_r = ireg(d) | 0 << 8; | |
| 874 | + } else | |
| 875 | + vtop[0].r = d; | |
| 827 | 876 | return; |
| 828 | 877 | case TOK_LE: |
| 829 | 878 | if (fc >= (1 << 11) - 1) |
| @@ -847,19 +896,16 @@ static void gen_opil(int op, int ll) · 17 unmodified lines | ||
| 847 | 896 | case TOK_GE: |
| 848 | 897 | case TOK_GT: |
| 849 | 898 | gen_opil(op - 1, ll); |
| 850 | − EI(0x13, 4, ireg(vtop->r), ireg(vtop->r), 1);// xori d, d, 1 | |
| 899 | + vtop->cmp_op ^= 1; | |
| 851 | 900 | return; |
| 852 | 901 | |
| 853 | 902 | case TOK_NE: |
| 854 | 903 | case TOK_EQ: |
| 855 | 904 | if (fc) |
| 856 | 905 | gen_opil('-', ll), a = ireg(vtop++->r); |
| 857 | − if (op == TOK_NE) | |
| 858 | − ER(0x33, 3, ireg(d), 0, a, 0); //sltu d, x0, a == snez d,a | |
| 859 | − else | |
| 860 | − EI(0x13, 3, ireg(d), a, 1); // sltiu d, a, 1 == seqz d,a | |
| 861 | 906 | --vtop; |
| 862 | − vtop[0].r = d; | |
| 907 | + vset_VT_CMP(op); | |
| 908 | + vtop->cmp_r = a | 0 << 8; | |
| 863 | 909 | return; |
| 864 | 910 | } |
| 865 | 911 | } |
| @@ -874,7 +920,13 @@ static void gen_opil(int op, int ll) · 8 unmodified lines | ||
| 874 | 920 | d = ireg(d); |
| 875 | 921 | switch (op) { |
| 876 | 922 | default: |
| 923 | + if (op >= TOK_ULT && op <= TOK_GT) { | |
| 924 | + vset_VT_CMP(op); | |
| 925 | + vtop->cmp_r = a | b << 8; | |
| 926 | + break; | |
| 927 | + } | |
| 877 | 928 | tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL)); |
| 929 | + break; | |
| 878 | 930 | |
| 879 | 931 | case '+': |
| 880 | 932 | ER(0x33, 0, d, a, b, 0); // add d, a, b |
| @@ -916,39 +968,6 @@ static void gen_opil(int op, int ll) · 35 unmodified lines | ||
| 916 | 968 | case TOK_UDIV: |
| 917 | 969 | ER(0x33, 5, d, a, b, 1); // divu d, a, b |
| 918 | 970 | break; |
| 919 | − | |
| 920 | − case TOK_ULT: | |
| 921 | − case TOK_UGE: | |
| 922 | − case TOK_ULE: | |
| 923 | − case TOK_UGT: | |
| 924 | − case TOK_LT: | |
| 925 | − case TOK_GE: | |
| 926 | − case TOK_LE: | |
| 927 | − case TOK_GT: | |
| 928 | − if (op & 1) { // remove [U]GE,GT | |
| 929 | − inv = 1; | |
| 930 | − op--; | |
| 931 | − } | |
| 932 | − if ((op & 7) == 6) { // [U]LE | |
| 933 | − int t = a; a = b; b = t; | |
| 934 | − inv ^= 1; | |
| 935 | − } | |
| 936 | − ER(0x33, (op > TOK_UGT) ? 2 : 3, d, a, b, 0); // slt[u] d, a, b | |
| 937 | − if (inv) | |
| 938 | − EI(0x13, 4, d, d, 1); // xori d, d, 1 | |
| 939 | − vset_VT_CMP(TOK_NE); | |
| 940 | − vtop->cmp_r = d; | |
| 941 | − break; | |
| 942 | − case TOK_NE: | |
| 943 | − case TOK_EQ: | |
| 944 | − ER(0x33, 0, d, a, b, 0x20); // sub d, a, b | |
| 945 | − if (op == TOK_NE) | |
| 946 | − ER(0x33, 3, d, 0, d, 0); // sltu d, x0, d == snez d,d | |
| 947 | − else | |
| 948 | − EI(0x13, 3, d, d, 1); // sltiu d, d, 1 == seqz d,d | |
| 949 | − vset_VT_CMP(TOK_NE); | |
| 950 | − vtop->cmp_r = d; | |
| 951 | − break; | |
| 952 | 971 | } |
| 953 | 972 | } |
| 954 | 973 | |