Home | History | Annotate | Download | only in SystemZ
      1 ; Test 32-bit unsigned division and remainder.
      2 ;
      3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
      4 
      5 declare i32 @foo()
      6 
      7 ; Test register division.  The result is in the second of the two registers.
      8 define void @f1(i32 %dummy, i32 %a, i32 %b, i32 *%dest) {
      9 ; CHECK-LABEL: f1:
     10 ; CHECK-NOT: %r3
     11 ; CHECK: {{llill|lhi}} %r2, 0
     12 ; CHECK-NOT: %r3
     13 ; CHECK: dlr %r2, %r4
     14 ; CHECK: st %r3, 0(%r5)
     15 ; CHECK: br %r14
     16   %div = udiv i32 %a, %b
     17   store i32 %div, i32 *%dest
     18   ret void
     19 }
     20 
     21 ; Test register remainder.  The result is in the first of the two registers.
     22 define void @f2(i32 %dummy, i32 %a, i32 %b, i32 *%dest) {
     23 ; CHECK-LABEL: f2:
     24 ; CHECK-NOT: %r3
     25 ; CHECK: {{llill|lhi}} %r2, 0
     26 ; CHECK-NOT: %r3
     27 ; CHECK: dlr %r2, %r4
     28 ; CHECK: st %r2, 0(%r5)
     29 ; CHECK: br %r14
     30   %rem = urem i32 %a, %b
     31   store i32 %rem, i32 *%dest
     32   ret void
     33 }
     34 
     35 ; Test that division and remainder use a single instruction.
     36 define i32 @f3(i32 %dummy1, i32 %a, i32 %b) {
     37 ; CHECK-LABEL: f3:
     38 ; CHECK-NOT: %r3
     39 ; CHECK: {{llill|lhi}} %r2, 0
     40 ; CHECK-NOT: %r3
     41 ; CHECK: dlr %r2, %r4
     42 ; CHECK-NOT: dlr
     43 ; CHECK: or %r2, %r3
     44 ; CHECK: br %r14
     45   %div = udiv i32 %a, %b
     46   %rem = urem i32 %a, %b
     47   %or = or i32 %rem, %div
     48   ret i32 %or
     49 }
     50 
     51 ; Test memory division with no displacement.
     52 define void @f4(i32 %dummy, i32 %a, i32 *%src, i32 *%dest) {
     53 ; CHECK-LABEL: f4:
     54 ; CHECK-NOT: %r3
     55 ; CHECK: {{llill|lhi}} %r2, 0
     56 ; CHECK-NOT: %r3
     57 ; CHECK: dl %r2, 0(%r4)
     58 ; CHECK: st %r3, 0(%r5)
     59 ; CHECK: br %r14
     60   %b = load i32 , i32 *%src
     61   %div = udiv i32 %a, %b
     62   store i32 %div, i32 *%dest
     63   ret void
     64 }
     65 
     66 ; Test memory remainder with no displacement.
     67 define void @f5(i32 %dummy, i32 %a, i32 *%src, i32 *%dest) {
     68 ; CHECK-LABEL: f5:
     69 ; CHECK-NOT: %r3
     70 ; CHECK: {{llill|lhi}} %r2, 0
     71 ; CHECK-NOT: %r3
     72 ; CHECK: dl %r2, 0(%r4)
     73 ; CHECK: st %r2, 0(%r5)
     74 ; CHECK: br %r14
     75   %b = load i32 , i32 *%src
     76   %rem = urem i32 %a, %b
     77   store i32 %rem, i32 *%dest
     78   ret void
     79 }
     80 
     81 ; Test both memory division and memory remainder.
     82 define i32 @f6(i32 %dummy, i32 %a, i32 *%src) {
     83 ; CHECK-LABEL: f6:
     84 ; CHECK-NOT: %r3
     85 ; CHECK: {{llill|lhi}} %r2, 0
     86 ; CHECK-NOT: %r3
     87 ; CHECK: dl %r2, 0(%r4)
     88 ; CHECK-NOT: {{dl|dlr}}
     89 ; CHECK: or %r2, %r3
     90 ; CHECK: br %r14
     91   %b = load i32 , i32 *%src
     92   %div = udiv i32 %a, %b
     93   %rem = urem i32 %a, %b
     94   %or = or i32 %rem, %div
     95   ret i32 %or
     96 }
     97 
     98 ; Check the high end of the DL range.
     99 define i32 @f7(i32 %dummy, i32 %a, i32 *%src) {
    100 ; CHECK-LABEL: f7:
    101 ; CHECK: dl %r2, 524284(%r4)
    102 ; CHECK: br %r14
    103   %ptr = getelementptr i32, i32 *%src, i64 131071
    104   %b = load i32 , i32 *%ptr
    105   %rem = urem i32 %a, %b
    106   ret i32 %rem
    107 }
    108 
    109 ; Check the next word up, which needs separate address logic.
    110 ; Other sequences besides this one would be OK.
    111 define i32 @f8(i32 %dummy, i32 %a, i32 *%src) {
    112 ; CHECK-LABEL: f8:
    113 ; CHECK: agfi %r4, 524288
    114 ; CHECK: dl %r2, 0(%r4)
    115 ; CHECK: br %r14
    116   %ptr = getelementptr i32, i32 *%src, i64 131072
    117   %b = load i32 , i32 *%ptr
    118   %rem = urem i32 %a, %b
    119   ret i32 %rem
    120 }
    121 
    122 ; Check the high end of the negative aligned DL range.
    123 define i32 @f9(i32 %dummy, i32 %a, i32 *%src) {
    124 ; CHECK-LABEL: f9:
    125 ; CHECK: dl %r2, -4(%r4)
    126 ; CHECK: br %r14
    127   %ptr = getelementptr i32, i32 *%src, i64 -1
    128   %b = load i32 , i32 *%ptr
    129   %rem = urem i32 %a, %b
    130   ret i32 %rem
    131 }
    132 
    133 ; Check the low end of the DL range.
    134 define i32 @f10(i32 %dummy, i32 %a, i32 *%src) {
    135 ; CHECK-LABEL: f10:
    136 ; CHECK: dl %r2, -524288(%r4)
    137 ; CHECK: br %r14
    138   %ptr = getelementptr i32, i32 *%src, i64 -131072
    139   %b = load i32 , i32 *%ptr
    140   %rem = urem i32 %a, %b
    141   ret i32 %rem
    142 }
    143 
    144 ; Check the next word down, which needs separate address logic.
    145 ; Other sequences besides this one would be OK.
    146 define i32 @f11(i32 %dummy, i32 %a, i32 *%src) {
    147 ; CHECK-LABEL: f11:
    148 ; CHECK: agfi %r4, -524292
    149 ; CHECK: dl %r2, 0(%r4)
    150 ; CHECK: br %r14
    151   %ptr = getelementptr i32, i32 *%src, i64 -131073
    152   %b = load i32 , i32 *%ptr
    153   %rem = urem i32 %a, %b
    154   ret i32 %rem
    155 }
    156 
    157 ; Check that DL allows an index.
    158 define i32 @f12(i32 %dummy, i32 %a, i64 %src, i64 %index) {
    159 ; CHECK-LABEL: f12:
    160 ; CHECK: dl %r2, 524287(%r5,%r4)
    161 ; CHECK: br %r14
    162   %add1 = add i64 %src, %index
    163   %add2 = add i64 %add1, 524287
    164   %ptr = inttoptr i64 %add2 to i32 *
    165   %b = load i32 , i32 *%ptr
    166   %rem = urem i32 %a, %b
    167   ret i32 %rem
    168 }
    169 
    170 ; Check that divisions of spilled values can use DL rather than DLR.
    171 define i32 @f13(i32 *%ptr0) {
    172 ; CHECK-LABEL: f13:
    173 ; CHECK: brasl %r14, foo@PLT
    174 ; CHECK: dl {{%r[0-9]+}}, 16{{[04]}}(%r15)
    175 ; CHECK: br %r14
    176   %ptr1 = getelementptr i32, i32 *%ptr0, i64 2
    177   %ptr2 = getelementptr i32, i32 *%ptr0, i64 4
    178   %ptr3 = getelementptr i32, i32 *%ptr0, i64 6
    179   %ptr4 = getelementptr i32, i32 *%ptr0, i64 8
    180   %ptr5 = getelementptr i32, i32 *%ptr0, i64 10
    181   %ptr6 = getelementptr i32, i32 *%ptr0, i64 12
    182   %ptr7 = getelementptr i32, i32 *%ptr0, i64 14
    183   %ptr8 = getelementptr i32, i32 *%ptr0, i64 16
    184   %ptr9 = getelementptr i32, i32 *%ptr0, i64 18
    185 
    186   %val0 = load i32 , i32 *%ptr0
    187   %val1 = load i32 , i32 *%ptr1
    188   %val2 = load i32 , i32 *%ptr2
    189   %val3 = load i32 , i32 *%ptr3
    190   %val4 = load i32 , i32 *%ptr4
    191   %val5 = load i32 , i32 *%ptr5
    192   %val6 = load i32 , i32 *%ptr6
    193   %val7 = load i32 , i32 *%ptr7
    194   %val8 = load i32 , i32 *%ptr8
    195   %val9 = load i32 , i32 *%ptr9
    196 
    197   %ret = call i32 @foo()
    198 
    199   %div0 = udiv i32 %ret, %val0
    200   %div1 = udiv i32 %div0, %val1
    201   %div2 = udiv i32 %div1, %val2
    202   %div3 = udiv i32 %div2, %val3
    203   %div4 = udiv i32 %div3, %val4
    204   %div5 = udiv i32 %div4, %val5
    205   %div6 = udiv i32 %div5, %val6
    206   %div7 = udiv i32 %div6, %val7
    207   %div8 = udiv i32 %div7, %val8
    208   %div9 = udiv i32 %div8, %val9
    209 
    210   ret i32 %div9
    211 }
    212