aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGen/X86/conditional-tailcall.ll
blob: c00ce75b26decc5e10e553afe3c09b6c43a90e9f (plain) (blame)
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
153
154
155
156
157
158
159
160
161
162
163
; RUN: llc < %s -mtriple=i686-linux   -show-mc-encoding | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK32
; RUN: llc < %s -mtriple=x86_64-linux -show-mc-encoding | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK64
; RUN: llc < %s -mtriple=x86_64-win32 -show-mc-encoding | FileCheck %s --check-prefix=CHECK --check-prefix=WIN64

declare void @foo()
declare void @bar()

define void @f(i32 %x, i32 %y) optsize {
entry:
	%p = icmp eq i32 %x, %y
  br i1 %p, label %bb1, label %bb2
bb1:
  tail call void @foo()
  ret void
bb2:
  tail call void @bar()
  ret void

; CHECK-LABEL: f:
; CHECK: cmp
; CHECK: jne bar
; Check that the asm doesn't just look good, but uses the correct encoding.
; CHECK: encoding: [0x75,A]
; CHECK: jmp foo
}

define void @f_non_leaf(i32 %x, i32 %y) optsize {
entry:
  ; Force %ebx to be spilled on the stack, turning this into
  ; not a "leaf" function for Win64.
  tail call void asm sideeffect "", "~{ebx}"()

	%p = icmp eq i32 %x, %y
  br i1 %p, label %bb1, label %bb2
bb1:
  tail call void @foo()
  ret void
bb2:
  tail call void @bar()
  ret void

; CHECK-LABEL: f_non_leaf:
; WIN64-NOT: je foo
; WIN64-NOT: jne bar
; WIN64: jne
; WIN64: jmp foo
; WIN64: jmp bar
}

declare x86_thiscallcc zeroext i1 @baz(i8*, i32)
define x86_thiscallcc zeroext i1 @BlockPlacementTest(i8* %this, i32 %x) optsize {
entry:
  %and = and i32 %x, 42
  %tobool = icmp eq i32 %and, 0
  br i1 %tobool, label %land.end, label %land.rhs

land.rhs:
  %and6 = and i32 %x, 44
  %tobool7 = icmp eq i32 %and6, 0
  br i1 %tobool7, label %lor.rhs, label %land.end

lor.rhs:
  %call = tail call x86_thiscallcc zeroext i1 @baz(i8* %this, i32 %x) #2
  br label %land.end

land.end:
  %0 = phi i1 [ false, %entry ], [ true, %land.rhs ], [ %call, %lor.rhs ]
  ret i1 %0

; Make sure machine block placement isn't confused by the conditional tail call,
; but sees that it can fall through to the next block.
; CHECK-LABEL: BlockPlacementTest
; CHECK: je baz
; CHECK-NOT: xor
; CHECK: ret
}



%"class.std::basic_string" = type { %"struct.std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider" }
%"struct.std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider" = type { i8* }
declare zeroext i1 @_Z20isValidIntegerSuffixN9__gnu_cxx17__normal_iteratorIPKcSsEES3_(i8*, i8*)

define zeroext i1 @pr31257(%"class.std::basic_string"* nocapture readonly dereferenceable(8) %s) minsize {
; CHECK-LABEL: pr31257
entry:
  %_M_p.i.i = getelementptr inbounds %"class.std::basic_string", %"class.std::basic_string"* %s, i64 0, i32 0, i32 0
  %0 = load i8*, i8** %_M_p.i.i, align 8
  %arrayidx.i.i.i54 = getelementptr inbounds i8, i8* %0, i64 -24
  %_M_length.i.i55 = bitcast i8* %arrayidx.i.i.i54 to i64*
  %1 = load i64, i64* %_M_length.i.i55, align 8
  %add.ptr.i56 = getelementptr inbounds i8, i8* %0, i64 %1
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %entry
  %it.sroa.0.0 = phi i8* [ %0, %entry ], [ %incdec.ptr.i, %for.inc ]
  %state.0 = phi i32 [ 0, %entry ], [ %state.1, %for.inc ]
  %cmp.i = icmp eq i8* %it.sroa.0.0, %add.ptr.i56
  br i1 %cmp.i, label %5, label %for.body

for.body:                                         ; preds = %for.cond
  switch i32 %state.0, label %for.inc [
    i32 0, label %sw.bb
    i32 1, label %sw.bb14
    i32 2, label %sw.bb22
  ]

sw.bb:                                            ; preds = %for.body
  %2 = load i8, i8* %it.sroa.0.0, align 1
  switch i8 %2, label %if.else [
    i8 43, label %for.inc
    i8 45, label %for.inc
  ]

if.else:                                          ; preds = %sw.bb
  %conv9 = zext i8 %2 to i32
  %isdigittmp45 = add nsw i32 %conv9, -48
  %isdigit46 = icmp ult i32 %isdigittmp45, 10
  br i1 %isdigit46, label %for.inc, label %cleanup.thread.loopexit

sw.bb14:                                          ; preds = %for.body
  %3 = load i8, i8* %it.sroa.0.0, align 1
  %conv16 = zext i8 %3 to i32
  %isdigittmp43 = add nsw i32 %conv16, -48
  %isdigit44 = icmp ult i32 %isdigittmp43, 10
  br i1 %isdigit44, label %for.inc, label %cleanup.thread.loopexit

sw.bb22:                                          ; preds = %for.body
  %4 = load i8, i8* %it.sroa.0.0, align 1
  %conv24 = zext i8 %4 to i32
  %isdigittmp = add nsw i32 %conv24, -48
  %isdigit = icmp ult i32 %isdigittmp, 10
  br i1 %isdigit, label %for.inc, label %if.else28

; Make sure Machine Copy Propagation doesn't delete the mov to %ecx becaue it
; thinks the conditional tail call clobbers it.
; CHECK64-LABEL: .LBB3_11:
; CHECK64:       movzbl  (%rdi), %ecx
; CHECK64-NEXT:  addl    $-48, %ecx
; CHECK64-NEXT:  cmpl    $10, %ecx
; CHECK64-NEXT:  movl    %r9d, %ecx
; CHECK64-NEXT:  jae     _Z20isValidIntegerSuffixN9__gnu_cxx17__normal_iteratorIPKcSsEE

if.else28:                                        ; preds = %sw.bb22
  %call34 = tail call zeroext i1 @_Z20isValidIntegerSuffixN9__gnu_cxx17__normal_iteratorIPKcSsEES3_(i8* nonnull %it.sroa.0.0, i8* %add.ptr.i56)
  br label %cleanup.thread

for.inc:                                          ; preds = %sw.bb, %sw.bb, %sw.bb22, %sw.bb14, %if.else, %for.body
  %state.1 = phi i32 [ %state.0, %for.body ], [ 1, %sw.bb ], [ 2, %if.else ], [ 2, %sw.bb14 ], [ 2, %sw.bb22 ], [ 1, %sw.bb ]
  %incdec.ptr.i = getelementptr inbounds i8, i8* %it.sroa.0.0, i64 1
  br label %for.cond

; <label>:5:                                      ; preds = %for.cond
  %cmp37 = icmp eq i32 %state.0, 2
  br label %cleanup.thread

cleanup.thread.loopexit:                          ; preds = %if.else, %sw.bb14
  br label %cleanup.thread

cleanup.thread:                                   ; preds = %cleanup.thread.loopexit, %if.else28, %5
  %6 = phi i1 [ %cmp37, %5 ], [ %call34, %if.else28 ], [ false, %cleanup.thread.loopexit ]
  ret i1 %6
}