Home | History | Annotate | Download | only in SystemZ
      1 ; Test the handling of base + index + 12-bit displacement addresses for
      2 ; large frames, in cases where no 20-bit form exists.  The tests here
      3 ; assume z10 register pressure, without the high words being available.
      4 ;
      5 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | \
      6 ; RUN:   FileCheck -check-prefix=CHECK-NOFP %s
      7 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -disable-fp-elim | \
      8 ; RUN:   FileCheck -check-prefix=CHECK-FP %s
      9 
     10 declare void @foo(float *%ptr1, float *%ptr2)
     11 
     12 ; This file tests what happens when a displacement is converted from
     13 ; being relative to the start of a frame object to being relative to
     14 ; the frame itself.  In some cases the test is only possible if two
     15 ; objects are allocated.
     16 ;
     17 ; Rather than rely on a particular order for those objects, the tests
     18 ; instead allocate two objects of the same size and apply the test to
     19 ; both of them.  For consistency, all tests follow this model, even if
     20 ; one object would actually be enough.
     21 
     22 ; First check the highest in-range offset after conversion, which is 4092
     23 ; for word-addressing instructions like LDEB.
     24 ;
     25 ; The last in-range doubleword offset is 4088.  Since the frame has two
     26 ; emergency spill slots at 160(%r15), the amount that we need to allocate
     27 ; in order to put another object at offset 4088 is (4088 - 176) / 4 = 978
     28 ; words.
     29 define void @f1(double *%dst) {
     30 ; CHECK-NOFP-LABEL: f1:
     31 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r15)
     32 ; CHECK-NOFP: br %r14
     33 ;
     34 ; CHECK-FP-LABEL: f1:
     35 ; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r11)
     36 ; CHECK-FP: br %r14
     37   %region1 = alloca [978 x float], align 8
     38   %region2 = alloca [978 x float], align 8
     39   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
     40   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
     41   call void @foo(float *%start1, float *%start2)
     42   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 1
     43   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 1
     44   %float1 = load float , float *%ptr1
     45   %float2 = load float , float *%ptr2
     46   %double1 = fpext float %float1 to double
     47   %double2 = fpext float %float2 to double
     48   store volatile double %double1, double *%dst
     49   store volatile double %double2, double *%dst
     50   ret void
     51 }
     52 
     53 ; Test the first out-of-range offset.
     54 define void @f2(double *%dst) {
     55 ; CHECK-NOFP-LABEL: f2:
     56 ; CHECK-NOFP: lghi %r1, 4096
     57 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1,%r15)
     58 ; CHECK-NOFP: br %r14
     59 ;
     60 ; CHECK-FP-LABEL: f2:
     61 ; CHECK-FP: lghi %r1, 4096
     62 ; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1,%r11)
     63 ; CHECK-FP: br %r14
     64   %region1 = alloca [978 x float], align 8
     65   %region2 = alloca [978 x float], align 8
     66   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
     67   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
     68   call void @foo(float *%start1, float *%start2)
     69   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 2
     70   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 2
     71   %float1 = load float , float *%ptr1
     72   %float2 = load float , float *%ptr2
     73   %double1 = fpext float %float1 to double
     74   %double2 = fpext float %float2 to double
     75   store volatile double %double1, double *%dst
     76   store volatile double %double2, double *%dst
     77   ret void
     78 }
     79 
     80 ; Test the next offset after that.
     81 define void @f3(double *%dst) {
     82 ; CHECK-NOFP-LABEL: f3:
     83 ; CHECK-NOFP: lghi %r1, 4096
     84 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)
     85 ; CHECK-NOFP: br %r14
     86 ;
     87 ; CHECK-FP-LABEL: f3:
     88 ; CHECK-FP: lghi %r1, 4096
     89 ; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)
     90 ; CHECK-FP: br %r14
     91   %region1 = alloca [978 x float], align 8
     92   %region2 = alloca [978 x float], align 8
     93   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
     94   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
     95   call void @foo(float *%start1, float *%start2)
     96   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 3
     97   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 3
     98   %float1 = load float , float *%ptr1
     99   %float2 = load float , float *%ptr2
    100   %double1 = fpext float %float1 to double
    101   %double2 = fpext float %float2 to double
    102   store volatile double %double1, double *%dst
    103   store volatile double %double2, double *%dst
    104   ret void
    105 }
    106 
    107 ; Add 4096 bytes (1024 words) to the size of each object and repeat.
    108 define void @f4(double *%dst) {
    109 ; CHECK-NOFP-LABEL: f4:
    110 ; CHECK-NOFP: lghi %r1, 4096
    111 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r1,%r15)
    112 ; CHECK-NOFP: br %r14
    113 ;
    114 ; CHECK-FP-LABEL: f4:
    115 ; CHECK-FP: lghi %r1, 4096
    116 ; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r1,%r11)
    117 ; CHECK-FP: br %r14
    118   %region1 = alloca [2002 x float], align 8
    119   %region2 = alloca [2002 x float], align 8
    120   %start1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 0
    121   %start2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 0
    122   call void @foo(float *%start1, float *%start2)
    123   %ptr1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 1
    124   %ptr2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 1
    125   %float1 = load float , float *%ptr1
    126   %float2 = load float , float *%ptr2
    127   %double1 = fpext float %float1 to double
    128   %double2 = fpext float %float2 to double
    129   store volatile double %double1, double *%dst
    130   store volatile double %double2, double *%dst
    131   ret void
    132 }
    133 
    134 ; ...as above.
    135 define void @f5(double *%dst) {
    136 ; CHECK-NOFP-LABEL: f5:
    137 ; CHECK-NOFP: lghi %r1, 8192
    138 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1,%r15)
    139 ; CHECK-NOFP: br %r14
    140 ;
    141 ; CHECK-FP-LABEL: f5:
    142 ; CHECK-FP: lghi %r1, 8192
    143 ; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1,%r11)
    144 ; CHECK-FP: br %r14
    145   %region1 = alloca [2002 x float], align 8
    146   %region2 = alloca [2002 x float], align 8
    147   %start1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 0
    148   %start2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 0
    149   call void @foo(float *%start1, float *%start2)
    150   %ptr1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 2
    151   %ptr2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 2
    152   %float1 = load float , float *%ptr1
    153   %float2 = load float , float *%ptr2
    154   %double1 = fpext float %float1 to double
    155   %double2 = fpext float %float2 to double
    156   store volatile double %double1, double *%dst
    157   store volatile double %double2, double *%dst
    158   ret void
    159 }
    160 
    161 ; ...as above.
    162 define void @f6(double *%dst) {
    163 ; CHECK-NOFP-LABEL: f6:
    164 ; CHECK-NOFP: lghi %r1, 8192
    165 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)
    166 ; CHECK-NOFP: br %r14
    167 ;
    168 ; CHECK-FP-LABEL: f6:
    169 ; CHECK-FP: lghi %r1, 8192
    170 ; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)
    171 ; CHECK-FP: br %r14
    172   %region1 = alloca [2002 x float], align 8
    173   %region2 = alloca [2002 x float], align 8
    174   %start1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 0
    175   %start2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 0
    176   call void @foo(float *%start1, float *%start2)
    177   %ptr1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 3
    178   %ptr2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 3
    179   %float1 = load float , float *%ptr1
    180   %float2 = load float , float *%ptr2
    181   %double1 = fpext float %float1 to double
    182   %double2 = fpext float %float2 to double
    183   store volatile double %double1, double *%dst
    184   store volatile double %double2, double *%dst
    185   ret void
    186 }
    187 
    188 ; Now try an offset of 4092 from the start of the object, with the object
    189 ; being at offset 8192.  This time we need objects of (8192 - 168) / 4 = 2004
    190 ; words.
    191 define void @f7(double *%dst) {
    192 ; CHECK-NOFP-LABEL: f7:
    193 ; CHECK-NOFP: lghi %r1, 8192
    194 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r1,%r15)
    195 ; CHECK-NOFP: br %r14
    196 ;
    197 ; CHECK-FP-LABEL: f7:
    198 ; CHECK-FP: lghi %r1, 8192
    199 ; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r1,%r11)
    200 ; CHECK-FP: br %r14
    201   %region1 = alloca [2004 x float], align 8
    202   %region2 = alloca [2004 x float], align 8
    203   %start1 = getelementptr inbounds [2004 x float], [2004 x float]* %region1, i64 0, i64 0
    204   %start2 = getelementptr inbounds [2004 x float], [2004 x float]* %region2, i64 0, i64 0
    205   call void @foo(float *%start1, float *%start2)
    206   %ptr1 = getelementptr inbounds [2004 x float], [2004 x float]* %region1, i64 0, i64 1023
    207   %ptr2 = getelementptr inbounds [2004 x float], [2004 x float]* %region2, i64 0, i64 1023
    208   %float1 = load float , float *%ptr1
    209   %float2 = load float , float *%ptr2
    210   %double1 = fpext float %float1 to double
    211   %double2 = fpext float %float2 to double
    212   store volatile double %double1, double *%dst
    213   store volatile double %double2, double *%dst
    214   ret void
    215 }
    216 
    217 ; Keep the object-relative offset the same but bump the size of the
    218 ; objects by one doubleword.
    219 define void @f8(double *%dst) {
    220 ; CHECK-NOFP-LABEL: f8:
    221 ; CHECK-NOFP: lghi %r1, 12288
    222 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)
    223 ; CHECK-NOFP: br %r14
    224 ;
    225 ; CHECK-FP-LABEL: f8:
    226 ; CHECK-FP: lghi %r1, 12288
    227 ; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)
    228 ; CHECK-FP: br %r14
    229   %region1 = alloca [2006 x float], align 8
    230   %region2 = alloca [2006 x float], align 8
    231   %start1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 0
    232   %start2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 0
    233   call void @foo(float *%start1, float *%start2)
    234   %ptr1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 1023
    235   %ptr2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 1023
    236   %float1 = load float , float *%ptr1
    237   %float2 = load float , float *%ptr2
    238   %double1 = fpext float %float1 to double
    239   %double2 = fpext float %float2 to double
    240   store volatile double %double1, double *%dst
    241   store volatile double %double2, double *%dst
    242   ret void
    243 }
    244 
    245 ; Check a case where the original displacement is out of range.  The backend
    246 ; should force an LAY from the outset.  We don't yet do any kind of anchor
    247 ; optimization, so there should be no offset on the LDEB itself.
    248 define void @f9(double *%dst) {
    249 ; CHECK-NOFP-LABEL: f9:
    250 ; CHECK-NOFP: lay %r1, 12296(%r15)
    251 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1)
    252 ; CHECK-NOFP: br %r14
    253 ;
    254 ; CHECK-FP-LABEL: f9:
    255 ; CHECK-FP: lay %r1, 12296(%r11)
    256 ; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1)
    257 ; CHECK-FP: br %r14
    258   %region1 = alloca [2006 x float], align 8
    259   %region2 = alloca [2006 x float], align 8
    260   %start1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 0
    261   %start2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 0
    262   call void @foo(float *%start1, float *%start2)
    263   %ptr1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 1024
    264   %ptr2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 1024
    265   %float1 = load float , float *%ptr1
    266   %float2 = load float , float *%ptr2
    267   %double1 = fpext float %float1 to double
    268   %double2 = fpext float %float2 to double
    269   store volatile double %double1, double *%dst
    270   store volatile double %double2, double *%dst
    271   ret void
    272 }
    273 
    274 ; Repeat f2 in a case that needs the emergency spill slots, because all
    275 ; call-clobbered and allocated call-saved registers are live.  Note that
    276 ; %vptr and %dst are copied to call-saved registers, freeing up %r2 and
    277 ; %r3 during the main test.
    278 define void @f10(i32 *%vptr, double *%dst) {
    279 ; CHECK-NOFP-LABEL: f10:
    280 ; CHECK-NOFP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r15)
    281 ; CHECK-NOFP: lghi [[REGISTER]], 4096
    282 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r15)
    283 ; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15)
    284 ; CHECK-NOFP: br %r14
    285 ;
    286 ; CHECK-FP-LABEL: f10:
    287 ; CHECK-FP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r11)
    288 ; CHECK-FP: lghi [[REGISTER]], 4096
    289 ; CHECK-FP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r11)
    290 ; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11)
    291 ; CHECK-FP: br %r14
    292   %region1 = alloca [978 x float], align 8
    293   %region2 = alloca [978 x float], align 8
    294   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
    295   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
    296   call void @foo(float *%start1, float *%start2)
    297   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 2
    298   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 2
    299   %i0 = load volatile i32 , i32 *%vptr
    300   %i1 = load volatile i32 , i32 *%vptr
    301   %i2 = load volatile i32 , i32 *%vptr
    302   %i3 = load volatile i32 , i32 *%vptr
    303   %i4 = load volatile i32 , i32 *%vptr
    304   %i5 = load volatile i32 , i32 *%vptr
    305   %i14 = load volatile i32 , i32 *%vptr
    306   %float1 = load float , float *%ptr1
    307   %float2 = load float , float *%ptr2
    308   %double1 = fpext float %float1 to double
    309   %double2 = fpext float %float2 to double
    310   store volatile double %double1, double *%dst
    311   store volatile double %double2, double *%dst
    312   store volatile i32 %i0, i32 *%vptr
    313   store volatile i32 %i1, i32 *%vptr
    314   store volatile i32 %i2, i32 *%vptr
    315   store volatile i32 %i3, i32 *%vptr
    316   store volatile i32 %i4, i32 *%vptr
    317   store volatile i32 %i5, i32 *%vptr
    318   store volatile i32 %i14, i32 *%vptr
    319   ret void
    320 }
    321 
    322 ; Repeat f2 in a case where the index register is already occupied.
    323 define void @f11(double *%dst, i64 %index) {
    324 ; CHECK-NOFP-LABEL: f11:
    325 ; CHECK-NOFP: lgr [[REGISTER:%r[1-9][0-5]?]], %r3
    326 ; CHECK-NOFP: lay %r1, 4096(%r15)
    327 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r1)
    328 ; CHECK-NOFP: br %r14
    329 ;
    330 ; CHECK-FP-LABEL: f11:
    331 ; CHECK-FP: lgr [[REGISTER:%r[1-9][0-5]?]], %r3
    332 ; CHECK-FP: lay %r1, 4096(%r11)
    333 ; CHECK-FP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r1)
    334 ; CHECK-FP: br %r14
    335   %region1 = alloca [978 x float], align 8
    336   %region2 = alloca [978 x float], align 8
    337   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
    338   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
    339   call void @foo(float *%start1, float *%start2)
    340   %elem1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 2
    341   %elem2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 2
    342   %base1 = ptrtoint float *%elem1 to i64
    343   %base2 = ptrtoint float *%elem2 to i64
    344   %addr1 = add i64 %base1, %index
    345   %addr2 = add i64 %base2, %index
    346   %ptr1 = inttoptr i64 %addr1 to float *
    347   %ptr2 = inttoptr i64 %addr2 to float *
    348   %float1 = load float , float *%ptr1
    349   %float2 = load float , float *%ptr2
    350   %double1 = fpext float %float1 to double
    351   %double2 = fpext float %float2 to double
    352   store volatile double %double1, double *%dst
    353   store volatile double %double2, double *%dst
    354   ret void
    355 }
    356