| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; Run with --no_x86_scrub_rip because we care a lot about how globals are |
| ; accessed in the code model. |
| |
| ; RUN: llc < %s -relocation-model=static -code-model=small | FileCheck %s --check-prefix=CHECK --check-prefix=SMALL-STATIC |
| ; RUN: llc < %s -relocation-model=static -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-STATIC |
| ; RUN: llc < %s -relocation-model=static -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-STATIC |
| ; RUN: llc < %s -relocation-model=pic -code-model=small | FileCheck %s --check-prefix=CHECK --check-prefix=SMALL-PIC |
| ; RUN: llc < %s -relocation-model=pic -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-PIC |
| ; RUN: llc < %s -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC |
| |
| ; Generated from this C source: |
| ; |
| ; static int static_data[10]; |
| ; int global_data[10] = {1, 2}; |
| ; extern int extern_data[10]; |
| ; |
| ; int *lea_static_data() { return &static_data[0]; } |
| ; int *lea_global_data() { return &global_data[0]; } |
| ; int *lea_extern_data() { return &extern_data[0]; } |
| ; |
| ; static void static_fn(void) {} |
| ; void global_fn(void) {} |
| ; void extern_fn(void); |
| ; |
| ; typedef void (*void_fn)(void); |
| ; void_fn lea_static_fn() { return &static_fn; } |
| ; void_fn lea_global_fn() { return &global_fn; } |
| ; void_fn lea_extern_fn() { return &extern_fn; } |
| |
| |
| ; ModuleID = 'model.c' |
| source_filename = "model.c" |
| target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| target triple = "x86_64--linux" |
| |
| @global_data = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16 |
| @static_data = internal global [10 x i32] zeroinitializer, align 16 |
| @extern_data = external global [10 x i32], align 16 |
| |
| define dso_local i32* @lea_static_data() #0 { |
| ; SMALL-STATIC-LABEL: lea_static_data: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl $static_data, %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: lea_static_data: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $static_data, %rax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: lea_static_data: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $static_data, %rax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: lea_static_data: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: leaq static_data(%rip), %rax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: lea_static_data: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx |
| ; MEDIUM-PIC-NEXT: movabsq $static_data@GOTOFF, %rax |
| ; MEDIUM-PIC-NEXT: addq %rcx, %rax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: lea_static_data: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp0: |
| ; LARGE-PIC-NEXT: leaq .Ltmp0(%rip), %rcx |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp0, %rax |
| ; LARGE-PIC-NEXT: addq %rax, %rcx |
| ; LARGE-PIC-NEXT: movabsq $static_data@GOTOFF, %rax |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: retq |
| ret i32* getelementptr inbounds ([10 x i32], [10 x i32]* @static_data, i64 0, i64 0) |
| } |
| |
| define dso_local i32* @lea_global_data() #0 { |
| ; SMALL-STATIC-LABEL: lea_global_data: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl $global_data, %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: lea_global_data: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $global_data, %rax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: lea_global_data: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $global_data, %rax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: lea_global_data: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: leaq global_data(%rip), %rax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: lea_global_data: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx |
| ; MEDIUM-PIC-NEXT: movabsq $global_data@GOTOFF, %rax |
| ; MEDIUM-PIC-NEXT: addq %rcx, %rax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: lea_global_data: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp1: |
| ; LARGE-PIC-NEXT: leaq .Ltmp1(%rip), %rcx |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp1, %rax |
| ; LARGE-PIC-NEXT: addq %rax, %rcx |
| ; LARGE-PIC-NEXT: movabsq $global_data@GOTOFF, %rax |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: retq |
| ret i32* getelementptr inbounds ([10 x i32], [10 x i32]* @global_data, i64 0, i64 0) |
| } |
| |
| define dso_local i32* @lea_extern_data() #0 { |
| ; SMALL-STATIC-LABEL: lea_extern_data: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl $extern_data, %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: lea_extern_data: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $extern_data, %rax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: lea_extern_data: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $extern_data, %rax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: lea_extern_data: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: lea_extern_data: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: lea_extern_data: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp2: |
| ; LARGE-PIC-NEXT: leaq .Ltmp2(%rip), %rax |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp2, %rcx |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: movabsq $extern_data@GOT, %rcx |
| ; LARGE-PIC-NEXT: movq (%rax,%rcx), %rax |
| ; LARGE-PIC-NEXT: retq |
| ret i32* getelementptr inbounds ([10 x i32], [10 x i32]* @extern_data, i64 0, i64 0) |
| } |
| |
| define dso_local i32 @load_global_data() #0 { |
| ; SMALL-STATIC-LABEL: load_global_data: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl global_data+8(%rip), %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: load_global_data: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $global_data, %rax |
| ; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: load_global_data: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $global_data, %rax |
| ; LARGE-STATIC-NEXT: movl 8(%rax), %eax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: load_global_data: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: movl global_data+8(%rip), %eax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: load_global_data: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax |
| ; MEDIUM-PIC-NEXT: movabsq $global_data@GOTOFF, %rcx |
| ; MEDIUM-PIC-NEXT: movl 8(%rax,%rcx), %eax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: load_global_data: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp3: |
| ; LARGE-PIC-NEXT: leaq .Ltmp3(%rip), %rax |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp3, %rcx |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: movabsq $global_data@GOTOFF, %rcx |
| ; LARGE-PIC-NEXT: movl 8(%rax,%rcx), %eax |
| ; LARGE-PIC-NEXT: retq |
| %rv = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @global_data, i64 0, i64 2) |
| ret i32 %rv |
| } |
| |
| define dso_local i32 @load_extern_data() #0 { |
| ; SMALL-STATIC-LABEL: load_extern_data: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl extern_data+8(%rip), %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: load_extern_data: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $extern_data, %rax |
| ; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: load_extern_data: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $extern_data, %rax |
| ; LARGE-STATIC-NEXT: movl 8(%rax), %eax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: load_extern_data: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax |
| ; SMALL-PIC-NEXT: movl 8(%rax), %eax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: load_extern_data: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax |
| ; MEDIUM-PIC-NEXT: movl 8(%rax), %eax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: load_extern_data: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp4: |
| ; LARGE-PIC-NEXT: leaq .Ltmp4(%rip), %rax |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp4, %rcx |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: movabsq $extern_data@GOT, %rcx |
| ; LARGE-PIC-NEXT: movq (%rax,%rcx), %rax |
| ; LARGE-PIC-NEXT: movl 8(%rax), %eax |
| ; LARGE-PIC-NEXT: retq |
| %rv = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @extern_data, i64 0, i64 2) |
| ret i32 %rv |
| } |
| |
| define dso_local void @global_fn() #0 { |
| ; CHECK-LABEL: global_fn: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: retq |
| ret void |
| } |
| |
| define internal void @static_fn() #0 { |
| ; CHECK-LABEL: static_fn: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: retq |
| ret void |
| } |
| |
| declare void @extern_fn() |
| |
| define dso_local void ()* @lea_static_fn() #0 { |
| ; SMALL-STATIC-LABEL: lea_static_fn: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl $static_fn, %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: lea_static_fn: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $static_fn, %rax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: lea_static_fn: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $static_fn, %rax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: lea_static_fn: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: leaq static_fn(%rip), %rax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: lea_static_fn: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: movabsq $static_fn, %rax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: lea_static_fn: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp5: |
| ; LARGE-PIC-NEXT: leaq .Ltmp5(%rip), %rcx |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp5, %rax |
| ; LARGE-PIC-NEXT: addq %rax, %rcx |
| ; LARGE-PIC-NEXT: movabsq $static_fn@GOTOFF, %rax |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: retq |
| ret void ()* @static_fn |
| } |
| |
| define dso_local void ()* @lea_global_fn() #0 { |
| ; SMALL-STATIC-LABEL: lea_global_fn: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl $global_fn, %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: lea_global_fn: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $global_fn, %rax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: lea_global_fn: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $global_fn, %rax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: lea_global_fn: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: leaq global_fn(%rip), %rax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: lea_global_fn: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: movabsq $global_fn, %rax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: lea_global_fn: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp6: |
| ; LARGE-PIC-NEXT: leaq .Ltmp6(%rip), %rcx |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp6, %rax |
| ; LARGE-PIC-NEXT: addq %rax, %rcx |
| ; LARGE-PIC-NEXT: movabsq $global_fn@GOTOFF, %rax |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: retq |
| ret void ()* @global_fn |
| } |
| |
| define dso_local void ()* @lea_extern_fn() #0 { |
| ; SMALL-STATIC-LABEL: lea_extern_fn: |
| ; SMALL-STATIC: # %bb.0: |
| ; SMALL-STATIC-NEXT: movl $extern_fn, %eax |
| ; SMALL-STATIC-NEXT: retq |
| ; |
| ; MEDIUM-STATIC-LABEL: lea_extern_fn: |
| ; MEDIUM-STATIC: # %bb.0: |
| ; MEDIUM-STATIC-NEXT: movabsq $extern_fn, %rax |
| ; MEDIUM-STATIC-NEXT: retq |
| ; |
| ; LARGE-STATIC-LABEL: lea_extern_fn: |
| ; LARGE-STATIC: # %bb.0: |
| ; LARGE-STATIC-NEXT: movabsq $extern_fn, %rax |
| ; LARGE-STATIC-NEXT: retq |
| ; |
| ; SMALL-PIC-LABEL: lea_extern_fn: |
| ; SMALL-PIC: # %bb.0: |
| ; SMALL-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax |
| ; SMALL-PIC-NEXT: retq |
| ; |
| ; MEDIUM-PIC-LABEL: lea_extern_fn: |
| ; MEDIUM-PIC: # %bb.0: |
| ; MEDIUM-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax |
| ; MEDIUM-PIC-NEXT: retq |
| ; |
| ; LARGE-PIC-LABEL: lea_extern_fn: |
| ; LARGE-PIC: # %bb.0: |
| ; LARGE-PIC-NEXT: .Ltmp7: |
| ; LARGE-PIC-NEXT: leaq .Ltmp7(%rip), %rax |
| ; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.Ltmp7, %rcx |
| ; LARGE-PIC-NEXT: addq %rcx, %rax |
| ; LARGE-PIC-NEXT: movabsq $extern_fn@GOT, %rcx |
| ; LARGE-PIC-NEXT: movq (%rax,%rcx), %rax |
| ; LARGE-PIC-NEXT: retq |
| ret void ()* @extern_fn |
| } |
| |
| attributes #0 = { noinline nounwind uwtable } |
| |
| !llvm.module.flags = !{!0, !1, !2} |
| !llvm.ident = !{!3} |
| |
| !0 = !{i32 1, !"wchar_size", i32 4} |
| !1 = !{i32 7, !"PIC Level", i32 2} |
| !2 = !{i32 7, !"PIE Level", i32 2} |
| !3 = !{!"clang version 7.0.0 "} |