aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/NaCl/expand-tls-constexpr.ll
blob: b7ab25369208b994227313322edd9dbedd0acec3 (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
; RUN: opt < %s -nacl-expand-tls-constant-expr -S | FileCheck %s

@tvar = thread_local global i32 0


define i32 @test_converting_ptrtoint() {
  ret i32 ptrtoint (i32* @tvar to i32)
}
; CHECK: define i32 @test_converting_ptrtoint()
; CHECK: %expanded = ptrtoint i32* @tvar to i32
; CHECK: ret i32 %expanded


define i32 @test_converting_add() {
  ret i32 add (i32 ptrtoint (i32* @tvar to i32), i32 4)
}
; CHECK: define i32 @test_converting_add()
; CHECK: %expanded1 = ptrtoint i32* @tvar to i32
; CHECK: %expanded = add i32 %expanded1, 4
; CHECK: ret i32 %expanded


define i32 @test_converting_multiple_operands() {
  ret i32 add (i32 ptrtoint (i32* @tvar to i32),
               i32 ptrtoint (i32* @tvar to i32))
}
; CHECK: define i32 @test_converting_multiple_operands()
; CHECK: %expanded1 = ptrtoint i32* @tvar to i32
; CHECK: %expanded = add i32 %expanded1, %expanded1
; CHECK: ret i32 %expanded


define i32 @test_allocating_new_var_name(i32 %expanded) {
  %result = add i32 %expanded, ptrtoint (i32* @tvar to i32)
  ret i32 %result
}
; CHECK: define i32 @test_allocating_new_var_name(i32 %expanded)
; CHECK: %expanded1 = ptrtoint i32* @tvar to i32
; CHECK: %result = add i32 %expanded, %expanded1
; CHECK: ret i32 %result


define i8* @test_converting_bitcast() {
  ret i8* bitcast (i32* @tvar to i8*)
}
; CHECK: define i8* @test_converting_bitcast()
; CHECK: %expanded = bitcast i32* @tvar to i8*
; CHECK: ret i8* %expanded


define i32* @test_converting_getelementptr() {
  ; Use an index >1 to ensure that "inbounds" is not added automatically.
  ret i32* getelementptr (i32* @tvar, i32 2)
}
; CHECK: define i32* @test_converting_getelementptr()
; CHECK: %expanded = getelementptr i32* @tvar, i32 2
; CHECK: ret i32* %expanded


; This is identical to @test_converting_getelementptr().
; We need to check that both copies of getelementptr are fixed.
define i32* @test_converting_getelementptr_copy() {
  ret i32* getelementptr (i32* @tvar, i32 2)
}
; CHECK: define i32* @test_converting_getelementptr_copy()
; CHECK: %expanded = getelementptr i32* @tvar, i32 2
; CHECK: ret i32* %expanded


define i32* @test_converting_getelementptr_inbounds() {
  ret i32* getelementptr inbounds (i32* @tvar, i32 2)
}
; CHECK: define i32* @test_converting_getelementptr_inbounds()
; CHECK: %expanded = getelementptr inbounds i32* @tvar, i32 2
; CHECK: ret i32* %expanded


define i32* @test_converting_phi(i1 %cmp) {
entry:
  br i1 %cmp, label %return, label %else

else:
  br label %return

return:
  %result = phi i32* [ getelementptr (i32* @tvar, i32 1), %entry ], [ null, %else ]
  ret i32* %result
}
; The converted ConstantExprs get pushed back into the PHI node's
; incoming block, which might be suboptimal but works in all cases.
; CHECK: define i32* @test_converting_phi(i1 %cmp)
; CHECK: entry:
; CHECK: %expanded = getelementptr inbounds i32* @tvar, i32 1
; CHECK: else:
; CHECK: return:
; CHECK: %result = phi i32* [ %expanded, %entry ], [ null, %else ]


@addr1 = global i8* blockaddress(@test_converting_phi_with_indirectbr, %return)
@addr2 = global i8* blockaddress(@test_converting_phi_with_indirectbr, %else)
define i32* @test_converting_phi_with_indirectbr(i8* %addr) {
entry:
  indirectbr i8* %addr, [ label %return, label %else ]

else:
  br label %return

return:
  %result = phi i32* [ getelementptr (i32* @tvar, i32 1), %entry ], [ null, %else ]
  ret i32* %result
}
; CHECK: define i32* @test_converting_phi_with_indirectbr(i8* %addr)
; CHECK: entry:
; CHECK: %expanded = getelementptr inbounds i32* @tvar, i32 1
; CHECK: return:
; CHECK: %result = phi i32* [ %expanded, %entry ], [ null, %else ]


; This tests that ExpandTlsConstantExpr correctly handles a PHI node
; that contains the same ConstantExpr twice.  Using
; replaceAllUsesWith() is not correct on a PHI node when the new
; instruction has to be added to an incoming block.
define i32 @test_converting_phi_twice(i1 %arg) {
  br i1 %arg, label %iftrue, label %iffalse
iftrue:
  br label %exit
iffalse:
  br label %exit
exit:
  %result = phi i32 [ ptrtoint (i32* @tvar to i32), %iftrue ],
                    [ ptrtoint (i32* @tvar to i32), %iffalse ]
  ret i32 %result
}
; CHECK: define i32 @test_converting_phi_twice(i1 %arg)
; CHECK: iftrue:
; CHECK: %expanded{{.*}} = ptrtoint i32* @tvar to i32
; CHECK: iffalse:
; CHECK: %expanded{{.*}} = ptrtoint i32* @tvar to i32
; CHECK: exit:
; CHECK: %result = phi i32 [ %expanded1, %iftrue ], [ %expanded, %iffalse ]


define i32 @test_converting_phi_multiple_entry(i1 %arg) {
entry:
  br i1 %arg, label %done, label %done
done:
  %result = phi i32 [ ptrtoint (i32* @tvar to i32), %entry ],
                    [ ptrtoint (i32* @tvar to i32), %entry ]
  ret i32 %result
}
; CHECK: define i32 @test_converting_phi_multiple_entry(i1 %arg)
; CHECK: %result = phi i32 [ %expanded, %entry ], [ %expanded, %entry ]