| OLD | NEW |
| 1 ; RUN: opt < %s -nacl-expand-tls -S | FileCheck %s | 1 ; RUN: opt < %s -nacl-expand-tls -S | FileCheck %s |
| 2 | 2 |
| 3 | 3 |
| 4 @tvar = thread_local global i32 123 | 4 @tvar = thread_local global i32 123 |
| 5 | 5 |
| 6 define i32* @get_tvar(i1 %cmp) { | 6 define i32* @get_tvar(i1 %cmp) { |
| 7 entry: | 7 entry: |
| 8 br i1 %cmp, label %return, label %else | 8 br i1 %cmp, label %return, label %else |
| 9 | 9 |
| 10 else: | 10 else: |
| 11 br label %return | 11 br label %return |
| 12 | 12 |
| 13 return: | 13 return: |
| 14 %result = phi i32* [ @tvar, %entry ], [ null, %else ] | 14 %result = phi i32* [ @tvar, %entry ], [ null, %else ] |
| 15 ret i32* %result | 15 ret i32* %result |
| 16 } | 16 } |
| 17 ; The TLS access gets pushed back into the PHI node's incoming block, | 17 ; The TLS access gets pushed back into the PHI node's incoming block, |
| 18 ; which might be suboptimal but works in all cases. | 18 ; which might be suboptimal but works in all cases. |
| 19 ; CHECK: define i32* @get_tvar(i1 %cmp) { | 19 ; CHECK: define i32* @get_tvar(i1 %cmp) { |
| 20 ; CHECK: entry: | 20 ; CHECK: entry: |
| 21 ; CHECK: %field = getelementptr %tls_struct* %tls_struct, i32 -1, i32 0, i32 0 | 21 ; CHECK: %field = getelementptr %tls_struct, %tls_struct* %tls_struct, i32 -1, i
32 0, i32 0 |
| 22 ; CHECK: else: | 22 ; CHECK: else: |
| 23 ; CHECK: return: | 23 ; CHECK: return: |
| 24 ; CHECK: %result = phi i32* [ %field, %entry ], [ null, %else ] | 24 ; CHECK: %result = phi i32* [ %field, %entry ], [ null, %else ] |
| 25 | 25 |
| 26 | 26 |
| 27 ; This tests that ExpandTls correctly handles a PHI node that contains | 27 ; This tests that ExpandTls correctly handles a PHI node that contains |
| 28 ; the same TLS variable twice. Using replaceAllUsesWith() is not | 28 ; the same TLS variable twice. Using replaceAllUsesWith() is not |
| 29 ; correct on a PHI node when the new instruction has to be added to an | 29 ; correct on a PHI node when the new instruction has to be added to an |
| 30 ; incoming block. | 30 ; incoming block. |
| 31 define i32* @tls_phi_twice(i1 %arg) { | 31 define i32* @tls_phi_twice(i1 %arg) { |
| 32 br i1 %arg, label %iftrue, label %iffalse | 32 br i1 %arg, label %iftrue, label %iffalse |
| 33 iftrue: | 33 iftrue: |
| 34 br label %exit | 34 br label %exit |
| 35 iffalse: | 35 iffalse: |
| 36 br label %exit | 36 br label %exit |
| 37 exit: | 37 exit: |
| 38 %result = phi i32* [ @tvar, %iftrue ], [ @tvar, %iffalse ] | 38 %result = phi i32* [ @tvar, %iftrue ], [ @tvar, %iffalse ] |
| 39 ret i32* %result | 39 ret i32* %result |
| 40 } | 40 } |
| 41 ; CHECK: define i32* @tls_phi_twice(i1 %arg) { | 41 ; CHECK: define i32* @tls_phi_twice(i1 %arg) { |
| 42 ; CHECK: iftrue: | 42 ; CHECK: iftrue: |
| 43 ; CHECK: %field{{.*}} = getelementptr %tls_struct* %tls_struct{{.*}}, i32 -1, i3
2 0, i32 0 | 43 ; CHECK: %field{{.*}} = getelementptr %tls_struct, %tls_struct* %tls_struct{{.*}
}, i32 -1, i32 0, i32 0 |
| 44 ; CHECK: iffalse: | 44 ; CHECK: iffalse: |
| 45 ; CHECK: %field{{.*}} = getelementptr %tls_struct* %tls_struct{{.*}}, i32 -1, i3
2 0, i32 0 | 45 ; CHECK: %field{{.*}} = getelementptr %tls_struct, %tls_struct* %tls_struct{{.*}
}, i32 -1, i32 0, i32 0 |
| 46 ; CHECK: exit: | 46 ; CHECK: exit: |
| 47 ; CHECK: %result = phi i32* [ %field{{.*}}, %iftrue ], [ %field{{.*}}, %iffalse
] | 47 ; CHECK: %result = phi i32* [ %field{{.*}}, %iftrue ], [ %field{{.*}}, %iffalse
] |
| 48 | 48 |
| 49 | 49 |
| 50 ; In this corner case, ExpandTls must expand out @tvar only once, | 50 ; In this corner case, ExpandTls must expand out @tvar only once, |
| 51 ; otherwise it will produce invalid IR. | 51 ; otherwise it will produce invalid IR. |
| 52 define i32* @tls_phi_multiple_entry(i1 %arg) { | 52 define i32* @tls_phi_multiple_entry(i1 %arg) { |
| 53 entry: | 53 entry: |
| 54 br i1 %arg, label %done, label %done | 54 br i1 %arg, label %done, label %done |
| 55 done: | 55 done: |
| 56 %result = phi i32* [ @tvar, %entry ], [ @tvar, %entry ] | 56 %result = phi i32* [ @tvar, %entry ], [ @tvar, %entry ] |
| 57 ret i32* %result | 57 ret i32* %result |
| 58 } | 58 } |
| 59 ; CHECK: define i32* @tls_phi_multiple_entry(i1 %arg) { | 59 ; CHECK: define i32* @tls_phi_multiple_entry(i1 %arg) { |
| 60 ; CHECK: %result = phi i32* [ %field, %entry ], [ %field, %entry ] | 60 ; CHECK: %result = phi i32* [ %field, %entry ], [ %field, %entry ] |
| OLD | NEW |