1; RUN: llc -mtriple x86_64-apple-darwin -O0 < %s -o - | FileCheck %s 2; 3; During X86 fastisel, the address of indirect call was resolved 4; through bitcast, ptrtoint, and inttoptr instructions. This is valid 5; only if the related instructions are in that same basic block, otherwise 6; we may reference variables that were not live across basic blocks 7; resulting in undefined virtual registers. 8; 9; In this example, this is illustrated by a spill/reload of the 10; LOADED_PTR_SLOT. 11; 12; Before this patch, the compiler was accessing two different spill 13; slots. 14; <rdar://problem/15192473> 15 16; CHECK-LABEL: @test_bitcast 17; Load the value of the function pointer: %loaded_ptr 18; CHECK: movq (%rdi), [[LOADED_PTR:%[a-z]+]] 19; Spill %arg2. 20; CHECK: movq %rdx, [[ARG2_SLOT:[0-9]*\(%[a-z]+\)]] 21; Spill %loaded_ptr. 22; CHECK: movq [[LOADED_PTR]], [[LOADED_PTR_SLOT:[0-9]*\(%[a-z]+\)]] 23; Perform the indirect call. 24; Load the first argument 25; CHECK: movq [[ARG2_SLOT]], %rdi 26; Load the second argument 27; CHECK: movq [[ARG2_SLOT]], %rsi 28; Load the third argument 29; CHECK: movq [[ARG2_SLOT]], %rdx 30; Load the function pointer. 31; CHECK: movq [[LOADED_PTR_SLOT]], [[FCT_PTR:%[a-z]+]] 32; Call. 33; CHECK: callq *[[FCT_PTR]] 34; CHECK: ret 35define i64 @test_bitcast(i64 (i64, i64, i64)** %arg, i1 %bool, i64 %arg2) { 36entry: 37 %loaded_ptr = load i64 (i64, i64, i64)*, i64 (i64, i64, i64)** %arg, align 8 38 %raw = bitcast i64 (i64, i64, i64)* %loaded_ptr to i8* 39 switch i1 %bool, label %default [ 40 i1 true, label %label_true 41 i1 false, label %label_end 42 ] 43default: 44 br label %label_end 45 46label_true: 47 br label %label_end 48 49label_end: 50 %fct_ptr = bitcast i8* %raw to i64 (i64, i64, i64)* 51 %res = call i64 %fct_ptr(i64 %arg2, i64 %arg2, i64 %arg2) 52 ret i64 %res 53} 54 55; CHECK-LABEL: @test_inttoptr 56; Load the value of the function pointer: %loaded_ptr 57; CHECK: movq (%rdi), [[LOADED_PTR:%[a-z]+]] 58; Spill %arg2. 59; CHECK: movq %rdx, [[ARG2_SLOT:[0-9]*\(%[a-z]+\)]] 60; Spill %loaded_ptr. 61; CHECK: movq [[LOADED_PTR]], [[LOADED_PTR_SLOT:[0-9]*\(%[a-z]+\)]] 62; Perform the indirect call. 63; Load the first argument 64; CHECK: movq [[ARG2_SLOT]], %rdi 65; Load the second argument 66; CHECK: movq [[ARG2_SLOT]], %rsi 67; Load the third argument 68; CHECK: movq [[ARG2_SLOT]], %rdx 69; Load the function pointer. 70; CHECK: movq [[LOADED_PTR_SLOT]], [[FCT_PTR:%[a-z]+]] 71; Call. 72; CHECK: callq *[[FCT_PTR]] 73; CHECK: ret 74define i64 @test_inttoptr(i64 (i64, i64, i64)** %arg, i1 %bool, i64 %arg2) { 75entry: 76 %loaded_ptr = load i64 (i64, i64, i64)*, i64 (i64, i64, i64)** %arg, align 8 77 %raw = ptrtoint i64 (i64, i64, i64)* %loaded_ptr to i64 78 switch i1 %bool, label %default [ 79 i1 true, label %label_true 80 i1 false, label %label_end 81 ] 82default: 83 br label %label_end 84 85label_true: 86 br label %label_end 87 88label_end: 89 %fct_ptr = inttoptr i64 %raw to i64 (i64, i64, i64)* 90 %res = call i64 %fct_ptr(i64 %arg2, i64 %arg2, i64 %arg2) 91 ret i64 %res 92} 93 94; CHECK-LABEL: @test_ptrtoint 95; Load the value of the function pointer: %loaded_ptr 96; CHECK: movq (%rdi), [[LOADED_PTR:%[a-z]+]] 97; Spill %arg2. 98; CHECK: movq %rdx, [[ARG2_SLOT:[0-9]*\(%[a-z]+\)]] 99; Spill %loaded_ptr. 100; CHECK: movq [[LOADED_PTR]], [[LOADED_PTR_SLOT:[0-9]*\(%[a-z]+\)]] 101; Perform the indirect call. 102; Load the first argument 103; CHECK: movq [[ARG2_SLOT]], %rdi 104; Load the second argument 105; CHECK: movq [[ARG2_SLOT]], %rsi 106; Load the third argument 107; CHECK: movq [[ARG2_SLOT]], %rdx 108; Load the function pointer. 109; CHECK: movq [[LOADED_PTR_SLOT]], [[FCT_PTR:%[a-z]+]] 110; Call. 111; CHECK: callq *[[FCT_PTR]] 112; CHECK: ret 113define i64 @test_ptrtoint(i64 (i64, i64, i64)** %arg, i1 %bool, i64 %arg2) { 114entry: 115 %loaded_ptr = load i64 (i64, i64, i64)*, i64 (i64, i64, i64)** %arg, align 8 116 %raw = bitcast i64 (i64, i64, i64)* %loaded_ptr to i8* 117 switch i1 %bool, label %default [ 118 i1 true, label %label_true 119 i1 false, label %label_end 120 ] 121default: 122 br label %label_end 123 124label_true: 125 br label %label_end 126 127label_end: 128 %fct_int = ptrtoint i8* %raw to i64 129 %fct_ptr = inttoptr i64 %fct_int to i64 (i64, i64, i64)* 130 %res = call i64 %fct_ptr(i64 %arg2, i64 %arg2, i64 %arg2) 131 ret i64 %res 132} 133