Home | History | Annotate | Download | only in PowerPC
      1 ; RUN: llc -relocation-model=static -verify-machineinstrs -mcpu=pwr7 -O1 -code-model=medium <%s | FileCheck %s
      2 ; RUN: llc -relocation-model=static -verify-machineinstrs -mcpu=pwr8 -O1 -code-model=medium <%s | FileCheck %s
      3 
      4 ; Test peephole optimization for medium code model (32-bit TOC offsets)
      5 ; for loading and storing small offsets within aligned values.
      6 
      7 target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
      8 target triple = "powerpc64-unknown-linux-gnu"
      9 
     10 %struct.b4 = type<{ i8, i8, i8, i8 }>
     11 %struct.h2 = type<{ i16, i16 }>
     12 
     13 %struct.b8 = type<{ i8, i8, i8, i8, i8, i8, i8, i8 }>
     14 %struct.h4 = type<{ i16, i16, i16, i16 }>
     15 %struct.w2 = type<{ i32, i32 }>
     16 
     17 %struct.d2 = type<{ i64, i64 }>
     18 %struct.misalign = type<{ i8, i64 }>
     19 
     20 @b4v = global %struct.b4 <{ i8 1, i8 2, i8 3, i8 4 }>, align 4
     21 @h2v = global %struct.h2 <{ i16 1, i16 2 }>, align 4
     22 
     23 @b8v = global %struct.b8 <{ i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8 }>, align 8
     24 @h4v = global %struct.h4 <{ i16 1, i16 2, i16 3, i16 4 }>, align 8
     25 @w2v = global %struct.w2 <{ i32 1, i32 2 }>, align 8
     26 
     27 @d2v = global %struct.d2 <{ i64 1, i64 2 }>, align 16
     28 @misalign_v = global %struct.misalign <{ i8 1, i64 2 }>, align 16
     29 
     30 ; CHECK-LABEL: test_b4:
     31 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, b4v@toc@ha
     32 ; CHECK-DAG: lbz [[REG0_0:[0-9]+]], b4v@toc@l([[REGSTRUCT]])
     33 ; CHECK-DAG: lbz [[REG1_0:[0-9]+]], b4v@toc@l+1([[REGSTRUCT]])
     34 ; CHECK-DAG: lbz [[REG2_0:[0-9]+]], b4v@toc@l+2([[REGSTRUCT]])
     35 ; CHECK-DAG: lbz [[REG3_0:[0-9]+]], b4v@toc@l+3([[REGSTRUCT]])
     36 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
     37 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
     38 ; CHECK-DAG: addi [[REG2_1:[0-9]+]], [[REG2_0]], 3
     39 ; CHECK-DAG: addi [[REG3_1:[0-9]+]], [[REG3_0]], 4
     40 ; CHECK-DAG: stb [[REG0_1]], b4v@toc@l([[REGSTRUCT]])
     41 ; CHECK-DAG: stb [[REG1_1]], b4v@toc@l+1([[REGSTRUCT]])
     42 ; CHECK-DAG: stb [[REG2_1]], b4v@toc@l+2([[REGSTRUCT]])
     43 ; CHECK-DAG: stb [[REG3_1]], b4v@toc@l+3([[REGSTRUCT]])
     44 
     45 define void @test_b4() nounwind {
     46 entry:
     47   %0 = load i8, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 0), align 1
     48   %inc0 = add nsw i8 %0, 1
     49   store i8 %inc0, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 0), align 1
     50   %1 = load i8, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 1), align 1
     51   %inc1 = add nsw i8 %1, 2
     52   store i8 %inc1, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 1), align 1
     53   %2 = load i8, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 2), align 1
     54   %inc2 = add nsw i8 %2, 3
     55   store i8 %inc2, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 2), align 1
     56   %3 = load i8, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 3), align 1
     57   %inc3 = add nsw i8 %3, 4
     58   store i8 %inc3, i8* getelementptr inbounds (%struct.b4, %struct.b4* @b4v, i32 0, i32 3), align 1
     59   ret void
     60 }
     61 
     62 ; CHECK-LABEL: test_h2:
     63 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, h2v@toc@ha
     64 ; CHECK-DAG: lhz [[REG0_0:[0-9]+]], h2v@toc@l([[REGSTRUCT]])
     65 ; CHECK-DAG: lhz [[REG1_0:[0-9]+]], h2v@toc@l+2([[REGSTRUCT]])
     66 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
     67 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
     68 ; CHECK-DAG: sth [[REG0_1]], h2v@toc@l([[REGSTRUCT]])
     69 ; CHECK-DAG: sth [[REG1_1]], h2v@toc@l+2([[REGSTRUCT]])
     70 
     71 define void @test_h2() nounwind {
     72 entry:
     73   %0 = load i16, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 0), align 2
     74   %inc0 = add nsw i16 %0, 1
     75   store i16 %inc0, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 0), align 2
     76   %1 = load i16, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 1), align 2
     77   %inc1 = add nsw i16 %1, 2
     78   store i16 %inc1, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 1), align 2
     79   ret void
     80 }
     81 
     82 ; CHECK-LABEL: test_h2_optsize:
     83 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, h2v@toc@ha
     84 ; CHECK-DAG: lhz [[REG0_0:[0-9]+]], h2v@toc@l([[REGSTRUCT]])
     85 ; CHECK-DAG: lhz [[REG1_0:[0-9]+]], h2v@toc@l+2([[REGSTRUCT]])
     86 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
     87 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
     88 ; CHECK-DAG: sth [[REG0_1]], h2v@toc@l([[REGSTRUCT]])
     89 ; CHECK-DAG: sth [[REG1_1]], h2v@toc@l+2([[REGSTRUCT]])
     90 define void @test_h2_optsize() optsize nounwind {
     91 entry:
     92   %0 = load i16, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 0), align 2
     93   %inc0 = add nsw i16 %0, 1
     94   store i16 %inc0, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 0), align 2
     95   %1 = load i16, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 1), align 2
     96   %inc1 = add nsw i16 %1, 2
     97   store i16 %inc1, i16* getelementptr inbounds (%struct.h2, %struct.h2* @h2v, i32 0, i32 1), align 2
     98   ret void
     99 }
    100 
    101 ; CHECK-LABEL: test_b8:
    102 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, b8v@toc@ha
    103 ; CHECK-DAG: lbz [[REG0_0:[0-9]+]], b8v@toc@l([[REGSTRUCT]])
    104 ; CHECK-DAG: lbz [[REG1_0:[0-9]+]], b8v@toc@l+1([[REGSTRUCT]])
    105 ; CHECK-DAG: lbz [[REG2_0:[0-9]+]], b8v@toc@l+2([[REGSTRUCT]])
    106 ; CHECK-DAG: lbz [[REG3_0:[0-9]+]], b8v@toc@l+3([[REGSTRUCT]])
    107 ; CHECK-DAG: lbz [[REG4_0:[0-9]+]], b8v@toc@l+4([[REGSTRUCT]])
    108 ; CHECK-DAG: lbz [[REG5_0:[0-9]+]], b8v@toc@l+5([[REGSTRUCT]])
    109 ; CHECK-DAG: lbz [[REG6_0:[0-9]+]], b8v@toc@l+6([[REGSTRUCT]])
    110 ; CHECK-DAG: lbz [[REG7_0:[0-9]+]], b8v@toc@l+7([[REGSTRUCT]])
    111 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
    112 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
    113 ; CHECK-DAG: addi [[REG2_1:[0-9]+]], [[REG2_0]], 3
    114 ; CHECK-DAG: addi [[REG3_1:[0-9]+]], [[REG3_0]], 4
    115 ; CHECK-DAG: addi [[REG4_1:[0-9]+]], [[REG4_0]], 5
    116 ; CHECK-DAG: addi [[REG5_1:[0-9]+]], [[REG5_0]], 6
    117 ; CHECK-DAG: addi [[REG6_1:[0-9]+]], [[REG6_0]], 7
    118 ; CHECK-DAG: addi [[REG7_1:[0-9]+]], [[REG7_0]], 8
    119 ; CHECK-DAG: stb [[REG0_1]], b8v@toc@l([[REGSTRUCT]])
    120 ; CHECK-DAG: stb [[REG1_1]], b8v@toc@l+1([[REGSTRUCT]])
    121 ; CHECK-DAG: stb [[REG2_1]], b8v@toc@l+2([[REGSTRUCT]])
    122 ; CHECK-DAG: stb [[REG3_1]], b8v@toc@l+3([[REGSTRUCT]])
    123 ; CHECK-DAG: stb [[REG4_1]], b8v@toc@l+4([[REGSTRUCT]])
    124 ; CHECK-DAG: stb [[REG5_1]], b8v@toc@l+5([[REGSTRUCT]])
    125 ; CHECK-DAG: stb [[REG6_1]], b8v@toc@l+6([[REGSTRUCT]])
    126 ; CHECK-DAG: stb [[REG7_1]], b8v@toc@l+7([[REGSTRUCT]])
    127 
    128 define void @test_b8() nounwind {
    129 entry:
    130   %0 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 0), align 1
    131   %inc0 = add nsw i8 %0, 1
    132   store i8 %inc0, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 0), align 1
    133   %1 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 1), align 1
    134   %inc1 = add nsw i8 %1, 2
    135   store i8 %inc1, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 1), align 1
    136   %2 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 2), align 1
    137   %inc2 = add nsw i8 %2, 3
    138   store i8 %inc2, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 2), align 1
    139   %3 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 3), align 1
    140   %inc3 = add nsw i8 %3, 4
    141   store i8 %inc3, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 3), align 1
    142   %4 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 4), align 1
    143   %inc4 = add nsw i8 %4, 5
    144   store i8 %inc4, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 4), align 1
    145   %5 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 5), align 1
    146   %inc5 = add nsw i8 %5, 6
    147   store i8 %inc5, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 5), align 1
    148   %6 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 6), align 1
    149   %inc6 = add nsw i8 %6, 7
    150   store i8 %inc6, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 6), align 1
    151   %7 = load i8, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 7), align 1
    152   %inc7 = add nsw i8 %7, 8
    153   store i8 %inc7, i8* getelementptr inbounds (%struct.b8, %struct.b8* @b8v, i32 0, i32 7), align 1
    154   ret void
    155 }
    156 
    157 ; CHECK-LABEL: test_h4:
    158 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, h4v@toc@ha
    159 ; CHECK-DAG: lhz [[REG0_0:[0-9]+]], h4v@toc@l([[REGSTRUCT]])
    160 ; CHECK-DAG: lhz [[REG1_0:[0-9]+]], h4v@toc@l+2([[REGSTRUCT]])
    161 ; CHECK-DAG: lhz [[REG2_0:[0-9]+]], h4v@toc@l+4([[REGSTRUCT]])
    162 ; CHECK-DAG: lhz [[REG3_0:[0-9]+]], h4v@toc@l+6([[REGSTRUCT]])
    163 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
    164 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
    165 ; CHECK-DAG: addi [[REG2_1:[0-9]+]], [[REG2_0]], 3
    166 ; CHECK-DAG: addi [[REG3_1:[0-9]+]], [[REG3_0]], 4
    167 ; CHECK-DAG: sth [[REG0_1]], h4v@toc@l([[REGSTRUCT]])
    168 ; CHECK-DAG: sth [[REG1_1]], h4v@toc@l+2([[REGSTRUCT]])
    169 ; CHECK-DAG: sth [[REG2_1]], h4v@toc@l+4([[REGSTRUCT]])
    170 ; CHECK-DAG: sth [[REG3_1]], h4v@toc@l+6([[REGSTRUCT]])
    171 
    172 define void @test_h4() nounwind {
    173 entry:
    174   %0 = load i16, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 0), align 2
    175   %inc0 = add nsw i16 %0, 1
    176   store i16 %inc0, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 0), align 2
    177   %1 = load i16, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 1), align 2
    178   %inc1 = add nsw i16 %1, 2
    179   store i16 %inc1, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 1), align 2
    180   %2 = load i16, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 2), align 2
    181   %inc2 = add nsw i16 %2, 3
    182   store i16 %inc2, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 2), align 2
    183   %3 = load i16, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 3), align 2
    184   %inc3 = add nsw i16 %3, 4
    185   store i16 %inc3, i16* getelementptr inbounds (%struct.h4, %struct.h4* @h4v, i32 0, i32 3), align 2
    186   ret void
    187 }
    188 
    189 ; CHECK-LABEL: test_w2:
    190 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, w2v@toc@ha
    191 ; CHECK-DAG: lwz [[REG0_0:[0-9]+]], w2v@toc@l([[REGSTRUCT]])
    192 ; CHECK-DAG: lwz [[REG1_0:[0-9]+]], w2v@toc@l+4([[REGSTRUCT]])
    193 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
    194 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
    195 ; CHECK-DAG: stw [[REG0_1]], w2v@toc@l([[REGSTRUCT]])
    196 ; CHECK-DAG: stw [[REG1_1]], w2v@toc@l+4([[REGSTRUCT]])
    197 
    198 define void @test_w2() nounwind {
    199 entry:
    200   %0 = load i32, i32* getelementptr inbounds (%struct.w2, %struct.w2* @w2v, i32 0, i32 0), align 4
    201   %inc0 = add nsw i32 %0, 1
    202   store i32 %inc0, i32* getelementptr inbounds (%struct.w2, %struct.w2* @w2v, i32 0, i32 0), align 4
    203   %1 = load i32, i32* getelementptr inbounds (%struct.w2, %struct.w2* @w2v, i32 0, i32 1), align 4
    204   %inc1 = add nsw i32 %1, 2
    205   store i32 %inc1, i32* getelementptr inbounds (%struct.w2, %struct.w2* @w2v, i32 0, i32 1), align 4
    206   ret void
    207 }
    208 
    209 ; CHECK-LABEL: test_d2:
    210 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, d2v@toc@ha
    211 ; CHECK: addi [[BASEV:[0-9]+]], [[REGSTRUCT]], d2v@toc@l
    212 ; CHECK-DAG: ld [[REG0_0:[0-9]+]], d2v@toc@l([[REGSTRUCT]])
    213 ; CHECK-DAG: ld [[REG1_0:[0-9]+]], 8([[BASEV]])
    214 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
    215 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
    216 ; CHECK-DAG: std [[REG0_1]], d2v@toc@l([[REGSTRUCT]])
    217 ; CHECK-DAG: std [[REG1_1]], 8([[BASEV]])
    218 
    219 define void @test_d2() nounwind {
    220 entry:
    221   %0 = load i64, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 0), align 8
    222   %inc0 = add nsw i64 %0, 1
    223   store i64 %inc0, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 0), align 8
    224   %1 = load i64, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 1), align 8
    225   %inc1 = add nsw i64 %1, 2
    226   store i64 %inc1, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 1), align 8
    227   ret void
    228 }
    229 
    230 ; CHECK-LABEL: test_singleuse:
    231 ; CHECK: addis [[REG:[0-9]+]], 2, d2v@toc@ha+8
    232 ; CHECK: ld 3, d2v@toc@l+8([[REG]])
    233 define i64 @test_singleuse() nounwind {
    234 entry:
    235   %0 = load i64, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 1), align 8
    236   ret i64 %0
    237 }
    238 
    239 ; Make sure the optimization fails to fire if the symbol is aligned, but the offset is not.
    240 ; CHECK-LABEL: test_misalign
    241 ; CHECK: addis [[REGSTRUCT_0:[0-9]+]], 2, misalign_v@toc@ha
    242 ; CHECK-DAG: addi [[REGSTRUCT:[0-9]+]], [[REGSTRUCT_0]], misalign_v@toc@l
    243 ; CHECK-DAG: li [[OFFSET_REG:[0-9]+]], 1
    244 ; CHECK: ldx [[REG0_0:[0-9]+]], [[REGSTRUCT]], [[OFFSET_REG]]
    245 ; CHECK: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
    246 ; CHECK: stdx [[REG0_1]], [[REGSTRUCT]], [[OFFSET_REG]]
    247 define void @test_misalign() nounwind {
    248 entry:
    249   %0 = load i64, i64* getelementptr inbounds (%struct.misalign, %struct.misalign* @misalign_v, i32 0, i32 1), align 1
    250   %inc0 = add nsw i64 %0, 1
    251   store i64 %inc0, i64* getelementptr inbounds (%struct.misalign, %struct.misalign* @misalign_v, i32 0, i32 1), align 1
    252   ret void
    253 }
    254