• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -tailcallelim -verify-dom-info -S | grep call | count 4
2; PR4323
3
4; Several cases where tail call elimination should not move the load above the
5; call, and thus can't eliminate the tail recursion.
6
7
8@extern_weak_global = extern_weak global i32		; <i32*> [#uses=1]
9
10
11; This load can't be safely moved above the call because the load is from an
12; extern_weak global and may trap, but the call may unwind before that happens.
13define fastcc i32 @no_tailrecelim_1(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
14entry:
15	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
16	br i1 %tmp2, label %if, label %else
17
18if:		; preds = %entry
19	ret i32 37
20
21else:		; preds = %entry
22	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
23	%tmp8 = call fastcc i32 @no_tailrecelim_1(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
24	%tmp9 = load i32, i32* @extern_weak_global		; <i32> [#uses=1]
25	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
26	ret i32 %tmp10
27}
28
29
30; This load can't be safely moved above the call because function may write to the pointer.
31define fastcc i32 @no_tailrecelim_2(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind {
32entry:
33	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
34	br i1 %tmp2, label %if, label %else
35
36if:		; preds = %entry
37	store i32 1, i32* %a_arg
38        ret i32 0
39
40else:		; preds = %entry
41	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
42	%tmp8 = call fastcc i32 @no_tailrecelim_2(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
43	%tmp9 = load i32, i32* %a_arg		; <i32> [#uses=1]
44	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
45	ret i32 %tmp10
46}
47
48; This load can't be safely moved above the call because that would change the
49; order in which the load volatiles are performed.
50define fastcc i32 @no_tailrecelim_3(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind {
51entry:
52	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
53	br i1 %tmp2, label %if, label %else
54
55if:		; preds = %entry
56        ret i32 0
57
58else:		; preds = %entry
59	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
60	%tmp8 = call fastcc i32 @no_tailrecelim_3(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
61	%tmp9 = load volatile i32, i32* %a_arg		; <i32> [#uses=1]
62	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
63	ret i32 %tmp10
64}
65
66; This load can NOT be moved above the call because the a_arg is not
67; sufficiently dereferenceable.
68define fastcc i32 @no_tailrecelim_4(i32* dereferenceable(2) %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
69entry:
70	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
71	br i1 %tmp2, label %if, label %else
72
73if:		; preds = %entry
74	ret i32 0
75
76else:		; preds = %entry
77	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
78	%tmp8 = call fastcc i32 @no_tailrecelim_4(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
79	%tmp9 = load i32, i32* %a_arg		; <i32> [#uses=1]
80	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
81	ret i32 %tmp10
82}
83