1 ; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu | FileCheck -check-prefix=X32_LINUX %s 2 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s 3 ; RUN: llc < %s -march=x86 -mtriple=x86-pc-win32 | FileCheck -check-prefix=X32_WIN %s 4 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s 5 6 @i1 = thread_local global i32 15 7 @i2 = external thread_local global i32 8 @i3 = internal thread_local global i32 15 9 @i4 = hidden thread_local global i32 15 10 @i5 = external hidden thread_local global i32 11 @s1 = thread_local global i16 15 12 @b1 = thread_local global i8 0 13 14 define i32 @f1() { 15 ; X32_LINUX: f1: 16 ; X32_LINUX: movl %gs:i1@NTPOFF, %eax 17 ; X32_LINUX-NEXT: ret 18 ; X64_LINUX: f1: 19 ; X64_LINUX: movl %fs:i1@TPOFF, %eax 20 ; X64_LINUX-NEXT: ret 21 ; X32_WIN: f1: 22 ; X32_WIN: movl __tls_index, %eax 23 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 24 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 25 ; X32_WIN-NEXT: movl _i1@SECREL(%eax), %eax 26 ; X32_WIN-NEXT: ret 27 ; X64_WIN: f1: 28 ; X64_WIN: movl _tls_index(%rip), %eax 29 ; X64_WIN-NEXT: movq %gs:88, %rcx 30 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 31 ; X64_WIN-NEXT: movl i1@SECREL(%rax), %eax 32 ; X64_WIN-NEXT: ret 33 34 entry: 35 %tmp1 = load i32* @i1 36 ret i32 %tmp1 37 } 38 39 define i32* @f2() { 40 ; X32_LINUX: f2: 41 ; X32_LINUX: movl %gs:0, %eax 42 ; X32_LINUX-NEXT: leal i1@NTPOFF(%eax), %eax 43 ; X32_LINUX-NEXT: ret 44 ; X64_LINUX: f2: 45 ; X64_LINUX: movq %fs:0, %rax 46 ; X64_LINUX-NEXT: leaq i1@TPOFF(%rax), %rax 47 ; X64_LINUX-NEXT: ret 48 ; X32_WIN: f2: 49 ; X32_WIN: movl __tls_index, %eax 50 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 51 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 52 ; X32_WIN-NEXT: leal _i1@SECREL(%eax), %eax 53 ; X32_WIN-NEXT: ret 54 ; X64_WIN: f2: 55 ; X64_WIN: movl _tls_index(%rip), %eax 56 ; X64_WIN-NEXT: movq %gs:88, %rcx 57 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 58 ; X64_WIN-NEXT: leaq i1@SECREL(%rax), %rax 59 ; X64_WIN-NEXT: ret 60 61 entry: 62 ret i32* @i1 63 } 64 65 define i32 @f3() nounwind { 66 ; X32_LINUX: f3: 67 ; X32_LINUX: movl i2@INDNTPOFF, %eax 68 ; X32_LINUX-NEXT: movl %gs:(%eax), %eax 69 ; X32_LINUX-NEXT: ret 70 ; X64_LINUX: f3: 71 ; X64_LINUX: movq i2@GOTTPOFF(%rip), %rax 72 ; X64_LINUX-NEXT: movl %fs:(%rax), %eax 73 ; X64_LINUX-NEXT: ret 74 ; X32_WIN: f3: 75 ; X32_WIN: movl __tls_index, %eax 76 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 77 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 78 ; X32_WIN-NEXT: movl _i2@SECREL(%eax), %eax 79 ; X32_WIN-NEXT: ret 80 ; X64_WIN: f3: 81 ; X64_WIN: movl _tls_index(%rip), %eax 82 ; X64_WIN-NEXT: movq %gs:88, %rcx 83 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 84 ; X64_WIN-NEXT: movl i2@SECREL(%rax), %eax 85 ; X64_WIN-NEXT: ret 86 87 entry: 88 %tmp1 = load i32* @i2 89 ret i32 %tmp1 90 } 91 92 define i32* @f4() { 93 ; X32_LINUX: f4: 94 ; X32_LINUX: movl %gs:0, %eax 95 ; X32_LINUX-NEXT: addl i2@INDNTPOFF, %eax 96 ; X32_LINUX-NEXT: ret 97 ; X64_LINUX: f4: 98 ; X64_LINUX: movq %fs:0, %rax 99 ; X64_LINUX-NEXT: addq i2@GOTTPOFF(%rip), %rax 100 ; X64_LINUX-NEXT: ret 101 ; X32_WIN: f4: 102 ; X32_WIN: movl __tls_index, %eax 103 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 104 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 105 ; X32_WIN-NEXT: leal _i2@SECREL(%eax), %eax 106 ; X32_WIN-NEXT: ret 107 ; X64_WIN: f4: 108 ; X64_WIN: movl _tls_index(%rip), %eax 109 ; X64_WIN-NEXT: movq %gs:88, %rcx 110 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 111 ; X64_WIN-NEXT: leaq i2@SECREL(%rax), %rax 112 ; X64_WIN-NEXT: ret 113 114 entry: 115 ret i32* @i2 116 } 117 118 define i32 @f5() nounwind { 119 ; X32_LINUX: f5: 120 ; X32_LINUX: movl %gs:i3@NTPOFF, %eax 121 ; X32_LINUX-NEXT: ret 122 ; X64_LINUX: f5: 123 ; X64_LINUX: movl %fs:i3@TPOFF, %eax 124 ; X64_LINUX-NEXT: ret 125 ; X32_WIN: f5: 126 ; X32_WIN: movl __tls_index, %eax 127 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 128 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 129 ; X32_WIN-NEXT: movl _i3@SECREL(%eax), %eax 130 ; X32_WIN-NEXT: ret 131 ; X64_WIN: f5: 132 ; X64_WIN: movl _tls_index(%rip), %eax 133 ; X64_WIN-NEXT: movq %gs:88, %rcx 134 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 135 ; X64_WIN-NEXT: movl i3@SECREL(%rax), %eax 136 ; X64_WIN-NEXT: ret 137 138 entry: 139 %tmp1 = load i32* @i3 140 ret i32 %tmp1 141 } 142 143 define i32* @f6() { 144 ; X32_LINUX: f6: 145 ; X32_LINUX: movl %gs:0, %eax 146 ; X32_LINUX-NEXT: leal i3@NTPOFF(%eax), %eax 147 ; X32_LINUX-NEXT: ret 148 ; X64_LINUX: f6: 149 ; X64_LINUX: movq %fs:0, %rax 150 ; X64_LINUX-NEXT: leaq i3@TPOFF(%rax), %rax 151 ; X64_LINUX-NEXT: ret 152 ; X32_WIN: f6: 153 ; X32_WIN: movl __tls_index, %eax 154 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 155 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 156 ; X32_WIN-NEXT: leal _i3@SECREL(%eax), %eax 157 ; X32_WIN-NEXT: ret 158 ; X64_WIN: f6: 159 ; X64_WIN: movl _tls_index(%rip), %eax 160 ; X64_WIN-NEXT: movq %gs:88, %rcx 161 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 162 ; X64_WIN-NEXT: leaq i3@SECREL(%rax), %rax 163 ; X64_WIN-NEXT: ret 164 165 entry: 166 ret i32* @i3 167 } 168 169 define i32 @f7() { 170 ; X32_LINUX: f7: 171 ; X32_LINUX: movl %gs:i4@NTPOFF, %eax 172 ; X32_LINUX-NEXT: ret 173 ; X64_LINUX: f7: 174 ; X64_LINUX: movl %fs:i4@TPOFF, %eax 175 ; X64_LINUX-NEXT: ret 176 177 entry: 178 %tmp1 = load i32* @i4 179 ret i32 %tmp1 180 } 181 182 define i32* @f8() { 183 ; X32_LINUX: f8: 184 ; X32_LINUX: movl %gs:0, %eax 185 ; X32_LINUX-NEXT: leal i4@NTPOFF(%eax), %eax 186 ; X32_LINUX-NEXT: ret 187 ; X64_LINUX: f8: 188 ; X64_LINUX: movq %fs:0, %rax 189 ; X64_LINUX-NEXT: leaq i4@TPOFF(%rax), %rax 190 ; X64_LINUX-NEXT: ret 191 192 entry: 193 ret i32* @i4 194 } 195 196 define i32 @f9() { 197 ; X32_LINUX: f9: 198 ; X32_LINUX: movl %gs:i5@NTPOFF, %eax 199 ; X32_LINUX-NEXT: ret 200 ; X64_LINUX: f9: 201 ; X64_LINUX: movl %fs:i5@TPOFF, %eax 202 ; X64_LINUX-NEXT: ret 203 204 entry: 205 %tmp1 = load i32* @i5 206 ret i32 %tmp1 207 } 208 209 define i32* @f10() { 210 ; X32_LINUX: f10: 211 ; X32_LINUX: movl %gs:0, %eax 212 ; X32_LINUX-NEXT: leal i5@NTPOFF(%eax), %eax 213 ; X32_LINUX-NEXT: ret 214 ; X64_LINUX: f10: 215 ; X64_LINUX: movq %fs:0, %rax 216 ; X64_LINUX-NEXT: leaq i5@TPOFF(%rax), %rax 217 ; X64_LINUX-NEXT: ret 218 219 entry: 220 ret i32* @i5 221 } 222 223 define i16 @f11() { 224 ; X32_LINUX: f11: 225 ; X32_LINUX: movzwl %gs:s1@NTPOFF, %eax 226 ; Why is this kill line here, but no where else? 227 ; X32_LINUX-NEXT: # kill 228 ; X32_LINUX-NEXT: ret 229 ; X64_LINUX: f11: 230 ; X64_LINUX: movzwl %fs:s1@TPOFF, %eax 231 ; X64_LINUX-NEXT: # kill 232 ; X64_LINUX-NEXT: ret 233 ; X32_WIN: f11: 234 ; X32_WIN: movl __tls_index, %eax 235 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 236 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 237 ; X32_WIN-NEXT: movzwl _s1@SECREL(%eax), %eax 238 ; X32_WIN-NEXT: # kill 239 ; X32_WIN-NEXT: ret 240 ; X64_WIN: f11: 241 ; X64_WIN: movl _tls_index(%rip), %eax 242 ; X64_WIN-NEXT: movq %gs:88, %rcx 243 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 244 ; X64_WIN-NEXT: movzwl s1@SECREL(%rax), %eax 245 ; X64_WIN-NEXT: # kill 246 ; X64_WIN-NEXT: ret 247 248 entry: 249 %tmp1 = load i16* @s1 250 ret i16 %tmp1 251 } 252 253 define i32 @f12() { 254 ; X32_LINUX: f12: 255 ; X32_LINUX: movswl %gs:s1@NTPOFF, %eax 256 ; X32_LINUX-NEXT: ret 257 ; X64_LINUX: f12: 258 ; X64_LINUX: movswl %fs:s1@TPOFF, %eax 259 ; X64_LINUX-NEXT: ret 260 ; X32_WIN: f12: 261 ; X32_WIN: movl __tls_index, %eax 262 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 263 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 264 ; X32_WIN-NEXT: movswl _s1@SECREL(%eax), %eax 265 ; X32_WIN-NEXT: ret 266 ; X64_WIN: f12: 267 ; X64_WIN: movl _tls_index(%rip), %eax 268 ; X64_WIN-NEXT: movq %gs:88, %rcx 269 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 270 ; X64_WIN-NEXT: movswl s1@SECREL(%rax), %eax 271 ; X64_WIN-NEXT: ret 272 273 entry: 274 %tmp1 = load i16* @s1 275 %tmp2 = sext i16 %tmp1 to i32 276 ret i32 %tmp2 277 } 278 279 define i8 @f13() { 280 ; X32_LINUX: f13: 281 ; X32_LINUX: movb %gs:b1@NTPOFF, %al 282 ; X32_LINUX-NEXT: ret 283 ; X64_LINUX: f13: 284 ; X64_LINUX: movb %fs:b1@TPOFF, %al 285 ; X64_LINUX-NEXT: ret 286 ; X32_WIN: f13: 287 ; X32_WIN: movl __tls_index, %eax 288 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 289 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 290 ; X32_WIN-NEXT: movb _b1@SECREL(%eax), %al 291 ; X32_WIN-NEXT: ret 292 ; X64_WIN: f13: 293 ; X64_WIN: movl _tls_index(%rip), %eax 294 ; X64_WIN-NEXT: movq %gs:88, %rcx 295 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 296 ; X64_WIN-NEXT: movb b1@SECREL(%rax), %al 297 ; X64_WIN-NEXT: ret 298 299 entry: 300 %tmp1 = load i8* @b1 301 ret i8 %tmp1 302 } 303 304 define i32 @f14() { 305 ; X32_LINUX: f14: 306 ; X32_LINUX: movsbl %gs:b1@NTPOFF, %eax 307 ; X32_LINUX-NEXT: ret 308 ; X64_LINUX: f14: 309 ; X64_LINUX: movsbl %fs:b1@TPOFF, %eax 310 ; X64_LINUX-NEXT: ret 311 ; X32_WIN: f14: 312 ; X32_WIN: movl __tls_index, %eax 313 ; X32_WIN-NEXT: movl %fs:__tls_array, %ecx 314 ; X32_WIN-NEXT: movl (%ecx,%eax,4), %eax 315 ; X32_WIN-NEXT: movsbl _b1@SECREL(%eax), %eax 316 ; X32_WIN-NEXT: ret 317 ; X64_WIN: f14: 318 ; X64_WIN: movl _tls_index(%rip), %eax 319 ; X64_WIN-NEXT: movq %gs:88, %rcx 320 ; X64_WIN-NEXT: movq (%rcx,%rax,8), %rax 321 ; X64_WIN-NEXT: movsbl b1@SECREL(%rax), %eax 322 ; X64_WIN-NEXT: ret 323 324 entry: 325 %tmp1 = load i8* @b1 326 %tmp2 = sext i8 %tmp1 to i32 327 ret i32 %tmp2 328 } 329 330