| /* { dg-do compile } */ |
| /* { dg-options "-O2 -fdump-tree-sink-stats" } */ |
| |
| #include <stdint.h> |
| |
| #define HLOG 16 |
| #define MAX_LIT (1 << 5) |
| typedef const uint8_t *LZF_HSLOT; |
| typedef LZF_HSLOT LZF_STATE[1 << (HLOG)]; |
| |
| int |
| compute_on_bytes (uint8_t *in_data, int in_len, uint8_t *out_data, int out_len) |
| { |
| LZF_STATE htab; |
| |
| uint8_t *ip = in_data; |
| uint8_t *op = out_data; |
| uint8_t *in_end = ip + in_len; |
| uint8_t *out_end = op + out_len; |
| uint8_t *ref; |
| |
| unsigned long off; |
| unsigned int hval; |
| int lit; |
| |
| if (!in_len || !out_len) |
| return 0; |
| |
| lit = 0; |
| op++; |
| hval = (((ip[0]) << 8) | ip[1]); |
| |
| while (ip < in_end - 2) |
| { |
| uint8_t *hslot; |
| |
| hval = (((hval) << 8) | ip[2]); |
| hslot = (uint8_t*)(htab + (((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))); |
| |
| ref = *hslot + in_data; |
| *hslot = ip - in_data; |
| |
| if (1 && (off = ip - ref - 1) < (1 << 13) && ref > in_data |
| && ref[2] == ip[2] |
| && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0])) |
| { |
| unsigned int len = 2; |
| unsigned int maxlen = in_end - ip - len; |
| maxlen |
| = maxlen > ((1 << 8) + (1 << 3)) ? ((1 << 8) + (1 << 3)) : maxlen; |
| |
| if ((op + 3 + 1 >= out_end) != 0) |
| if (op - !lit + 3 + 1 >= out_end) |
| return 0; |
| |
| op[-lit - 1] = lit - 1; |
| op -= !lit; |
| |
| for (;;) |
| { |
| if (maxlen > 16) |
| { |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| len++; |
| if (ref[len] != ip[len]) |
| break; |
| } |
| |
| do |
| { |
| len++; |
| } |
| while (len < maxlen && ip[len] == ref[len]); |
| |
| break; |
| } |
| |
| len -= 2; |
| ip++; |
| |
| if (len < 7) |
| { |
| *op++ = (off >> 8) + (len << 5); |
| } |
| else |
| { |
| *op++ = (off >> 8) + (7 << 5); |
| *op++ = len - 7; |
| } |
| *op++ = off; |
| lit = 0; |
| op++; |
| ip += len + 1; |
| |
| if (ip >= in_end - 2) |
| break; |
| |
| --ip; |
| --ip; |
| |
| hval = (((ip[0]) << 8) | ip[1]); |
| hval = (((hval) << 8) | ip[2]); |
| htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))] |
| = (LZF_HSLOT)(ip - in_data); |
| ip++; |
| |
| hval = (((hval) << 8) | ip[2]); |
| htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))] |
| = (LZF_HSLOT)(ip - in_data); |
| ip++; |
| } |
| else |
| { |
| if (op >= out_end) |
| return 0; |
| |
| lit++; |
| *op++ = *ip++; |
| |
| if (lit == (1 << 5)) |
| { |
| op[-lit - 1] = lit - 1; |
| lit = 0; |
| op++; |
| } |
| } |
| } |
| if (op + 3 > out_end) /* at most 3 bytes can be missing here */ |
| return 0; |
| |
| while (ip < in_end) |
| { |
| lit++; |
| *op++ = *ip++; |
| if (lit == MAX_LIT) |
| { |
| op[-lit - 1] = lit - 1; /* stop run */ |
| lit = 0; |
| op++; /* start run */ |
| } |
| } |
| |
| op[-lit - 1] = lit - 1; /* end run */ |
| op -= !lit; /* undo run if length is zero */ |
| |
| return op - out_data; |
| } |
| |
| /* For this case, pass sink2 sinks statements from hot loop header to loop |
| exits after gimple loop optimizations, which generates instructions executed |
| each iteration in loop, but the results are used outside of loop: |
| With -m64, |
| "Sinking _367 = (uint8_t *) _320; |
| from bb 31 to bb 90 |
| Sinking _320 = _321 + ivtmp.25_326; |
| from bb 31 to bb 90 |
| Sinking _321 = (unsigned long) ip_229; |
| from bb 31 to bb 90 |
| Sinking len_158 = _322 + 4294967295; |
| from bb 31 to bb 33" |
| When -m32, Power and X86 will sink 3 instructions, but arm ilp32 couldn't |
| sink due to ivopts chooses two IV candidates instead of one, which is |
| expected, so this case is restricted to lp64 only so far. */ |
| |
| /* { dg-final { scan-tree-dump-times "Sunk statements: 4" 1 "sink2" { target lp64 } } } */ |