Home | History | Annotate | Download | only in ARM
      1 ; RUN: llc < %s -mtriple=armv7-apple-darwin -mcpu=cortex-a8 | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-ARM
      2 ; RUN: llc < %s -mtriple=armv7-apple-darwin -mcpu=cortex-a9 | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-ARM
      3 ; RUN: llc < %s -mtriple=thumbv7m-none-eabi | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-THUMB
      4 ; rdar://8576755
      5 
      6 
      7 define i32 @test1(i32 %X, i32 %Y, i8 %sh) {
      8 ; CHECK-LABEL: test1:
      9 ; CHECK-ARM: add r0, r0, r1, lsl r2
     10 ; CHECK-THUMB: lsls r1, r2
     11 ; CHECK-THUMB: add r0, r1
     12         %shift.upgrd.1 = zext i8 %sh to i32
     13         %A = shl i32 %Y, %shift.upgrd.1
     14         %B = add i32 %X, %A
     15         ret i32 %B
     16 }
     17 
     18 define i32 @test2(i32 %X, i32 %Y, i8 %sh) {
     19 ; CHECK-LABEL: test2:
     20 ; CHECK-ARM: bic r0, r0, r1, asr r2
     21 ; CHECK-THUMB: asrs r1, r2
     22 ; CHECK-THUMB: bics r0, r1
     23         %shift.upgrd.2 = zext i8 %sh to i32
     24         %A = ashr i32 %Y, %shift.upgrd.2
     25         %B = xor i32 %A, -1
     26         %C = and i32 %X, %B
     27         ret i32 %C
     28 }
     29 
     30 define i32 @test3(i32 %base, i32 %base2, i32 %offset) {
     31 entry:
     32 ; CHECK-LABEL: test3:
     33 ; CHECK: ldr{{(.w)?}} r0, [r0, r2, lsl #2]
     34 ; CHECK: ldr{{(.w)?}} r1, [r1, r2, lsl #2]
     35         %tmp1 = shl i32 %offset, 2
     36         %tmp2 = add i32 %base, %tmp1
     37         %tmp3 = inttoptr i32 %tmp2 to i32*
     38         %tmp4 = add i32 %base2, %tmp1
     39         %tmp5 = inttoptr i32 %tmp4 to i32*
     40         %tmp6 = load i32, i32* %tmp3
     41         %tmp7 = load i32, i32* %tmp5
     42         %tmp8 = add i32 %tmp7, %tmp6
     43         ret i32 %tmp8
     44 }
     45 
     46 declare i8* @malloc(...)
     47 
     48 define fastcc void @test4(i16 %addr) nounwind {
     49 entry:
     50 ; CHECK-LABEL: test4:
     51 ; CHECK: ldr{{(.w)?}} [[REG:r[0-9]+]], [r0, r1, lsl #2]
     52 ; CHECK-NOT: ldr{{(.w)?}} [[REG:r[0-9]+]], [r0, r1, lsl #2]!
     53 ; CHECK: str{{(.w)?}} [[REG]], [r0, r1, lsl #2]
     54 ; CHECK-NOT: str{{(.w)?}} [[REG]], [r0]
     55   %0 = tail call i8* (...) @malloc(i32 undef) nounwind
     56   %1 = bitcast i8* %0 to i32*
     57   %2 = sext i16 %addr to i32
     58   %3 = getelementptr inbounds i32, i32* %1, i32 %2
     59   %4 = load i32, i32* %3, align 4
     60   %5 = add nsw i32 %4, 1
     61   store i32 %5, i32* %3, align 4
     62   ret void
     63 }
     64 
     65 define i32 @test_orr_extract_from_mul_1(i32 %x, i32 %y) {
     66 entry:
     67 ; CHECK-LABEL: test_orr_extract_from_mul_1
     68 ; CHECK: movw r2, #63767
     69 ; CHECK-ARM: mul r1, r1, r2
     70 ; CHECK-ARM: orr r0, r1, r0
     71 ; CHECK-THUMB: muls r1, r2, r1
     72 ; CHECk-THUMB: orrs r0, r1
     73   %mul = mul i32 %y, 63767
     74   %or = or i32 %mul, %x
     75   ret i32 %or
     76 }
     77 
     78 define i32 @test_orr_extract_from_mul_2(i32 %x, i32 %y) {
     79 ; CHECK-LABEL: test_orr_extract_from_mul_2
     80 ; CHECK: movw r2, #63767
     81 ; CHECK-ARM: mul r1, r1, r2
     82 ; CHECK-THUMB: muls r1, r2, r1
     83 ; CHECK: orr{{(.w)?}} r0, r0, r1, lsl #1
     84 entry:
     85   %mul1 = mul i32 %y, 127534
     86   %or = or i32 %mul1, %x
     87   ret i32 %or
     88 }
     89 
     90 define i32 @test_orr_extract_from_mul_3(i32 %x, i32 %y) {
     91 ; CHECK-LABEL: test_orr_extract_from_mul_3
     92 ; CHECK: movw r2, #63767
     93 ; CHECK-ARM: mul r1, r1, r2
     94 ; CHECK-THUMB: muls r1, r2, r1
     95 ; CHECK: orr{{(.w)?}} r0, r0, r1, lsl #2
     96 entry:
     97   %mul1 = mul i32 %y, 255068
     98   %or = or i32 %mul1, %x
     99   ret i32 %or
    100 }
    101 
    102 define i32 @test_orr_extract_from_mul_4(i32 %x, i32 %y) {
    103 ; CHECK-LABEL: test_orr_extract_from_mul_4
    104 ; CHECK: movw r2, #63767
    105 ; CHECK-ARM: mul r1, r1, r2
    106 ; CHECK-THUMB: muls r1, r2, r1
    107 ; CHECK: orr{{(.w)?}} r0, r0, r1, lsl #3
    108 entry:
    109   %mul1 = mul i32 %y, 510136
    110   %or = or i32 %mul1, %x
    111   ret i32 %or
    112 }
    113 
    114 define i32 @test_orr_extract_from_mul_5(i32 %x, i32 %y) {
    115 ; CHECK-LABEL: test_orr_extract_from_mul_5
    116 ; CHECK: movw r2, #63767
    117 ; CHECK-ARM: mul r1, r1, r2
    118 ; CHECK-THUMB: muls r1, r2, r1
    119 ; CHECK: orr{{(.w)?}} r0, r0, r1, lsl #4
    120 entry:
    121   %mul1 = mul i32 %y, 1020272
    122   %or = or i32 %mul1, %x
    123   ret i32 %or
    124 }
    125 
    126 define i32 @test_orr_extract_from_mul_6(i32 %x, i32 %y) {
    127 ; CHECK-LABEL: test_orr_extract_from_mul_6
    128 ; CHECK: movw r2, #63767
    129 ; CHECK-ARM: mul r1, r1, r2
    130 ; CHECK-THUMB: muls r1, r2, r1
    131 ; CHECK: orr{{(.w)?}} r0, r0, r1, lsl #16
    132 entry:
    133   %mul = mul i32 %y, -115933184
    134   %or = or i32 %mul, %x
    135   ret i32 %or
    136 }
    137 
    138 define i32 @test_load_extract_from_mul_1(i8* %x, i32 %y) {
    139 ; CHECK-LABEL: test_load_extract_from_mul_1
    140 ; CHECK: movw r2, #63767
    141 ; CHECK-ARM: mul r1, r1, r2
    142 ; CHECK-THUMB: muls r1, r2, r1
    143 ; CHECK: ldrb r0, [r0, r1]
    144 entry:
    145   %mul = mul i32 %y, 63767
    146   %arrayidx = getelementptr inbounds i8, i8* %x, i32 %mul
    147   %0 = load i8, i8* %arrayidx, align 1
    148   %conv = zext i8 %0 to i32
    149   ret i32 %conv
    150 }
    151 
    152 define i32 @test_load_extract_from_mul_2(i8* %x, i32 %y) {
    153 ; CHECK-LABEL: test_load_extract_from_mul_2
    154 ; CHECK: movw r2, #63767
    155 ; CHECK-ARM: mul r1, r1, r2
    156 ; CHECK-THUMB: muls r1, r2, r1
    157 ; CHECK: ldrb{{(.w)?}} r0, [r0, r1, lsl #1]
    158 entry:
    159   %mul1 = mul i32 %y, 127534
    160   %arrayidx = getelementptr inbounds i8, i8* %x, i32 %mul1
    161   %0 = load i8, i8* %arrayidx, align 1
    162   %conv = zext i8 %0 to i32
    163   ret i32 %conv
    164 }
    165 
    166 define i32 @test_load_extract_from_mul_3(i8* %x, i32 %y) {
    167 ; CHECK-LABEL: test_load_extract_from_mul_3
    168 ; CHECK: movw r2, #63767
    169 ; CHECK-ARM: mul r1, r1, r2
    170 ; CHECK-THUMB: muls r1, r2, r1
    171 ; CHECK: ldrb{{(.w)?}} r0, [r0, r1, lsl #2]
    172 entry:
    173   %mul1 = mul i32 %y, 255068
    174   %arrayidx = getelementptr inbounds i8, i8* %x, i32 %mul1
    175   %0 = load i8, i8* %arrayidx, align 1
    176   %conv = zext i8 %0 to i32
    177   ret i32 %conv
    178 }
    179 
    180 define i32 @test_load_extract_from_mul_4(i8* %x, i32 %y) {
    181 ; CHECK-LABEL: test_load_extract_from_mul_4
    182 ; CHECK: movw r2, #63767
    183 ; CHECK-ARM: mul r1, r1, r2
    184 ; CHECK-THUMB: muls r1, r2, r1
    185 ; CHECK: ldrb{{(.w)?}} r0, [r0, r1, lsl #3]
    186 entry:
    187   %mul1 = mul i32 %y, 510136
    188   %arrayidx = getelementptr inbounds i8, i8* %x, i32 %mul1
    189   %0 = load i8, i8* %arrayidx, align 1
    190   %conv = zext i8 %0 to i32
    191   ret i32 %conv
    192 }
    193 
    194 define i32 @test_load_extract_from_mul_5(i8* %x, i32 %y) {
    195 ; CHECK-LABEL: test_load_extract_from_mul_5
    196 ; CHECK-ARM: movw r2, #63767
    197 ; CHECK-ARM: mul r1, r1, r2
    198 ; CHECK-ARM: ldrb r0, [r0, r1, lsl #4]
    199 ; CHECK-THUMB: movw r2, #37232
    200 ; CHECK-THUMB: movt r2, #15
    201 ; CHECK-THUMB: muls r1, r2, r1
    202 ; CHECK-THUMB: ldrb r0, [r0, r1]
    203 entry:
    204   %mul1 = mul i32 %y, 1020272
    205   %arrayidx = getelementptr inbounds i8, i8* %x, i32 %mul1
    206   %0 = load i8, i8* %arrayidx, align 1
    207   %conv = zext i8 %0 to i32
    208   ret i32 %conv
    209 }
    210 
    211 define i32 @test_load_extract_from_mul_6(i8* %x, i32 %y) {
    212 ; CHECK-LABEL: test_load_extract_from_mul_6
    213 ; CHECK-ARM: movw r2, #63767
    214 ; CHECK-ARM: mul r1, r1, r2
    215 ; CHECK-ARM: ldrb r0, [r0, r1, lsl #16]
    216 ; CHECK-THUMB: movs r2, #0
    217 ; CHECK-THUMB: movt r2, #63767
    218 ; CHECK-THUMB: muls r1, r2, r1
    219 ; CHECK-THUMB: ldrb r0, [r0, r1]
    220 entry:
    221   %mul = mul i32 %y, -115933184
    222   %arrayidx = getelementptr inbounds i8, i8* %x, i32 %mul
    223   %0 = load i8, i8* %arrayidx, align 1
    224   %conv = zext i8 %0 to i32
    225   ret i32 %conv
    226 }
    227 
    228 
    229 define void @test_well_formed_dag(i32 %in1, i32 %in2, i32* %addr) {
    230 ; CHECK-LABEL: test_well_formed_dag:
    231 ; CHECK-ARM: movw [[SMALL_CONST:r[0-9]+]], #675
    232 ; CHECK-ARM: mul [[SMALL_PROD:r[0-9]+]], r0, [[SMALL_CONST]]
    233 ; CHECK-ARM: add {{r[0-9]+}}, r1, [[SMALL_PROD]], lsl #7
    234 
    235   %mul.small = mul i32 %in1, 675
    236   store i32 %mul.small, i32* %addr
    237   %mul.big = mul i32 %in1, 86400
    238   %add = add i32 %in2, %mul.big
    239   store i32 %add, i32* %addr
    240   ret void
    241 }
    242 
    243 define { i32, i32 } @test_multi_use_add(i32 %base, i32 %offset) {
    244 ; CHECK-LABEL: test_multi_use_add:
    245 ; CHECK-THUMB: movs [[CONST:r[0-9]+]], #28
    246 ; CHECK-THUMB: movt [[CONST]], #1
    247 
    248   %prod = mul i32 %offset, 65564
    249   %sum = add i32 %base, %prod
    250 
    251   %ptr = inttoptr i32 %sum to i32*
    252   %loaded = load i32, i32* %ptr
    253 
    254   %ret.tmp = insertvalue { i32, i32 } undef, i32 %sum, 0
    255   %ret = insertvalue { i32, i32 } %ret.tmp, i32 %loaded, 1
    256 
    257   ret { i32, i32 } %ret
    258 }
    259