1  /* Check that GCC generates Armv8.1-M low over head loop instructions
       2     with some less trivial loops and the result is correct.  */
       3  /* { dg-do run } */
       4  /* { dg-require-effective-target arm_v8_1_lob_ok } */
       5  /* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
       6  /* { dg-options "-march=armv8.1-m.main -mthumb -O3 --save-temps" } */
       7  #include <stdlib.h>
       8  #include "lob.h"
       9  
      10  #define TEST_CODE1				\
      11    {						\
      12      for (int i = 0; i < N; i++)			\
      13        {						\
      14  	a[i] = i;				\
      15  	b[i] = i * 2;				\
      16  						\
      17  	for (int k = 0; k < N; k++)		\
      18  	  {					\
      19  	    MAYBE_LOB;				\
      20  	    c[k] = k / 2;			\
      21  	  }					\
      22  	c[i] = a[i] - b[i];			\
      23        }						\
      24    }
      25  
      26  #define TEST_CODE2				\
      27    {						\
      28      for (int i = 0; i < N / 2; i++)		\
      29        {						\
      30  	MAYBE_LOB;				\
      31  	if (c[i] % 2 == 0)			\
      32  	  break;				\
      33  	a[i]++;					\
      34  	b[i]++;					\
      35        }						\
      36    }
      37  
      38  int a1[N];
      39  int b1[N];
      40  int c1[N];
      41  
      42  int a2[N];
      43  int b2[N];
      44  int c2[N];
      45  
      46  #define MAYBE_LOB
      47  void __attribute__((noinline))
      48  loop1 (int *a, int *b, int *c)
      49    TEST_CODE1;
      50  
      51  void __attribute__((noinline))
      52  loop2 (int *a, int *b, int *c)
      53    TEST_CODE2;
      54  
      55  #undef MAYBE_LOB
      56  #define MAYBE_LOB NO_LOB
      57  
      58  void
      59  ref1 (int *a, int *b, int *c)
      60    TEST_CODE1;
      61  
      62  void
      63  ref2 (int *a, int *b, int *c)
      64    TEST_CODE2;
      65  
      66  void
      67  check (void)
      68  {
      69    for (int i = 0; i < N; i++)
      70      {
      71        NO_LOB;
      72        if (a1[i] != a2[i]
      73  	  && b1[i] != b2[i]
      74  	  && c1[i] != c2[i])
      75  	abort ();
      76      }
      77  }
      78  
      79  int
      80  main (void)
      81  {
      82    reset_data (a1, b1, c1);
      83    reset_data (a2, b2, c2);
      84    loop1 (a1, b1, c1);
      85    ref1 (a2, b2, c2);
      86    check ();
      87  
      88    reset_data (a1, b1, c1);
      89    reset_data (a2, b2, c2);
      90    loop2 (a1, b1, c1);
      91    ref2 (a2, b2, c2);
      92    check ();
      93  
      94    return 0;
      95  }
      96  /* { dg-final { scan-assembler-times {dls\s\S*,\s\S*} 1 } } */
      97  /* { dg-final { scan-assembler-times {le\slr,\s\S*} 1 } } */