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