1 ; RUN: llc -mtriple=thumb-eabi %s -verify-machineinstrs -o - | \ 2 ; RUN: FileCheck %s -check-prefix CHECK --check-prefix CHECK-EABI 3 ; RUN: llc -mtriple=thumb-apple-darwin %s -verify-machineinstrs -o - | \ 4 ; RUN: FileCheck %s -check-prefix CHECK -check-prefix CHECK-DARWIN 5 6 define i64 @f1() { 7 entry: 8 ret i64 0 9 ; CHECK-LABEL: f1: 10 ; CHECK: movs r0, #0 11 ; CHECK: movs r1, r0 12 } 13 14 define i64 @f2() { 15 entry: 16 ret i64 1 17 ; CHECK-LABEL: f2: 18 ; CHECK: movs r0, #1 19 ; CHECK: movs r1, #0 20 } 21 22 define i64 @f3() { 23 entry: 24 ret i64 2147483647 25 ; CHECK-LABEL: f3: 26 ; CHECK: ldr r0, 27 ; CHECK: movs r1, #0 28 } 29 30 define i64 @f4() { 31 entry: 32 ret i64 2147483648 33 ; CHECK-LABEL: f4: 34 ; CHECK: movs r0, #1 35 ; CHECK: lsls r0, r0, #31 36 ; CHECK: movs r1, #0 37 } 38 39 define i64 @f5() { 40 entry: 41 ret i64 9223372036854775807 42 ; CHECK-LABEL: f5: 43 ; CHECK: movs r0, #0 44 ; CHECK: mvns r0, r0 45 ; CHECK: ldr r1, 46 } 47 48 define i64 @f6(i64 %x, i64 %y) { 49 entry: 50 %tmp1 = add i64 %y, 1 ; <i64> [#uses=1] 51 ret i64 %tmp1 52 ; CHECK-LABEL: f6: 53 ; CHECK: movs r1, #0 54 ; CHECK: adds r0, r2, #1 55 ; CHECK: adcs r1, r3 56 } 57 58 define i64 @f6a(i64 %x, i64 %y) { 59 entry: 60 %tmp1 = add i64 %y, 10 61 ret i64 %tmp1 62 ; CHECK-LABEL: f6a: 63 ; CHECK: movs r0, r2 64 ; CHECK: movs r1, #0 65 ; CHECK: adds r0, #10 66 ; CHECK: adcs r1, r3 67 } 68 69 define i64 @f6b(i64 %x, i64 %y) { 70 entry: 71 %tmp1 = add i64 %y, 1000 72 ret i64 %tmp1 73 ; CHECK-LABEL: f6b: 74 ; CHECK: movs r0, #125 75 ; CHECK: lsls r0, r0, #3 76 ; CHECK: movs r1, #0 77 ; CHECK: adds r0, r2, r0 78 ; CHECK: adcs r1, r3 79 } 80 81 define void @f7() { 82 entry: 83 %tmp = call i64 @f8( ) ; <i64> [#uses=0] 84 ret void 85 ; CHECK-LABEL: f7: 86 ; CHECK: bl 87 } 88 89 declare i64 @f8() 90 91 define i64 @f9(i64 %a, i64 %b) { 92 entry: 93 %tmp = sub i64 %a, %b ; <i64> [#uses=1] 94 ret i64 %tmp 95 ; CHECK-LABEL: f9: 96 ; CHECK: subs r0, r0, r2 97 ; CHECK: sbcs r1, r3 98 } 99 100 define i64 @f9a(i64 %x, i64 %y) { ; ADDC with small negative imm => SUBS imm 101 entry: 102 %tmp1 = sub i64 %y, 10 103 ret i64 %tmp1 104 ; CHECK-LABEL: f9a: 105 ; CHECK: movs r1, r3 106 ; CHECK: movs r0, r2 107 ; CHECK: movs r2, #0 108 ; CHECK: subs r0, #10 109 ; CHECK: sbcs r1, r2 110 } 111 112 define i64 @f9b(i64 %x, i64 %y) { ; ADDC with big negative imm => SUBS reg 113 entry: 114 %tmp1 = sub i64 1000, %y 115 ret i64 %tmp1 116 ; CHECK-LABEL: f9b: 117 ; CHECK: movs r0, #125 118 ; CHECK: lsls r0, r0, #3 119 ; CHECK: movs r1, #0 120 ; CHECK: subs r0, r0, r2 121 ; CHECK: sbcs r1, r3 122 } 123 124 define i64 @f9c(i64 %x, i32 %y) { ; SUBS with small positive imm => SUBS imm 125 entry: 126 %conv = sext i32 %y to i64 127 %shl = shl i64 %conv, 32 128 %or = or i64 %shl, 1 129 %sub = sub nsw i64 %x, %or 130 ret i64 %sub 131 ; CHECK-LABEL: f9c: 132 ; CHECK: subs r0, r0, #1 133 ; CHECK: sbcs r1, r2 134 } 135 136 define i64 @f9d(i64 %x, i32 %y) { ; SUBS with small negative imm => ADDS imm 137 entry: 138 %conv = sext i32 %y to i64 139 %shl = shl i64 %conv, 32 140 %or = or i64 %shl, 4294967295 141 %sub = sub nsw i64 %x, %or 142 ret i64 %sub 143 ; CHECK-LABEL: f9d: 144 ; CHECK: adds r0, r0, #1 145 ; CHECK: sbcs r1, r2 146 } 147 148 define i64 @f(i32 %a, i32 %b) { 149 entry: 150 %tmp = sext i32 %a to i64 ; <i64> [#uses=1] 151 %tmp1 = sext i32 %b to i64 ; <i64> [#uses=1] 152 %tmp2 = mul i64 %tmp1, %tmp ; <i64> [#uses=1] 153 ret i64 %tmp2 154 ; CHECK-LABEL: f: 155 ; CHECK-V6: bl __aeabi_lmul 156 ; CHECK-DARWIN: __muldi3 157 } 158 159 define i64 @g(i32 %a, i32 %b) { 160 entry: 161 %tmp = zext i32 %a to i64 ; <i64> [#uses=1] 162 %tmp1 = zext i32 %b to i64 ; <i64> [#uses=1] 163 %tmp2 = mul i64 %tmp1, %tmp ; <i64> [#uses=1] 164 ret i64 %tmp2 165 ; CHECK-LABEL: g: 166 ; CHECK-V6: bl __aeabi_lmul 167 ; CHECK-DARWIN: __muldi3 168 } 169 170 define i64 @f10() { 171 entry: 172 %a = alloca i64, align 8 ; <i64*> [#uses=1] 173 %retval = load i64, i64* %a ; <i64> [#uses=1] 174 ret i64 %retval 175 ; CHECK-LABEL: f10: 176 ; CHECK-EABI: sub sp, #8 177 ; CHECK-DARWIN: add r7, sp, #4 178 ; CHECK: ldr r0, [sp] 179 ; CHECK: ldr r1, [sp, #4] 180 ; CHECK-EABI: add sp, #8 181 ; CHECK-DARWIN: mov sp, r4 182 } 183 184 define i64 @f11(i64 %x, i64 %y) { 185 entry: 186 %tmp1 = add i64 -1000, %y 187 %tmp2 = add i64 %tmp1, -1000 188 ret i64 %tmp2 189 ; CHECK-LABEL: f11: 190 ; CHECK: movs r1, r3 191 ; CHECK: movs r0, #125 192 ; CHECK: lsls r0, r0, #3 193 ; CHECK: movs r3, #0 194 ; CHECK: subs r2, r2, r0 195 ; CHECK: sbcs r1, r3 196 ; CHECK: subs r0, r2, r0 197 ; CHECK: sbcs r1, r3 198 } 199 200 ; "sub 2147483648" has to be lowered into "add -2147483648" 201 define i64 @f12(i64 %x, i64 %y) { 202 entry: 203 %tmp1 = sub i64 %x, 2147483648 204 ret i64 %tmp1 205 ; CHECK-LABEL: f12: 206 ; CHECK: movs r2, #1 207 ; CHECK: lsls r2, r2, #31 208 ; CHECK: movs r3, #0 209 ; CHECK: adds r0, r0, r2 210 ; CHECK: sbcs r1, r3 211 } 212 213 declare void @f13(i64 %x) 214 215 define void @f14(i1 %x, i64 %y) #0 { 216 ; CHECK-LABEL: f14: 217 entry: 218 %a = add i64 %y, 47 219 call void @f13(i64 %a) 220 ; CHECK: bl 221 br i1 %x, label %if.end, label %if.then 222 223 if.then: 224 call void @f13(i64 %y) 225 ; CHECK: bl 226 br label %if.end 227 228 if.end: 229 %b = add i64 %y, 45 230 call void @f13(i64 %b) 231 ; CHECK: adds 232 ; CHECK: adcs 233 ; CHECK: bl 234 %c = add i64 %y, 47 235 call void @f13(i64 %c) 236 ; CHECK: adds 237 ; CHECK-NEXT: adcs 238 ; CHECK: bl 239 ret void 240 } 241 242 attributes #0 = { optsize } 243