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