166 lines · plain
1; RUN: llc -verify-machineinstrs -mtriple=x86_64-unknown < %s | FileCheck %s --implicit-check-not="jmp.*\*" --implicit-check-not="call.*\*" --check-prefix=X642; RUN: llc -verify-machineinstrs -mtriple=x86_64-unknown -O0 < %s | FileCheck %s --implicit-check-not="jmp.*\*" --implicit-check-not="call.*\*" --check-prefix=X64FAST3 4; RUN: llc -verify-machineinstrs -mtriple=i686-unknown < %s | FileCheck %s --implicit-check-not="jmp.*\*" --implicit-check-not="call.*\*" --check-prefix=X865; RUN: llc -verify-machineinstrs -mtriple=i686-unknown -O0 < %s | FileCheck %s --implicit-check-not="jmp.*\*" --implicit-check-not="call.*\*" --check-prefix=X86FAST6 7declare dso_local void @bar(i32)8 9; Test a simple indirect call and tail call.10define void @icall_reg(ptr %fp, i32 %x) #0 {11entry:12 tail call void @bar(i32 %x)13 tail call void %fp(i32 %x)14 tail call void @bar(i32 %x)15 tail call void %fp(i32 %x)16 ret void17}18 19; X64-LABEL: icall_reg:20; X64-DAG: movq %rdi, %[[fp:[^ ]*]]21; X64-DAG: movl %esi, %[[x:[^ ]*]]22; X64: movl %esi, %edi23; X64: callq bar24; X64-DAG: movl %[[x]], %edi25; X64-DAG: movq %[[fp]], %r1126; X64: callq __x86_indirect_thunk_r1127; X64: movl %[[x]], %edi28; X64: callq bar29; X64-DAG: movl %[[x]], %edi30; X64-DAG: movq %[[fp]], %r1131; X64: jmp __x86_indirect_thunk_r11 # TAILCALL32 33; X64FAST-LABEL: icall_reg:34; X64FAST: callq bar35; X64FAST: callq __x86_indirect_thunk_r1136; X64FAST: callq bar37; X64FAST: jmp __x86_indirect_thunk_r11 # TAILCALL38 39; X86-LABEL: icall_reg:40; X86-DAG: movl 12(%esp), %[[fp:[^ ]*]]41; X86-DAG: movl 16(%esp), %[[x:[^ ]*]]42; X86: pushl %[[x]]43; X86: calll bar44; X86: movl %[[fp]], %eax45; X86: pushl %[[x]]46; X86: calll __x86_indirect_thunk_eax47; X86: pushl %[[x]]48; X86: calll bar49; X86: movl %[[fp]], %eax50; X86: pushl %[[x]]51; X86: calll __x86_indirect_thunk_eax52; X86-NOT: # TAILCALL53 54; X86FAST-LABEL: icall_reg:55; X86FAST: calll bar56; X86FAST: calll __x86_indirect_thunk_eax57; X86FAST: calll bar58; X86FAST: calll __x86_indirect_thunk_eax59 60 61@global_fp = external dso_local global ptr62 63; Test an indirect call through a global variable.64define void @icall_global_fp(i32 %x, ptr %fpp) #0 {65 %fp1 = load ptr, ptr @global_fp66 call void %fp1(i32 %x)67 %fp2 = load ptr, ptr @global_fp68 tail call void %fp2(i32 %x)69 ret void70}71 72; X64-LABEL: icall_global_fp:73; X64-DAG: movl %edi, %[[x:[^ ]*]]74; X64-DAG: movq global_fp(%rip), %r1175; X64: callq __x86_indirect_thunk_r1176; X64-DAG: movl %[[x]], %edi77; X64-DAG: movq global_fp(%rip), %r1178; X64: jmp __x86_indirect_thunk_r11 # TAILCALL79 80; X64FAST-LABEL: icall_global_fp:81; X64FAST: movq global_fp(%rip), %r1182; X64FAST: callq __x86_indirect_thunk_r1183; X64FAST: movq global_fp(%rip), %r1184; X64FAST: jmp __x86_indirect_thunk_r11 # TAILCALL85 86; X86-LABEL: icall_global_fp:87; X86: movl global_fp, %eax88; X86: pushl 4(%esp)89; X86: calll __x86_indirect_thunk_eax90; X86: addl $4, %esp91; X86: movl global_fp, %eax92; X86: jmp __x86_indirect_thunk_eax # TAILCALL93 94; X86FAST-LABEL: icall_global_fp:95; X86FAST: calll __x86_indirect_thunk_eax96; X86FAST: jmp __x86_indirect_thunk_eax # TAILCALL97 98 99%struct.Foo = type { ptr }100 101; Test an indirect call through a vtable.102define void @vcall(ptr %obj) #0 {103 %vptr = load ptr, ptr %obj104 %vslot = getelementptr ptr, ptr %vptr, i32 1105 %fp = load ptr, ptr %vslot106 tail call void %fp(ptr %obj)107 tail call void %fp(ptr %obj)108 ret void109}110 111; X64-LABEL: vcall:112; X64: movq %rdi, %[[obj:[^ ]*]]113; X64: movq (%rdi), %[[vptr:[^ ]*]]114; X64: movq 8(%[[vptr]]), %[[fp:[^ ]*]]115; X64: movq %[[fp]], %r11116; X64: callq __x86_indirect_thunk_r11117; X64-DAG: movq %[[obj]], %rdi118; X64-DAG: movq %[[fp]], %r11119; X64: jmp __x86_indirect_thunk_r11 # TAILCALL120 121; X64FAST-LABEL: vcall:122; X64FAST: callq __x86_indirect_thunk_r11123; X64FAST: jmp __x86_indirect_thunk_r11 # TAILCALL124 125; X86-LABEL: vcall:126; X86: movl 8(%esp), %[[obj:[^ ]*]]127; X86: movl (%[[obj]]), %[[vptr:[^ ]*]]128; X86: movl 4(%[[vptr]]), %[[fp:[^ ]*]]129; X86: movl %[[fp]], %eax130; X86: pushl %[[obj]]131; X86: calll __x86_indirect_thunk_eax132; X86: addl $4, %esp133; X86: movl %[[fp]], %eax134; X86: jmp __x86_indirect_thunk_eax # TAILCALL135 136; X86FAST-LABEL: vcall:137; X86FAST: calll __x86_indirect_thunk_eax138; X86FAST: jmp __x86_indirect_thunk_eax # TAILCALL139 140 141declare dso_local void @direct_callee()142 143define void @direct_tail() #0 {144 tail call void @direct_callee()145 ret void146}147 148; X64-LABEL: direct_tail:149; X64: jmp direct_callee # TAILCALL150; X64FAST-LABEL: direct_tail:151; X64FAST: jmp direct_callee # TAILCALL152; X86-LABEL: direct_tail:153; X86: jmp direct_callee # TAILCALL154; X86FAST-LABEL: direct_tail:155; X86FAST: jmp direct_callee # TAILCALL156 157 158; Lastly check that no thunks were emitted.159; X64-NOT: __{{.*}}_retpoline_{{.*}}:160; X64FAST-NOT: __{{.*}}_retpoline_{{.*}}:161; X86-NOT: __{{.*}}_retpoline_{{.*}}:162; X86FAST-NOT: __{{.*}}_retpoline_{{.*}}:163 164 165attributes #0 = { "target-features"="+retpoline-indirect-calls,+retpoline-external-thunk" }166