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 35 define i64 @test_bitcast(i64 (i64, i64, i64)** %arg, i1 %bool, i64 %arg2) { 36 entry: 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 ] 43 default: 44 br label %label_end 45 46 label_true: 47 br label %label_end 48 49 label_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 74 define i64 @test_inttoptr(i64 (i64, i64, i64)** %arg, i1 %bool, i64 %arg2) { 75 entry: 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 ] 82 default: 83 br label %label_end 84 85 label_true: 86 br label %label_end 87 88 label_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 113 define i64 @test_ptrtoint(i64 (i64, i64, i64)** %arg, i1 %bool, i64 %arg2) { 114 entry: 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 ] 121 default: 122 br label %label_end 123 124 label_true: 125 br label %label_end 126 127 label_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