| Kyle Butt | b15c066 | 2017-01-31 23:48:32 +0000 | [diff] [blame] | 1 | ; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumb-macho \ | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 2 | ; RUN:      | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE --check-prefix=ENABLE-V4T | 
| Kyle Butt | b15c066 | 2017-01-31 23:48:32 +0000 | [diff] [blame] | 3 | ; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumbv5-macho \ | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 4 | ; RUN:      | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE --check-prefix=ENABLE-V5T | 
| Kyle Butt | b15c066 | 2017-01-31 23:48:32 +0000 | [diff] [blame] | 5 | ; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumb-macho \ | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 6 | ; RUN:      | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE --check-prefix=DISABLE-V4T | 
| Kyle Butt | b15c066 | 2017-01-31 23:48:32 +0000 | [diff] [blame] | 7 | ; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumbv5-macho \ | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 8 | ; RUN:      | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE --check-prefix=DISABLE-V5T | 
| Kyle Butt | b15c066 | 2017-01-31 23:48:32 +0000 | [diff] [blame] | 9 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 10 | ; | 
|  | 11 | ; Note: Lots of tests use inline asm instead of regular calls. | 
|  | 12 | ; This allows to have a better control on what the allocation will do. | 
|  | 13 | ; Otherwise, we may have spill right in the entry block, defeating | 
|  | 14 | ; shrink-wrapping. Moreover, some of the inline asm statements (nop) | 
|  | 15 | ; are here to ensure that the related paths do not end up as critical | 
|  | 16 | ; edges. | 
|  | 17 | ; Also disable the late if-converter as it makes harder to reason on | 
|  | 18 | ; the diffs. | 
| Kyle Butt | b15c066 | 2017-01-31 23:48:32 +0000 | [diff] [blame] | 19 | ; Disable tail-duplication during placement, as v4t vs v5t get different | 
|  | 20 | ; results due to branches not being analyzable under v5 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 21 |  | 
|  | 22 | ; Initial motivating example: Simple diamond with a call just on one side. | 
|  | 23 | ; CHECK-LABEL: foo: | 
|  | 24 | ; | 
|  | 25 | ; Compare the arguments and jump to exit. | 
|  | 26 | ; No prologue needed. | 
|  | 27 | ; ENABLE: cmp r0, r1 | 
|  | 28 | ; ENABLE-NEXT: bge [[EXIT_LABEL:LBB[0-9_]+]] | 
|  | 29 | ; | 
|  | 30 | ; Prologue code. | 
|  | 31 | ; CHECK: push {r7, lr} | 
| Tim Northover | 747ae9a | 2015-11-18 21:10:39 +0000 | [diff] [blame] | 32 | ; CHECK: sub sp, #8 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 33 | ; | 
|  | 34 | ; Compare the arguments and jump to exit. | 
|  | 35 | ; After the prologue is set. | 
|  | 36 | ; DISABLE: cmp r0, r1 | 
|  | 37 | ; DISABLE-NEXT: bge [[EXIT_LABEL:LBB[0-9_]+]] | 
|  | 38 | ; | 
|  | 39 | ; Store %a in the alloca. | 
|  | 40 | ; CHECK: str r0, [sp, #4] | 
|  | 41 | ; Set the alloca address in the second argument. | 
|  | 42 | ; Set the first argument to zero. | 
|  | 43 | ; CHECK: movs r0, #0 | 
|  | 44 | ; CHECK-NEXT: add r1, sp, #4 | 
|  | 45 | ; CHECK-NEXT: bl | 
|  | 46 | ; | 
|  | 47 | ; With shrink-wrapping, epilogue is just after the call. | 
|  | 48 | ; ENABLE-NEXT: add sp, #8 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 49 | ; ENABLE-V5T-NEXT: pop {r7, pc} | 
|  | 50 | ; ENABLE-V4T-NEXT: pop {r7} | 
|  | 51 | ; ENABLE-V4T-NEXT: pop {r1} | 
|  | 52 | ; ENABLE-V4T-NEXT: mov lr, r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 53 | ; | 
|  | 54 | ; CHECK: [[EXIT_LABEL]]: | 
|  | 55 | ; | 
|  | 56 | ; Without shrink-wrapping, epilogue is in the exit block. | 
|  | 57 | ; Epilogue code. (What we pop does not matter.) | 
|  | 58 | ; DISABLE: add sp, #8 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 59 | ; DISABLE-V5T-NEXT: pop {r7, pc} | 
|  | 60 | ; DISABLE-V4T-NEXT: pop {r7} | 
|  | 61 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 62 | ; DISABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 63 | ; | 
|  | 64 | ; ENABLE-NEXT: bx lr | 
|  | 65 | define i32 @foo(i32 %a, i32 %b) { | 
|  | 66 | %tmp = alloca i32, align 4 | 
|  | 67 | %tmp2 = icmp slt i32 %a, %b | 
|  | 68 | br i1 %tmp2, label %true, label %false | 
|  | 69 |  | 
|  | 70 | true: | 
|  | 71 | store i32 %a, i32* %tmp, align 4 | 
|  | 72 | %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) | 
|  | 73 | br label %false | 
|  | 74 |  | 
|  | 75 | false: | 
|  | 76 | %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] | 
|  | 77 | ret i32 %tmp.0 | 
|  | 78 | } | 
|  | 79 |  | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 80 |  | 
|  | 81 | ; Same, but the final BB is non-trivial, so we don't duplicate the return inst. | 
|  | 82 | ; CHECK-LABEL: bar: | 
|  | 83 | ; | 
|  | 84 | ; With shrink-wrapping, epilogue is just after the call. | 
|  | 85 | ; CHECK: bl | 
|  | 86 | ; ENABLE-NEXT: add sp, #8 | 
|  | 87 | ; ENABLE-NEXT: pop {r7} | 
|  | 88 | ; ENABLE-NEXT: pop {r0} | 
|  | 89 | ; ENABLE-NEXT: mov lr, r0 | 
|  | 90 | ; | 
|  | 91 | ; CHECK: movs r0, #42 | 
|  | 92 | ; | 
|  | 93 | ; Without shrink-wrapping, epilogue is in the exit block. | 
|  | 94 | ; Epilogue code. (What we pop does not matter.) | 
|  | 95 | ; DISABLE: add sp, #8 | 
|  | 96 | ; DISABLE-V5T-NEXT: pop {r7, pc} | 
|  | 97 | ; DISABLE-V4T-NEXT: pop {r7} | 
|  | 98 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 99 | ; DISABLE-V4T-NEXT: bx r1 | 
|  | 100 | ; | 
|  | 101 | ; ENABLE-NEXT: bx lr | 
|  | 102 | define i32 @bar(i32 %a, i32 %b) { | 
|  | 103 | %tmp = alloca i32, align 4 | 
|  | 104 | %tmp2 = icmp slt i32 %a, %b | 
|  | 105 | br i1 %tmp2, label %true, label %false | 
|  | 106 |  | 
|  | 107 | true: | 
|  | 108 | store i32 %a, i32* %tmp, align 4 | 
|  | 109 | %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) | 
|  | 110 | br label %false | 
|  | 111 |  | 
|  | 112 | false: | 
|  | 113 | ret i32 42 | 
|  | 114 | } | 
|  | 115 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 116 | ; Function Attrs: optsize | 
|  | 117 | declare i32 @doSomething(i32, i32*) | 
|  | 118 |  | 
|  | 119 |  | 
|  | 120 | ; Check that we do not perform the restore inside the loop whereas the save | 
|  | 121 | ; is outside. | 
|  | 122 | ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop: | 
|  | 123 | ; | 
|  | 124 | ; Shrink-wrapping allows to skip the prologue in the else case. | 
|  | 125 | ; ENABLE: cmp r0, #0 | 
|  | 126 | ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 127 | ; | 
|  | 128 | ; Prologue code. | 
|  | 129 | ; Make sure we save the CSR used in the inline asm: r4. | 
|  | 130 | ; CHECK: push {r4, lr} | 
|  | 131 | ; | 
|  | 132 | ; DISABLE: cmp r0, #0 | 
|  | 133 | ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 134 | ; | 
|  | 135 | ; SUM is in r0 because it is coalesced with the second | 
|  | 136 | ; argument on the else path. | 
|  | 137 | ; CHECK: movs [[SUM:r0]], #0 | 
|  | 138 | ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10 | 
|  | 139 | ; | 
|  | 140 | ; Next BB. | 
|  | 141 | ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body | 
|  | 142 | ; CHECK: movs [[TMP:r[0-9]+]], #1 | 
|  | 143 | ; CHECK: adds [[SUM]], [[TMP]], [[SUM]] | 
|  | 144 | ; CHECK-NEXT: subs [[IV]], [[IV]], #1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 145 | ; CHECK-NEXT: bne [[LOOP]] | 
|  | 146 | ; | 
|  | 147 | ; Next BB. | 
|  | 148 | ; SUM << 3. | 
|  | 149 | ; CHECK: lsls [[SUM]], [[SUM]], #3 | 
|  | 150 | ; | 
|  | 151 | ; Duplicated epilogue. | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 152 | ; DISABLE-V5T: pop {r4, pc} | 
|  | 153 | ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]] | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 154 | ; | 
|  | 155 | ; CHECK: [[ELSE_LABEL]]: @ %if.else | 
|  | 156 | ; Shift second argument by one and store into returned register. | 
|  | 157 | ; CHECK: lsls r0, r1, #1 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 158 | ; DISABLE-V5T-NEXT: pop {r4, pc} | 
|  | 159 | ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end | 
|  | 160 | ; DISABLE-V4T-NEXT: pop {r4} | 
|  | 161 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 162 | ; DISABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 163 | ; | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 164 | ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 165 | ; ENABLE-NEXT: bx lr | 
|  | 166 | define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { | 
|  | 167 | entry: | 
|  | 168 | %tobool = icmp eq i32 %cond, 0 | 
|  | 169 | br i1 %tobool, label %if.else, label %for.preheader | 
|  | 170 |  | 
|  | 171 | for.preheader: | 
|  | 172 | tail call void asm "nop", ""() | 
|  | 173 | br label %for.body | 
|  | 174 |  | 
|  | 175 | for.body:                                         ; preds = %entry, %for.body | 
|  | 176 | %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] | 
|  | 177 | %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] | 
|  | 178 | %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() | 
|  | 179 | %add = add nsw i32 %call, %sum.04 | 
|  | 180 | %inc = add nuw nsw i32 %i.05, 1 | 
|  | 181 | %exitcond = icmp eq i32 %inc, 10 | 
|  | 182 | br i1 %exitcond, label %for.end, label %for.body | 
|  | 183 |  | 
|  | 184 | for.end:                                          ; preds = %for.body | 
|  | 185 | %shl = shl i32 %add, 3 | 
|  | 186 | br label %if.end | 
|  | 187 |  | 
|  | 188 | if.else:                                          ; preds = %entry | 
|  | 189 | %mul = shl nsw i32 %N, 1 | 
|  | 190 | br label %if.end | 
|  | 191 |  | 
|  | 192 | if.end:                                           ; preds = %if.else, %for.end | 
|  | 193 | %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] | 
|  | 194 | ret i32 %sum.1 | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | declare i32 @something(...) | 
|  | 198 |  | 
|  | 199 | ; Check that we do not perform the shrink-wrapping inside the loop even | 
|  | 200 | ; though that would be legal. The cost model must prevent that. | 
|  | 201 | ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2: | 
|  | 202 | ; Prologue code. | 
|  | 203 | ; Make sure we save the CSR used in the inline asm: r4. | 
|  | 204 | ; CHECK: push {r4 | 
|  | 205 | ; This is the nop. | 
|  | 206 | ; CHECK: mov r8, r8 | 
|  | 207 | ; CHECK: movs [[SUM:r0]], #0 | 
|  | 208 | ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10 | 
|  | 209 | ; Next BB. | 
|  | 210 | ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: @ %for.body | 
|  | 211 | ; CHECK: movs [[TMP:r[0-9]+]], #1 | 
|  | 212 | ; CHECK: adds [[SUM]], [[TMP]], [[SUM]] | 
|  | 213 | ; CHECK-NEXT: subs [[IV]], [[IV]], #1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 214 | ; CHECK-NEXT: bne [[LOOP_LABEL]] | 
|  | 215 | ; Next BB. | 
|  | 216 | ; CHECK: @ %for.exit | 
|  | 217 | ; This is the nop. | 
|  | 218 | ; CHECK: mov r8, r8 | 
|  | 219 | ; CHECK: pop {r4 | 
|  | 220 | define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) { | 
|  | 221 | entry: | 
|  | 222 | br label %for.preheader | 
|  | 223 |  | 
|  | 224 | for.preheader: | 
|  | 225 | tail call void asm "nop", ""() | 
|  | 226 | br label %for.body | 
|  | 227 |  | 
|  | 228 | for.body:                                         ; preds = %for.body, %entry | 
|  | 229 | %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ] | 
|  | 230 | %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ] | 
|  | 231 | %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() | 
|  | 232 | %add = add nsw i32 %call, %sum.03 | 
|  | 233 | %inc = add nuw nsw i32 %i.04, 1 | 
|  | 234 | %exitcond = icmp eq i32 %inc, 10 | 
|  | 235 | br i1 %exitcond, label %for.exit, label %for.body | 
|  | 236 |  | 
|  | 237 | for.exit: | 
|  | 238 | tail call void asm "nop", ""() | 
|  | 239 | br label %for.end | 
|  | 240 |  | 
|  | 241 | for.end:                                          ; preds = %for.body | 
|  | 242 | ret i32 %add | 
|  | 243 | } | 
|  | 244 |  | 
|  | 245 | ; Check with a more complex case that we do not have save within the loop and | 
|  | 246 | ; restore outside. | 
|  | 247 | ; CHECK-LABEL: loopInfoSaveOutsideLoop: | 
|  | 248 | ; | 
|  | 249 | ; ENABLE: cmp r0, #0 | 
|  | 250 | ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 251 | ; | 
|  | 252 | ; Prologue code. | 
|  | 253 | ; Make sure we save the CSR used in the inline asm: r4. | 
|  | 254 | ; CHECK: push {r4, lr} | 
|  | 255 | ; | 
|  | 256 | ; DISABLE: cmp r0, #0 | 
|  | 257 | ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 258 | ; | 
|  | 259 | ; SUM is in r0 because it is coalesced with the second | 
|  | 260 | ; argument on the else path. | 
|  | 261 | ; CHECK: movs [[SUM:r0]], #0 | 
|  | 262 | ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10 | 
|  | 263 | ; | 
|  | 264 | ; Next BB. | 
|  | 265 | ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body | 
|  | 266 | ; CHECK: movs [[TMP:r[0-9]+]], #1 | 
|  | 267 | ; CHECK: adds [[SUM]], [[TMP]], [[SUM]] | 
|  | 268 | ; CHECK-NEXT: subs [[IV]], [[IV]], #1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 269 | ; CHECK-NEXT: bne [[LOOP]] | 
|  | 270 | ; | 
|  | 271 | ; Next BB. | 
|  | 272 | ; SUM << 3. | 
|  | 273 | ; CHECK: lsls [[SUM]], [[SUM]], #3 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 274 | ; ENABLE-V5T-NEXT: pop {r4, pc} | 
|  | 275 | ; ENABLE-V4T-NEXT: pop {r4} | 
|  | 276 | ; ENABLE-V4T-NEXT: pop {r1} | 
|  | 277 | ; ENABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 278 | ; | 
|  | 279 | ; Duplicated epilogue. | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 280 | ; DISABLE-V5T: pop {r4, pc} | 
|  | 281 | ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]] | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 282 | ; | 
|  | 283 | ; CHECK: [[ELSE_LABEL]]: @ %if.else | 
|  | 284 | ; Shift second argument by one and store into returned register. | 
|  | 285 | ; CHECK: lsls r0, r1, #1 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 286 | ; DISABLE-V5T-NEXT: pop {r4, pc} | 
|  | 287 | ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end | 
|  | 288 | ; DISABLE-V4T-NEXT: pop {r4} | 
|  | 289 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 290 | ; DISABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 291 | ; | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 292 | ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 293 | ; ENABLE-NEXT: bx lr | 
|  | 294 | define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) { | 
|  | 295 | entry: | 
|  | 296 | %tobool = icmp eq i32 %cond, 0 | 
|  | 297 | br i1 %tobool, label %if.else, label %for.preheader | 
|  | 298 |  | 
|  | 299 | for.preheader: | 
|  | 300 | tail call void asm "nop", ""() | 
|  | 301 | br label %for.body | 
|  | 302 |  | 
|  | 303 | for.body:                                         ; preds = %entry, %for.body | 
|  | 304 | %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] | 
|  | 305 | %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] | 
|  | 306 | %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() | 
|  | 307 | %add = add nsw i32 %call, %sum.04 | 
|  | 308 | %inc = add nuw nsw i32 %i.05, 1 | 
|  | 309 | %exitcond = icmp eq i32 %inc, 10 | 
|  | 310 | br i1 %exitcond, label %for.end, label %for.body | 
|  | 311 |  | 
|  | 312 | for.end:                                          ; preds = %for.body | 
|  | 313 | tail call void asm "nop", "~{r4}"() | 
|  | 314 | %shl = shl i32 %add, 3 | 
|  | 315 | br label %if.end | 
|  | 316 |  | 
|  | 317 | if.else:                                          ; preds = %entry | 
|  | 318 | %mul = shl nsw i32 %N, 1 | 
|  | 319 | br label %if.end | 
|  | 320 |  | 
|  | 321 | if.end:                                           ; preds = %if.else, %for.end | 
|  | 322 | %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] | 
|  | 323 | ret i32 %sum.1 | 
|  | 324 | } | 
|  | 325 |  | 
|  | 326 | declare void @somethingElse(...) | 
|  | 327 |  | 
|  | 328 | ; Check with a more complex case that we do not have restore within the loop and | 
|  | 329 | ; save outside. | 
|  | 330 | ; CHECK-LABEL: loopInfoRestoreOutsideLoop: | 
|  | 331 | ; | 
|  | 332 | ; ENABLE: cmp r0, #0 | 
|  | 333 | ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 334 | ; | 
|  | 335 | ; Prologue code. | 
|  | 336 | ; Make sure we save the CSR used in the inline asm: r4. | 
|  | 337 | ; CHECK: push {r4, lr} | 
|  | 338 | ; | 
|  | 339 | ; DISABLE-NEXT: cmp r0, #0 | 
|  | 340 | ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 341 | ; | 
|  | 342 | ; SUM is in r0 because it is coalesced with the second | 
|  | 343 | ; argument on the else path. | 
|  | 344 | ; CHECK: movs [[SUM:r0]], #0 | 
|  | 345 | ; CHECK-NEXT: movs [[IV:r[0-9]+]], #10 | 
|  | 346 | ; | 
|  | 347 | ; Next BB. | 
|  | 348 | ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body | 
|  | 349 | ; CHECK: movs [[TMP:r[0-9]+]], #1 | 
|  | 350 | ; CHECK: adds [[SUM]], [[TMP]], [[SUM]] | 
|  | 351 | ; CHECK-NEXT: subs [[IV]], [[IV]], #1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 352 | ; CHECK-NEXT: bne [[LOOP]] | 
|  | 353 | ; | 
|  | 354 | ; Next BB. | 
|  | 355 | ; SUM << 3. | 
|  | 356 | ; CHECK: lsls [[SUM]], [[SUM]], #3 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 357 | ; ENABLE-V5T-NEXT: pop {r4, pc} | 
|  | 358 | ; ENABLE-V4T-NEXT: pop {r4} | 
|  | 359 | ; ENABLE-V4T-NEXT: pop {r1} | 
|  | 360 | ; ENABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 361 | ; | 
|  | 362 | ; Duplicated epilogue. | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 363 | ; DISABLE-V5T: pop {r4, pc} | 
|  | 364 | ; DISABLE-V4T: b [[END_LABEL:LBB[0-9_]+]] | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 365 | ; | 
|  | 366 | ; CHECK: [[ELSE_LABEL]]: @ %if.else | 
|  | 367 | ; Shift second argument by one and store into returned register. | 
|  | 368 | ; CHECK: lsls r0, r1, #1 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 369 | ; DISABLE-V5T-NEXT: pop {r4, pc} | 
|  | 370 | ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end | 
|  | 371 | ; DISABLE-V4T-NEXT: pop {r4} | 
|  | 372 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 373 | ; DISABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 374 | ; | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 375 | ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 376 | ; ENABLE-NEXT: bx lr | 
| Tim Northover | e25e458 | 2018-04-07 10:57:03 +0000 | [diff] [blame] | 377 | define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind { | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 378 | entry: | 
|  | 379 | %tobool = icmp eq i32 %cond, 0 | 
|  | 380 | br i1 %tobool, label %if.else, label %if.then | 
|  | 381 |  | 
|  | 382 | if.then:                                          ; preds = %entry | 
|  | 383 | tail call void asm "nop", "~{r4}"() | 
|  | 384 | br label %for.body | 
|  | 385 |  | 
|  | 386 | for.body:                                         ; preds = %for.body, %if.then | 
|  | 387 | %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ] | 
|  | 388 | %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ] | 
|  | 389 | %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() | 
|  | 390 | %add = add nsw i32 %call, %sum.04 | 
|  | 391 | %inc = add nuw nsw i32 %i.05, 1 | 
|  | 392 | %exitcond = icmp eq i32 %inc, 10 | 
|  | 393 | br i1 %exitcond, label %for.end, label %for.body | 
|  | 394 |  | 
|  | 395 | for.end:                                          ; preds = %for.body | 
|  | 396 | %shl = shl i32 %add, 3 | 
|  | 397 | br label %if.end | 
|  | 398 |  | 
|  | 399 | if.else:                                          ; preds = %entry | 
|  | 400 | %mul = shl nsw i32 %N, 1 | 
|  | 401 | br label %if.end | 
|  | 402 |  | 
|  | 403 | if.end:                                           ; preds = %if.else, %for.end | 
|  | 404 | %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] | 
|  | 405 | ret i32 %sum.1 | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | ; Check that we handle function with no frame information correctly. | 
|  | 409 | ; CHECK-LABEL: emptyFrame: | 
|  | 410 | ; CHECK: @ %entry | 
|  | 411 | ; CHECK-NEXT: movs r0, #0 | 
|  | 412 | ; CHECK-NEXT: bx lr | 
|  | 413 | define i32 @emptyFrame() { | 
|  | 414 | entry: | 
|  | 415 | ret i32 0 | 
|  | 416 | } | 
|  | 417 |  | 
|  | 418 | ; Check that we handle inline asm correctly. | 
|  | 419 | ; CHECK-LABEL: inlineAsm: | 
|  | 420 | ; | 
|  | 421 | ; ENABLE: cmp r0, #0 | 
|  | 422 | ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 423 | ; | 
|  | 424 | ; Prologue code. | 
|  | 425 | ; Make sure we save the CSR used in the inline asm: r4. | 
|  | 426 | ; CHECK: push {r4, lr} | 
|  | 427 | ; | 
|  | 428 | ; DISABLE: cmp r0, #0 | 
|  | 429 | ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 430 | ; | 
|  | 431 | ; CHECK: movs [[IV:r[0-9]+]], #10 | 
|  | 432 | ; | 
|  | 433 | ; Next BB. | 
|  | 434 | ; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body | 
|  | 435 | ; CHECK: movs r4, #1 | 
|  | 436 | ; CHECK: subs [[IV]], [[IV]], #1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 437 | ; CHECK-NEXT: bne [[LOOP]] | 
|  | 438 | ; | 
|  | 439 | ; Next BB. | 
|  | 440 | ; CHECK: movs r0, #0 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 441 | ; ENABLE-V5T-NEXT: pop {r4, pc} | 
|  | 442 | ; ENABLE-V4T-NEXT: pop {r4} | 
|  | 443 | ; ENABLE-V4T-NEXT: pop {r1} | 
|  | 444 | ; ENABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 445 | ; | 
|  | 446 | ; Duplicated epilogue. | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 447 | ; DISABLE-V5T-NEXT: pop {r4, pc} | 
|  | 448 | ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]] | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 449 | ; | 
|  | 450 | ; CHECK: [[ELSE_LABEL]]: @ %if.else | 
|  | 451 | ; Shift second argument by one and store into returned register. | 
|  | 452 | ; CHECK: lsls r0, r1, #1 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 453 | ; DISABLE-V5T-NEXT: pop {r4, pc} | 
|  | 454 | ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end | 
|  | 455 | ; DISABLE-V4T-NEXT: pop {r4} | 
|  | 456 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 457 | ; DISABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 458 | ; | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 459 | ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 460 | ; ENABLE-NEXT: bx lr | 
|  | 461 | define i32 @inlineAsm(i32 %cond, i32 %N) { | 
|  | 462 | entry: | 
|  | 463 | %tobool = icmp eq i32 %cond, 0 | 
|  | 464 | br i1 %tobool, label %if.else, label %for.preheader | 
|  | 465 |  | 
|  | 466 | for.preheader: | 
|  | 467 | tail call void asm "nop", ""() | 
|  | 468 | br label %for.body | 
|  | 469 |  | 
|  | 470 | for.body:                                         ; preds = %entry, %for.body | 
|  | 471 | %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] | 
|  | 472 | tail call void asm sideeffect "movs r4, #1", "~{r4}"() | 
|  | 473 | %inc = add nuw nsw i32 %i.03, 1 | 
|  | 474 | %exitcond = icmp eq i32 %inc, 10 | 
|  | 475 | br i1 %exitcond, label %for.exit, label %for.body | 
|  | 476 |  | 
|  | 477 | for.exit: | 
|  | 478 | tail call void asm "nop", ""() | 
|  | 479 | br label %if.end | 
|  | 480 |  | 
|  | 481 | if.else:                                          ; preds = %entry | 
|  | 482 | %mul = shl nsw i32 %N, 1 | 
|  | 483 | br label %if.end | 
|  | 484 |  | 
|  | 485 | if.end:                                           ; preds = %for.body, %if.else | 
|  | 486 | %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ] | 
|  | 487 | ret i32 %sum.0 | 
|  | 488 | } | 
|  | 489 |  | 
|  | 490 | ; Check that we handle calls to variadic functions correctly. | 
|  | 491 | ; CHECK-LABEL: callVariadicFunc: | 
|  | 492 | ; | 
|  | 493 | ; ENABLE: cmp r0, #0 | 
|  | 494 | ; ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 495 | ; | 
|  | 496 | ; Prologue code. | 
|  | 497 | ; CHECK: push {[[TMP:r[0-9]+]], lr} | 
| Tim Northover | 747ae9a | 2015-11-18 21:10:39 +0000 | [diff] [blame] | 498 | ; CHECK: sub sp, #16 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 499 | ; | 
|  | 500 | ; DISABLE: cmp r0, #0 | 
|  | 501 | ; DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 502 | ; | 
|  | 503 | ; Setup of the varags. | 
|  | 504 | ; CHECK: mov [[TMP_SP:r[0-9]+]], sp | 
|  | 505 | ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]]] | 
|  | 506 | ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]], #4] | 
|  | 507 | ; CHECK-NEXT: str r1, {{\[}}[[TMP_SP]], #8] | 
| Artyom Skrobov | 1388e2f | 2017-03-07 09:38:16 +0000 | [diff] [blame] | 508 | ; CHECK:      movs r0, r1 | 
|  | 509 | ; CHECK-NEXT: movs r2, r1 | 
|  | 510 | ; CHECK-NEXT: movs r3, r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 511 | ; CHECK-NEXT: bl | 
|  | 512 | ; CHECK-NEXT: lsls r0, r0, #3 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 513 | ; | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 514 | ; ENABLE-NEXT: add sp, #16 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 515 | ; ENABLE-V5T-NEXT: pop {[[TMP]], pc} | 
|  | 516 | ; ENABLE-V4T-NEXT: pop {[[TMP]]} | 
|  | 517 | ; ENABLE-V4T-NEXT: pop {r1} | 
|  | 518 | ; ENABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 519 | ; | 
|  | 520 | ; Duplicated epilogue. | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 521 | ; DISABLE-V5T-NEXT: add sp, #16 | 
|  | 522 | ; DISABLE-V5T-NEXT: pop {[[TMP]], pc} | 
|  | 523 | ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]] | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 524 | ; | 
|  | 525 | ; CHECK: [[ELSE_LABEL]]: @ %if.else | 
|  | 526 | ; Shift second argument by one and store into returned register. | 
|  | 527 | ; CHECK: lsls r0, r1, #1 | 
|  | 528 | ; | 
|  | 529 | ; Epilogue code. | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 530 | ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 531 | ; ENABLE-NEXT: bx lr | 
|  | 532 | ; | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 533 | ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 534 | ; DISABLE-NEXT: add sp, #16 | 
| Artyom Skrobov | 0a37b80 | 2015-12-08 19:59:01 +0000 | [diff] [blame] | 535 | ; DISABLE-V5T-NEXT: pop {[[TMP]], pc} | 
|  | 536 | ; DISABLE-V4T-NEXT: pop {[[TMP]]} | 
|  | 537 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 538 | ; DISABLE-V4T-NEXT: bx r1 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 539 | define i32 @callVariadicFunc(i32 %cond, i32 %N) { | 
|  | 540 | entry: | 
|  | 541 | %tobool = icmp eq i32 %cond, 0 | 
|  | 542 | br i1 %tobool, label %if.else, label %if.then | 
|  | 543 |  | 
|  | 544 | if.then:                                          ; preds = %entry | 
|  | 545 | %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N) | 
|  | 546 | %shl = shl i32 %call, 3 | 
|  | 547 | br label %if.end | 
|  | 548 |  | 
|  | 549 | if.else:                                          ; preds = %entry | 
|  | 550 | %mul = shl nsw i32 %N, 1 | 
|  | 551 | br label %if.end | 
|  | 552 |  | 
|  | 553 | if.end:                                           ; preds = %if.else, %if.then | 
|  | 554 | %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ] | 
|  | 555 | ret i32 %sum.0 | 
|  | 556 | } | 
|  | 557 |  | 
|  | 558 | declare i32 @someVariadicFunc(i32, ...) | 
|  | 559 |  | 
|  | 560 | ; Make sure we do not insert unreachable code after noreturn function. | 
|  | 561 | ; Although this is not incorrect to insert such code, it is useless | 
|  | 562 | ; and it hurts the binary size. | 
|  | 563 | ; | 
|  | 564 | ; CHECK-LABEL: noreturn: | 
|  | 565 | ; DISABLE: push | 
|  | 566 | ; | 
| Weiming Zhao | 812fde3 | 2016-07-29 23:33:48 +0000 | [diff] [blame] | 567 | ; CHECK: cmp r0, #0 | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 568 | ; CHECK-NEXT: bne      [[ABORT:LBB[0-9_]+]] | 
|  | 569 | ; | 
|  | 570 | ; CHECK: movs r0, #42 | 
|  | 571 | ; | 
|  | 572 | ; ENABLE-NEXT: bx lr | 
|  | 573 | ; | 
|  | 574 | ; DISABLE-NEXT: pop | 
|  | 575 | ;; | 
|  | 576 | ; CHECK: [[ABORT]]: @ %if.abort | 
|  | 577 | ; | 
|  | 578 | ; ENABLE: push | 
|  | 579 | ; | 
|  | 580 | ; CHECK: bl | 
|  | 581 | ; ENABLE-NOT: pop | 
|  | 582 | define i32 @noreturn(i8 signext %bad_thing) { | 
|  | 583 | entry: | 
|  | 584 | %tobool = icmp eq i8 %bad_thing, 0 | 
|  | 585 | br i1 %tobool, label %if.end, label %if.abort | 
|  | 586 |  | 
|  | 587 | if.abort: | 
|  | 588 | %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() | 
|  | 589 | tail call void @abort() #0 | 
|  | 590 | unreachable | 
|  | 591 |  | 
|  | 592 | if.end: | 
|  | 593 | ret i32 42 | 
|  | 594 | } | 
|  | 595 |  | 
|  | 596 | declare void @abort() #0 | 
|  | 597 |  | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 598 | define i32 @b_to_bx(i32 %value) { | 
|  | 599 | ; CHECK-LABEL: b_to_bx: | 
|  | 600 | ; DISABLE: push {r7, lr} | 
| Geoff Berry | a2b9011 | 2018-02-27 16:59:10 +0000 | [diff] [blame] | 601 | ; CHECK: cmp r0, #49 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 602 | ; CHECK-NEXT: bgt [[ELSE_LABEL:LBB[0-9_]+]] | 
|  | 603 | ; ENABLE: push {r7, lr} | 
|  | 604 |  | 
|  | 605 | ; CHECK: bl | 
|  | 606 | ; DISABLE-V5-NEXT: pop {r7, pc} | 
|  | 607 | ; DISABLE-V4T-NEXT: b [[END_LABEL:LBB[0-9_]+]] | 
|  | 608 |  | 
|  | 609 | ; ENABLE-V5-NEXT: pop {r7, pc} | 
|  | 610 | ; ENABLE-V4-NEXT: pop {r7} | 
|  | 611 | ; ENABLE-V4-NEXT: pop {r1} | 
|  | 612 | ; ENABLE-V4-NEXT: bx r1 | 
|  | 613 |  | 
|  | 614 | ; CHECK: [[ELSE_LABEL]]: @ %if.else | 
|  | 615 | ; CHECK-NEXT: lsls r0, r1, #1 | 
|  | 616 | ; DISABLE-V5-NEXT: pop {r7, pc} | 
|  | 617 | ; DISABLE-V4T-NEXT: [[END_LABEL]]: @ %if.end | 
|  | 618 | ; DISABLE-V4T-NEXT: pop {r7} | 
|  | 619 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 620 | ; DISABLE-V4T-NEXT: bx r1 | 
|  | 621 |  | 
|  | 622 | ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end | 
|  | 623 | ; ENABLE-NEXT: bx lr | 
|  | 624 |  | 
|  | 625 | entry: | 
|  | 626 | %cmp = icmp slt i32 %value, 50 | 
|  | 627 | br i1 %cmp, label %if.then, label %if.else | 
|  | 628 |  | 
|  | 629 | if.then: | 
|  | 630 | %div = sdiv i32 5000, %value | 
|  | 631 | br label %if.end | 
|  | 632 |  | 
|  | 633 | if.else: | 
|  | 634 | %mul = shl nsw i32 %value, 1 | 
|  | 635 | br label %if.end | 
|  | 636 |  | 
|  | 637 | if.end: | 
|  | 638 | %value.addr.0 = phi i32 [ %div, %if.then ], [ %mul, %if.else ] | 
|  | 639 | ret i32 %value.addr.0 | 
|  | 640 | } | 
|  | 641 |  | 
|  | 642 | define i1 @beq_to_bx(i32* %y, i32 %head) { | 
|  | 643 | ; CHECK-LABEL: beq_to_bx: | 
|  | 644 | ; DISABLE: push {r4, lr} | 
|  | 645 | ; CHECK: cmp r2, #0 | 
|  | 646 | ; CHECK-NEXT: beq [[EXIT_LABEL:LBB[0-9_]+]] | 
|  | 647 | ; ENABLE: push {r4, lr} | 
|  | 648 |  | 
|  | 649 | ; CHECK: tst r3, r4 | 
| Momchil Velikov | bd2c7eb | 2017-11-27 10:13:14 +0000 | [diff] [blame] | 650 | ; ENABLE-NEXT: ldr [[POP:r[4567]]], [sp, #4] | 
| Momchil Velikov | dc86e14 | 2017-11-14 10:36:52 +0000 | [diff] [blame] | 651 | ; ENABLE-NEXT: mov lr, [[POP]] | 
|  | 652 | ; ENABLE-NEXT: pop {[[POP]]} | 
|  | 653 | ; ENABLE-NEXT: add sp, #4 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 654 | ; CHECK-NEXT: beq [[EXIT_LABEL]] | 
|  | 655 |  | 
|  | 656 | ; CHECK: str r1, [r2] | 
| Sjoerd Meijer | 96e10b5 | 2016-12-15 09:38:59 +0000 | [diff] [blame] | 657 | ; CHECK: str r3, [r2] | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 658 | ; CHECK-NEXT: movs r0, #0 | 
|  | 659 | ; CHECK-NEXT: [[EXIT_LABEL]]: @ %cleanup | 
|  | 660 | ; ENABLE-NEXT: bx lr | 
|  | 661 | ; DISABLE-V5-NEXT: pop {r4, pc} | 
|  | 662 | ; DISABLE-V4T-NEXT: pop {r4} | 
|  | 663 | ; DISABLE-V4T-NEXT: pop {r1} | 
|  | 664 | ; DISABLE-V4T-NEXT: bx r1 | 
|  | 665 |  | 
|  | 666 | entry: | 
|  | 667 | %cmp = icmp eq i32* %y, null | 
|  | 668 | br i1 %cmp, label %cleanup, label %if.end | 
|  | 669 |  | 
|  | 670 | if.end: | 
|  | 671 | %z = load i32, i32* %y, align 4 | 
|  | 672 | %and = and i32 %z, 2 | 
|  | 673 | %cmp2 = icmp eq i32 %and, 0 | 
|  | 674 | br i1 %cmp2, label %cleanup, label %if.end4 | 
|  | 675 |  | 
|  | 676 | if.end4: | 
|  | 677 | store i32 %head, i32* %y, align 4 | 
| Sjoerd Meijer | 96e10b5 | 2016-12-15 09:38:59 +0000 | [diff] [blame] | 678 | store volatile i32 %z, i32* %y, align 4 | 
| Artyom Skrobov | 2aca0c6 | 2015-12-28 21:40:45 +0000 | [diff] [blame] | 679 | br label %cleanup | 
|  | 680 |  | 
|  | 681 | cleanup: | 
|  | 682 | %retval.0 = phi i1 [ 0, %if.end4 ], [ 1, %entry ], [ 1, %if.end ] | 
|  | 683 | ret i1 %retval.0 | 
|  | 684 | } | 
|  | 685 |  | 
| Quentin Colombet | 48b7720 | 2015-07-22 16:34:37 +0000 | [diff] [blame] | 686 | attributes #0 = { noreturn nounwind } |