1  /* { dg-do compile { target aarch64-*-* } } */
       2  /* { dg-options "-O2" } */
       3  /*
       4     Tests are:
       5        Patterns allow subs/adds with a stack pointer source.
       6        define_peephole2's don't generate patterns for subs/adds with a stack
       7        pointer destination.
       8   */
       9  
      10  /* These functions used to ICE due to using the stack pointer as a source
      11     register.  */
      12  
      13  int __RTL (startwith ("final"))
      14  adds ()
      15  {
      16  (function "adds"
      17    (insn-chain
      18      (block 2
      19        (edge-from entry (flags "FALLTHRU"))
      20        (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
      21        (cinsn 101 (parallel [
      22  	    (set (reg:CC cc)
      23  		(compare:CC (reg/f:DI sp)
      24  		    (const_int -3)))
      25  	    (set (reg/f:DI x19)
      26  		(plus:DI (reg/f:DI sp)
      27  		    (const_int 3)))
      28  	]))
      29        ;; Extra insn to avoid the above being deleted by DCE.
      30        (cinsn 10 (use (reg/i:SI x19)))
      31        (cinsn 11 (use (reg/i:SI sp)))
      32        (edge-to exit (flags "FALLTHRU"))
      33      ) ;; block 2
      34    ) ;; insn-chain
      35  ) ;; function "main"
      36  }
      37  
      38  int __RTL (startwith ("final"))
      39  subs ()
      40  {
      41  (function "subs"
      42    (insn-chain
      43      (block 2
      44        (edge-from entry (flags "FALLTHRU"))
      45        (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
      46        (cinsn 101 (parallel [
      47  	    (set (reg:CC cc)
      48  		(compare:CC (reg/f:DI sp)
      49  		    (const_int 3)))
      50  	    (set (reg/f:DI x19)
      51  		(plus:DI (reg/f:DI sp)
      52  		    (const_int -3)))
      53  	]))
      54        ;; Extra insn to avoid the above being deleted by DCE.
      55        (cinsn 10 (use (reg/i:SI x19)))
      56        (cinsn 11 (use (reg/i:SI sp)))
      57        (edge-to exit (flags "FALLTHRU"))
      58      ) ;; block 2
      59    ) ;; insn-chain
      60  ) ;; function "main"
      61  }
      62  
      63  /* These functions used to trigger peepholes generating invalid SUBS patterns
      64     that used the stack pointer for the destination register.  */
      65  
      66  int __RTL (startwith ("peephole2")) sub3_compare1_peephole_1 ()
      67  {
      68  (function "sub3_compare1_peephole_1"
      69    (insn-chain
      70      (block 2
      71        (edge-from entry (flags "FALLTHRU"))
      72        (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
      73        (cinsn 89 (set (reg:DI sp)
      74  		 (minus:DI (reg:DI x2) (reg:DI x5))))
      75        (cinsn 90 (set (reg:CC cc)
      76  		 (compare:CC (reg:DI x2) (reg:DI x5))))
      77        ;; Extra insn to avoid the above being deleted by DCE.
      78        (cinsn 12 (use (reg/i:DI cc)))
      79        (cinsn 11 (use (reg/i:DI sp)))
      80        (edge-to exit (flags "FALLTHRU"))
      81      ) ;; block 2
      82    ) ;; insn-chain
      83  ) ;; function "main"
      84  }
      85  
      86  int __RTL (startwith ("peephole2")) sub3_compare1_peephole_2 ()
      87  {
      88  (function "sub3_compare1_peephole_2"
      89    (insn-chain
      90      (block 2
      91        (edge-from entry (flags "FALLTHRU"))
      92        (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
      93        (cinsn 90 (set (reg:CC cc)
      94  		 (compare:CC (reg:DI x2) (reg:DI x5))))
      95        (cinsn 89 (set (reg:DI sp)
      96  		 (minus:DI (reg:DI x2) (reg:DI x5))))
      97        ;; Extra insn to avoid the above being deleted by DCE.
      98        (cinsn 12 (use (reg/i:DI cc)))
      99        (cinsn 11 (use (reg/i:DI sp)))
     100        (edge-to exit (flags "FALLTHRU"))
     101      ) ;; block 2
     102    ) ;; insn-chain
     103  ) ;; function "main"
     104  }
     105  
     106  int __RTL (startwith ("peephole2")) sub3_compare1_imm_peephole_1 ()
     107  {
     108  (function "sub3_compare1_imm_peephole_1"
     109    (insn-chain
     110      (block 2
     111        (edge-from entry (flags "FALLTHRU"))
     112        (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
     113        (cinsn 90 (set (reg:CC cc)
     114  		 (compare:CC (reg:DI x2) (reg:DI x5))))
     115        (cinsn 89 (set (reg:DI sp)
     116  		 (minus:DI (reg:DI x2) (reg:DI x5))))
     117        ;; Extra insn to avoid the above being deleted by DCE.
     118        (cinsn 12 (use (reg/i:DI cc)))
     119        (cinsn 11 (use (reg/i:DI sp)))
     120        (edge-to exit (flags "FALLTHRU"))
     121      ) ;; block 2
     122    ) ;; insn-chain
     123  ) ;; function "main"
     124  }
     125  
     126  int __RTL (startwith ("peephole2")) sub3_compare1_imm_peephole_2 ()
     127  {
     128  (function "sub3_compare1_imm_peephole_1"
     129    (insn-chain
     130      (block 2
     131        (edge-from entry (flags "FALLTHRU"))
     132        (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
     133        (cinsn 89 (set (reg:DI sp)
     134  		 (minus:DI (reg:DI x2) (reg:DI x5))))
     135        (cinsn 90 (set (reg:CC cc)
     136  		 (compare:CC (reg:DI x2) (reg:DI x5))))
     137        ;; Extra insn to avoid the above being deleted by DCE.
     138        (cinsn 12 (use (reg/i:DI cc)))
     139        (cinsn 11 (use (reg/i:DI sp)))
     140        (edge-to exit (flags "FALLTHRU"))
     141      ) ;; block 2
     142    ) ;; insn-chain
     143  ) ;; function "main"
     144  }
     145  
     146  /* Verify that the adds and subs functions generated their respective
     147     instructions, and that none of the other functions generated either since
     148     they are setting the stack pointer.  */
     149  /* { dg-final { scan-assembler-times {adds\tx[0-9]+, sp} 1 } }  */
     150  /* { dg-final { scan-assembler-not {adds\tsp} } }  */
     151  /* { dg-final { scan-assembler-times {subs\tx[0-9]+, sp} 1 } }  */
     152  /* { dg-final { scan-assembler-not {subs\tsp} } }  */
     153