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