|  | ; Test of multiple indirect calls to the same target.  Each call | 
|  | ; should be to the same operand, whether it's in a register or on the | 
|  | ; stack. | 
|  |  | 
|  | ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 
|  | ; RUN:   --target x8632 -i %s --args -O2 \ | 
|  | ; RUN:   | %if --need=target_X8632 --command FileCheck %s | 
|  | ; RUN: %if --need=allow_dump --need=target_X8632 --command %p2i --filetype=asm \ | 
|  | ; RUN:     --assemble --disassemble -i %s --args -O2 \ | 
|  | ; RUN:   | %if --need=allow_dump --need=target_X8632 --command FileCheck %s | 
|  | ; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ | 
|  | ; RUN:   --target x8632 -i %s --args -Om1 \ | 
|  | ; RUN:   | %if --need=target_X8632 --command FileCheck --check-prefix=OPTM1 %s | 
|  |  | 
|  | ; RUN: %if --need=target_X8664 --command %p2i --filetype=obj --disassemble \ | 
|  | ; RUN:   --target x8664 -i %s --args -O2 \ | 
|  | ; RUN:   | %if --need=target_X8664 --command FileCheck --check-prefix X8664 %s | 
|  | ; RUN: %if --need=allow_dump --need=target_X8664 --command %p2i --filetype=asm \ | 
|  | ; RUN:     --assemble --disassemble --target x8664 -i %s --args -O2 \ | 
|  | ; RUN:   | %if --need=allow_dump --need=target_X8664 \ | 
|  | ; RUN:     --command FileCheck --check-prefix=X8664 %s | 
|  | ; RUN: %if --need=target_X8664 --command %p2i --filetype=obj --disassemble \ | 
|  | ; RUN:   --target x8664 -i %s --args -Om1 \ | 
|  | ; RUN:   | %if --need=target_X8664 \ | 
|  | ; RUN:     --command FileCheck --check-prefix=X8664-OPTM1 %s | 
|  |  | 
|  | ; RUN: %if --need=target_ARM32 \ | 
|  | ; RUN:   --command %p2i --filetype=obj \ | 
|  | ; RUN:   --disassemble --target arm32 -i %s --args -O2 \ | 
|  | ; RUN:   | %if --need=target_ARM32 \ | 
|  | ; RUN:   --command FileCheck --check-prefix ARM32 %s | 
|  | ; RUN: %if --need=target_ARM32 \ | 
|  | ; RUN:   --command %p2i --filetype=obj \ | 
|  | ; RUN:   --disassemble --target arm32 -i %s --args -Om1 \ | 
|  | ; RUN:   | %if --need=target_ARM32_dump \ | 
|  | ; RUN:   --command FileCheck --check-prefix ARM32 %s | 
|  |  | 
|  | ; RUN: %if --need=target_MIPS32 --need=allow_dump \ | 
|  | ; RUN:   --command %p2i --filetype=asm --assemble --disassemble --target \ | 
|  | ; RUN:   mips32 -i %s --args -O2 -allow-externally-defined-symbols \ | 
|  | ; RUN:   | %if --need=target_MIPS32 --need=allow_dump \ | 
|  | ; RUN:   --command FileCheck --check-prefix MIPS32 %s | 
|  |  | 
|  | @__init_array_start = internal constant [0 x i8] zeroinitializer, align 4 | 
|  | @__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4 | 
|  | @__tls_template_start = internal constant [0 x i8] zeroinitializer, align 8 | 
|  | @__tls_template_alignment = internal constant [4 x i8] c"\01\00\00\00", align 4 | 
|  |  | 
|  | define internal void @CallIndirect(i32 %f) { | 
|  | entry: | 
|  | %__1 = inttoptr i32 %f to void ()* | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | ret void | 
|  | } | 
|  | ; CHECK-LABEL: CallIndirect | 
|  | ; Use the first call as a barrier in case the register allocator decides to use | 
|  | ; a scratch register for it but a common preserved register for the rest. | 
|  | ; CHECK: call | 
|  | ; CHECK: call [[REGISTER:[a-z]+]] | 
|  | ; CHECK: call [[REGISTER]] | 
|  | ; CHECK: call [[REGISTER]] | 
|  | ; CHECK: call [[REGISTER]] | 
|  | ; CHECK: call [[REGISTER]] | 
|  | ; | 
|  | ; OPTM1-LABEL: CallIndirect | 
|  | ; OPTM1: call [[TARGET:.+]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; | 
|  | ; X8664-LABEL: CallIndirect | 
|  | ; Use the first call as a barrier so we skip the movs in the function prolog. | 
|  | ; X8664: call r{{..}} | 
|  | ; X8664: mov e[[REG:..]], | 
|  | ; X8664-NEXT: call r[[REG]] | 
|  | ; X8664: mov e[[REG:..]], | 
|  | ; X8664-NEXT: call r[[REG]] | 
|  | ; X8664: mov e[[REG:..]], | 
|  | ; X8664-NEXT: call r[[REG]] | 
|  | ; X8664: call r{{..}} | 
|  | ; | 
|  | ; X8664-OPTM1-LABEL: CallIndirect | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; | 
|  | ; ARM32-LABEL: CallIndirect | 
|  | ; ARM32: blx [[REGISTER:r.*]] | 
|  | ; ARM32: blx [[REGISTER]] | 
|  | ; ARM32: blx [[REGISTER]] | 
|  | ; ARM32: blx [[REGISTER]] | 
|  | ; ARM32: blx [[REGISTER]] | 
|  |  | 
|  | ; MIPS32-LABEL: CallIndirect | 
|  | ; MIPS32: jalr	[[REGISTER:.*]] | 
|  | ; MIPS32: jalr	[[REGISTER]] | 
|  | ; MIPS32: jalr	[[REGISTER]] | 
|  | ; MIPS32: jalr	[[REGISTER]] | 
|  |  | 
|  | @fp_v = internal global [4 x i8] zeroinitializer, align 4 | 
|  |  | 
|  | define internal void @CallIndirectGlobal() { | 
|  | entry: | 
|  | %fp_ptr_i32 = bitcast [4 x i8]* @fp_v to i32* | 
|  | %fp_ptr = load i32, i32* %fp_ptr_i32, align 1 | 
|  | %fp = inttoptr i32 %fp_ptr to void ()* | 
|  | call void %fp() | 
|  | call void %fp() | 
|  | call void %fp() | 
|  | call void %fp() | 
|  | ret void | 
|  | } | 
|  | ; CHECK-LABEL: CallIndirectGlobal | 
|  | ; Allow the first call to be to a different register because of simple | 
|  | ; availability optimization. | 
|  | ; CHECK: call | 
|  | ; CHECK: call [[REGISTER:[a-z]+]] | 
|  | ; CHECK: call [[REGISTER]] | 
|  | ; CHECK: call [[REGISTER]] | 
|  | ; | 
|  | ; OPTM1-LABEL: CallIndirectGlobal | 
|  | ; OPTM1: call [[TARGET:.+]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; OPTM1: call [[TARGET]] | 
|  | ; | 
|  | ; X8664-LABEL: CallIndirectGlobal | 
|  | ; X8664: call r[[REG]] | 
|  | ; X8664: mov e[[REG:..]] | 
|  | ; X8664-NEXT: call r[[REG]] | 
|  | ; X8664: mov e[[REG:..]] | 
|  | ; X8664-NEXT: call r[[REG]] | 
|  | ; X8664: call r{{..}} | 
|  | ; | 
|  | ; X8664-OPTM1-LABEL: CallIndirectGlobal | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; X8664-OPTM1: mov e[[REG:..]],DWORD PTR | 
|  | ; X8664-OPTM1: call r[[REG]] | 
|  | ; | 
|  | ; ARM32-LABEL: CallIndirectGlobal | 
|  | ; ARM32: blx {{r.*}} | 
|  | ; ARM32: blx [[REGISTER:r[0-9]*]] | 
|  | ; ARM32: blx [[REGISTER]] | 
|  | ; ARM32: blx [[REGISTER]] | 
|  |  | 
|  | ; MIPS32-LABEL: CallIndirectGlobal | 
|  | ; MIPS32: jalr	[[REGISTER:.*]] | 
|  | ; MIPS32: jalr	[[REGISTER]] | 
|  | ; MIPS32: jalr	[[REGISTER]] | 
|  | ; MIPS32: jalr	[[REGISTER]] | 
|  |  | 
|  | ; Calling an absolute address is used for non-IRT PNaCl pexes to directly | 
|  | ; access syscall trampolines. This is not really an indirect call, but | 
|  | ; there is a cast from int to pointer first. | 
|  | define internal void @CallConst() { | 
|  | entry: | 
|  | %__1 = inttoptr i32 66496 to void ()* | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | call void %__1() | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; CHECK-LABEL: CallConst | 
|  | ; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* | 
|  | ; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* | 
|  | ; CHECK: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* | 
|  | ; | 
|  | ; OPTM1-LABEL: CallConst | 
|  | ; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* | 
|  | ; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* | 
|  | ; OPTM1: e8 bc 03 01 00 call {{[0-9a-f]+}} {{.*}} R_386_PC32 *ABS* | 
|  | ; | 
|  | ; X8664-LABEL: CallConst | 
|  | ; TODO(jpp): fix absolute call emission. | 
|  | ; These are broken: the emitted code should be | 
|  | ;    e8 00 00 00 00 call {{.*}} *ABS*+0x103bc | 
|  | ; | 
|  | ; X8664-OPTM1-LABEL: CallConst | 
|  | ; TODO(jpp): fix absolute call emission. | 
|  | ; These are broken: the emitted code should be | 
|  | ;    e8 00 00 00 00 call {{.*}} *ABS*+0x103bc | 
|  | ; | 
|  | ; ARM32-LABEL: CallConst | 
|  | ; ARM32: movw [[REGISTER:r.*]], #960 | 
|  | ; ARM32: movt [[REGISTER]], #1 | 
|  | ; ARM32: blx [[REGISTER]] | 
|  | ; The legalization of the constant could be shared, but it isn't. | 
|  | ; ARM32: movw [[REGISTER:r.*]], #960 | 
|  | ; ARM32: blx [[REGISTER]] | 
|  | ; ARM32: blx [[REGISTER]] |