(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
tree-ssa/
ssa-sink-18.c
       1  /* { dg-do compile } */
       2  /* { dg-options "-O2 -fdump-tree-sink-stats" } */
       3  
       4  #include <stdint.h>
       5  
       6  #define HLOG 16
       7  #define        MAX_LIT        (1 <<  5)
       8  typedef const uint8_t *LZF_HSLOT;
       9  typedef LZF_HSLOT LZF_STATE[1 << (HLOG)];
      10  
      11  int
      12  compute_on_bytes (uint8_t *in_data, int in_len, uint8_t *out_data, int out_len)
      13  {
      14    LZF_STATE htab;
      15  
      16    uint8_t *ip = in_data;
      17    uint8_t *op = out_data;
      18    uint8_t *in_end = ip + in_len;
      19    uint8_t *out_end = op + out_len;
      20    uint8_t *ref;
      21  
      22    unsigned long off;
      23    unsigned int hval;
      24    int lit;
      25  
      26    if (!in_len || !out_len)
      27      return 0;
      28  
      29    lit = 0;
      30    op++;
      31    hval = (((ip[0]) << 8) | ip[1]);
      32  
      33    while (ip < in_end - 2)
      34      {
      35        uint8_t *hslot;
      36  
      37        hval = (((hval) << 8) | ip[2]);
      38        hslot = (uint8_t*)(htab + (((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1)));
      39  
      40        ref = *hslot + in_data;
      41        *hslot = ip - in_data;
      42  
      43        if (1 && (off = ip - ref - 1) < (1 << 13) && ref > in_data
      44  	  && ref[2] == ip[2]
      45  	  && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0]))
      46  	{
      47  	  unsigned int len = 2;
      48  	  unsigned int maxlen = in_end - ip - len;
      49  	  maxlen
      50  	    = maxlen > ((1 << 8) + (1 << 3)) ? ((1 << 8) + (1 << 3)) : maxlen;
      51  
      52  	  if ((op + 3 + 1 >= out_end) != 0)
      53  	    if (op - !lit + 3 + 1 >= out_end)
      54  	      return 0;
      55  
      56  	  op[-lit - 1] = lit - 1;
      57  	  op -= !lit;
      58  
      59  	  for (;;)
      60  	    {
      61  	      if (maxlen > 16)
      62  		{
      63  		  len++;
      64  		  if (ref[len] != ip[len])
      65  		    break;
      66  		  len++;
      67  		  if (ref[len] != ip[len])
      68  		    break;
      69  		  len++;
      70  		  if (ref[len] != ip[len])
      71  		    break;
      72  		  len++;
      73  		  if (ref[len] != ip[len])
      74  		    break;
      75  
      76  		  len++;
      77  		  if (ref[len] != ip[len])
      78  		    break;
      79  		  len++;
      80  		  if (ref[len] != ip[len])
      81  		    break;
      82  		  len++;
      83  		  if (ref[len] != ip[len])
      84  		    break;
      85  		  len++;
      86  		  if (ref[len] != ip[len])
      87  		    break;
      88  
      89  		  len++;
      90  		  if (ref[len] != ip[len])
      91  		    break;
      92  		  len++;
      93  		  if (ref[len] != ip[len])
      94  		    break;
      95  		  len++;
      96  		  if (ref[len] != ip[len])
      97  		    break;
      98  		  len++;
      99  		  if (ref[len] != ip[len])
     100  		    break;
     101  
     102  		  len++;
     103  		  if (ref[len] != ip[len])
     104  		    break;
     105  		  len++;
     106  		  if (ref[len] != ip[len])
     107  		    break;
     108  		  len++;
     109  		  if (ref[len] != ip[len])
     110  		    break;
     111  		  len++;
     112  		  if (ref[len] != ip[len])
     113  		    break;
     114  		}
     115  
     116  	      do
     117  		{
     118  		  len++;
     119  		}
     120  	      while (len < maxlen && ip[len] == ref[len]);
     121  
     122  	      break;
     123  	    }
     124  
     125  	  len -= 2;
     126  	  ip++;
     127  
     128  	  if (len < 7)
     129  	    {
     130  	      *op++ = (off >> 8) + (len << 5);
     131  	    }
     132  	  else
     133  	    {
     134  	      *op++ = (off >> 8) + (7 << 5);
     135  	      *op++ = len - 7;
     136  	    }
     137  	  *op++ = off;
     138  	  lit = 0;
     139  	  op++;
     140  	  ip += len + 1;
     141  
     142  	  if (ip >= in_end - 2)
     143  	    break;
     144  
     145  	  --ip;
     146  	  --ip;
     147  
     148  	  hval = (((ip[0]) << 8) | ip[1]);
     149  	  hval = (((hval) << 8) | ip[2]);
     150  	  htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))]
     151  	    = (LZF_HSLOT)(ip - in_data);
     152  	  ip++;
     153  
     154  	  hval = (((hval) << 8) | ip[2]);
     155  	  htab[(((hval >> (3 * 8 - 16)) - hval * 5) & ((1 << (16)) - 1))]
     156  	    = (LZF_HSLOT)(ip - in_data);
     157  	  ip++;
     158  	}
     159        else
     160  	{
     161  	  if (op >= out_end)
     162  	    return 0;
     163  
     164  	  lit++;
     165  	  *op++ = *ip++;
     166  
     167  	  if (lit == (1 << 5))
     168  	    {
     169  	      op[-lit - 1] = lit - 1;
     170  	      lit = 0;
     171  	      op++;
     172  	    }
     173  	}
     174      }
     175    if (op + 3 > out_end) /* at most 3 bytes can be missing here */
     176      return 0;
     177  
     178    while (ip < in_end)
     179      {
     180        lit++;
     181        *op++ = *ip++;
     182        if (lit == MAX_LIT)
     183  	{
     184  	  op[-lit - 1] = lit - 1; /* stop run */
     185  	  lit = 0;
     186  	  op++; /* start run */
     187  	}
     188      }
     189  
     190    op[-lit - 1] = lit - 1; /* end run */
     191    op -= !lit;		  /* undo run if length is zero */
     192  
     193    return op - out_data;
     194   }
     195  
     196   /* For this case, pass sink2 sinks statements from hot loop header to loop
     197      exits after gimple loop optimizations, which generates instructions executed
     198      each iteration in loop, but the results are used outside of loop:
     199      With -m64,
     200      "Sinking _367 = (uint8_t *) _320;
     201      from bb 31 to bb 90
     202      Sinking _320 = _321 + ivtmp.25_326;
     203      from bb 31 to bb 90
     204      Sinking _321 = (unsigned long) ip_229;
     205      from bb 31 to bb 90
     206      Sinking len_158 = _322 + 4294967295;
     207      from bb 31 to bb 33"
     208      When -m32, Power and X86 will sink 3 instructions, but arm ilp32 couldn't
     209      sink due to ivopts chooses two IV candidates instead of one, which is
     210      expected, so this case is restricted to lp64 only so far.  This different
     211      ivopts choice affects riscv64 as well, probably because it also lacks
     212      base+index addressing modes, so the ip[len] address computation can't be
     213      made from the IV computation above.  */
     214  
     215   /* { dg-final { scan-tree-dump-times "Sunk statements: 4" 1 "sink2" { target lp64 xfail { riscv64-*-* } } } } */