(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
torture/
asm-x86-linux-array_index_mask_nospec.c
       1  /* { dg-do compile { target x86_64-*-* } } */
       2  /* { dg-require-effective-target lp64 } */
       3  /* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
       4  
       5  #include "../analyzer-decls.h"
       6  
       7  /* Copied from linux: arch/x86/include/asm/barrier.h (GPL-2.0) */
       8  
       9  static inline unsigned long array_index_mask_nospec(unsigned long index,
      10  						    unsigned long size)
      11  {
      12  	unsigned long mask;
      13  
      14  	asm volatile ("cmp %1,%2; sbb %0,%0;"
      15  			:"=r" (mask)
      16  			:"g"(size),"r" (index)
      17  			:"cc");
      18  	return mask;
      19  }
      20  
      21  /* The analyzer ought to treat array_index_mask_nospec as being
      22     effectively pure.  */
      23  
      24  void test_1 (unsigned long index, unsigned long size)
      25  {
      26    unsigned long a = array_index_mask_nospec (index, size);
      27    unsigned long b = array_index_mask_nospec (index, size);
      28    __analyzer_eval (a == b); /* { dg-warning "TRUE" } */
      29  }
      30  
      31  void test_2 (unsigned long index_a, unsigned long size_a,
      32  	     unsigned long index_b, unsigned long size_b)
      33  {
      34    unsigned long aa_1 = array_index_mask_nospec (index_a, size_a);
      35    unsigned long ab_1 = array_index_mask_nospec (index_a, size_b);
      36    unsigned long ba_1 = array_index_mask_nospec (index_b, size_a);
      37    unsigned long bb_1 = array_index_mask_nospec (index_b, size_b);
      38  
      39    unsigned long aa_2 = array_index_mask_nospec (index_a, size_a);
      40    unsigned long ab_2 = array_index_mask_nospec (index_a, size_b);
      41    unsigned long ba_2 = array_index_mask_nospec (index_b, size_a);
      42    unsigned long bb_2 = array_index_mask_nospec (index_b, size_b);
      43  
      44    __analyzer_eval (aa_1 == aa_2); /* { dg-warning "TRUE" } */
      45    __analyzer_eval (ab_1 == ab_2); /* { dg-warning "TRUE" } */
      46    __analyzer_eval (ba_1 == ba_2); /* { dg-warning "TRUE" } */
      47    __analyzer_eval (bb_1 == bb_2); /* { dg-warning "TRUE" } */
      48  
      49    __analyzer_eval (aa_1 == ab_1); /* { dg-warning "UNKNOWN" } */
      50    __analyzer_eval (aa_1 == ba_1); /* { dg-warning "UNKNOWN" } */
      51    __analyzer_eval (aa_1 == bb_1); /* { dg-warning "UNKNOWN" } */
      52  
      53    __analyzer_eval (ab_1 == ba_1); /* { dg-warning "UNKNOWN" } */
      54    __analyzer_eval (ab_1 == bb_1); /* { dg-warning "UNKNOWN" } */
      55  
      56    __analyzer_eval (ba_1 == bb_1); /* { dg-warning "UNKNOWN" } */
      57  }
      58  
      59  /* Equivalent asm strings should be treated the same, rather
      60     than requiring the results to come from the same stmt.  */
      61  
      62  void test_3 (unsigned long index, unsigned long size)
      63  {
      64    unsigned long a = array_index_mask_nospec (index, size);
      65    unsigned long b;
      66  
      67    /* Copy of the asm from array_index_mask_nospec.  */
      68    asm volatile ("cmp %1,%2; sbb %0,%0;"
      69  		:"=r" (b)
      70  		:"g"(size),"r" (index)
      71  		:"cc");
      72  
      73    __analyzer_eval (a == b); /* { dg-warning "TRUE" } */
      74  }