83 lines · plain
1; RUN: opt < %s -passes=tailcallelim -verify-dom-info -S | grep call | count 42; PR43233 4; Several cases where tail call elimination should not move the load above the5; call, and thus can't eliminate the tail recursion.6 7 8@extern_weak_global = extern_weak global i32 ; <ptr> [#uses=1]9 10 11; This load can't be safely moved above the call because the load is from an12; extern_weak global and may trap, but the call may unwind before that happens.13define fastcc i32 @no_tailrecelim_1(ptr %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 %else17 18if: ; preds = %entry19 ret i32 3720 21else: ; preds = %entry22 %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]23 %tmp8 = call fastcc i32 @no_tailrecelim_1(ptr %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1]24 %tmp9 = load i32, ptr @extern_weak_global ; <i32> [#uses=1]25 %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]26 ret i32 %tmp1027}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(ptr %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 %else35 36if: ; preds = %entry37 store i32 1, ptr %a_arg38 ret i32 039 40else: ; preds = %entry41 %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]42 %tmp8 = call fastcc i32 @no_tailrecelim_2(ptr %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1]43 %tmp9 = load i32, ptr %a_arg ; <i32> [#uses=1]44 %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]45 ret i32 %tmp1046}47 48; This load can't be safely moved above the call because that would change the49; order in which the load volatiles are performed.50define fastcc i32 @no_tailrecelim_3(ptr %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 %else54 55if: ; preds = %entry56 ret i32 057 58else: ; preds = %entry59 %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]60 %tmp8 = call fastcc i32 @no_tailrecelim_3(ptr %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1]61 %tmp9 = load volatile i32, ptr %a_arg ; <i32> [#uses=1]62 %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]63 ret i32 %tmp1064}65 66; This load can NOT be moved above the call because the a_arg is not67; sufficiently dereferenceable.68define fastcc i32 @no_tailrecelim_4(ptr 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 %else72 73if: ; preds = %entry74 ret i32 075 76else: ; preds = %entry77 %tmp7 = add i32 %start_arg, 1 ; <i32> [#uses=1]78 %tmp8 = call fastcc i32 @no_tailrecelim_4(ptr %a_arg, i32 %a_len_arg, i32 %tmp7) ; <i32> [#uses=1]79 %tmp9 = load i32, ptr %a_arg ; <i32> [#uses=1]80 %tmp10 = add i32 %tmp9, %tmp8 ; <i32> [#uses=1]81 ret i32 %tmp1082}83