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 7define 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 18define 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 30define i32 @test3(i32 %base, i32 %base2, i32 %offset) { 31entry: 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 46declare i8* @malloc(...) 47 48define fastcc void @test4(i16 %addr) nounwind { 49entry: 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 65define i32 @test_orr_extract_from_mul_1(i32 %x, i32 %y) { 66entry: 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 78define 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 84entry: 85 %mul1 = mul i32 %y, 127534 86 %or = or i32 %mul1, %x 87 ret i32 %or 88} 89 90define 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 96entry: 97 %mul1 = mul i32 %y, 255068 98 %or = or i32 %mul1, %x 99 ret i32 %or 100} 101 102define 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 108entry: 109 %mul1 = mul i32 %y, 510136 110 %or = or i32 %mul1, %x 111 ret i32 %or 112} 113 114define 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 120entry: 121 %mul1 = mul i32 %y, 1020272 122 %or = or i32 %mul1, %x 123 ret i32 %or 124} 125 126define 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 132entry: 133 %mul = mul i32 %y, -115933184 134 %or = or i32 %mul, %x 135 ret i32 %or 136} 137 138define 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] 144entry: 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 152define 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] 158entry: 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 166define 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] 172entry: 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 180define 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] 186entry: 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 194define 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] 203entry: 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 211define 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] 220entry: 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 229define 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 243define { 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