forked from OSchip/llvm-project
126 lines
4.9 KiB
LLVM
126 lines
4.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=tailcallelim -verify-dom-info -S | FileCheck %s
|
|
|
|
; This test checks that TRE would be done for only one recursive call.
|
|
; The test_multiple_exits function has three recursive calls.
|
|
; First recursive call could not be eliminated because there is
|
|
; escaped pointer to local variable. Second recursive call could
|
|
; be eliminated. Thrid recursive call could not be eliminated since
|
|
; this is not last call. Thus, test checks that TRE would be done
|
|
; for only second recursive call.
|
|
|
|
; IR for that test was generated from the following C++ source:
|
|
;
|
|
; void capture_arg (int*);
|
|
; void test_multiple_exits (int param);
|
|
; if (param >= 0 && param < 10) {
|
|
; int temp;
|
|
; capture_arg(&temp);
|
|
; // TRE could not be done because pointer to local
|
|
; // variable "temp" is escaped.
|
|
; test_multiple_exits(param + 1);
|
|
; } else if (param >=10 && param < 20) {
|
|
; // TRE should be done.
|
|
; test_multiple_exits(param + 1);
|
|
; } else if (param >= 20 && param < 22) {
|
|
; // TRE could not be done since recursive
|
|
; // call is not last call.
|
|
; test_multiple_exits(param + 1);
|
|
; func();
|
|
; }
|
|
;
|
|
; return;
|
|
; }
|
|
|
|
; Function Attrs: noinline optnone uwtable
|
|
declare void @_Z11capture_argPi(i32* %param) #0
|
|
|
|
; Function Attrs: noinline optnone uwtable
|
|
declare void @_Z4funcv() #0
|
|
|
|
; Function Attrs: noinline nounwind uwtable
|
|
define dso_local void @_Z19test_multiple_exitsi(i32 %param) local_unnamed_addr #2 {
|
|
; CHECK-LABEL: @_Z19test_multiple_exitsi(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TEMP:%.*]] = alloca i32, align 4
|
|
; CHECK-NEXT: br label [[TAILRECURSE:%.*]]
|
|
; CHECK: tailrecurse:
|
|
; CHECK-NEXT: [[PARAM_TR:%.*]] = phi i32 [ [[PARAM:%.*]], [[ENTRY:%.*]] ], [ [[ADD6:%.*]], [[IF_THEN5:%.*]] ]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[PARAM_TR]], 10
|
|
; CHECK-NEXT: br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TEMP]] to i8*
|
|
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP1]]) #1
|
|
; CHECK-NEXT: call void @_Z11capture_argPi(i32* nonnull [[TEMP]])
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[PARAM_TR]], 1
|
|
; CHECK-NEXT: call void @_Z19test_multiple_exitsi(i32 [[ADD]])
|
|
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP1]]) #1
|
|
; CHECK-NEXT: br label [[IF_END14:%.*]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: [[PARAM_OFF:%.*]] = add i32 [[PARAM_TR]], -10
|
|
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[PARAM_OFF]], 10
|
|
; CHECK-NEXT: br i1 [[TMP2]], label [[IF_THEN5]], label [[IF_ELSE7:%.*]]
|
|
; CHECK: if.then5:
|
|
; CHECK-NEXT: [[ADD6]] = add nuw nsw i32 [[PARAM_TR]], 1
|
|
; CHECK-NEXT: br label [[TAILRECURSE]]
|
|
; CHECK: if.else7:
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[PARAM_TR]], -2
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 20
|
|
; CHECK-NEXT: br i1 [[TMP4]], label [[IF_THEN11:%.*]], label [[IF_END14]]
|
|
; CHECK: if.then11:
|
|
; CHECK-NEXT: [[ADD12:%.*]] = add nsw i32 [[PARAM_TR]], 1
|
|
; CHECK-NEXT: tail call void @_Z19test_multiple_exitsi(i32 [[ADD12]])
|
|
; CHECK-NEXT: tail call void @_Z4funcv()
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: if.end14:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%temp = alloca i32, align 4
|
|
%0 = icmp ult i32 %param, 10
|
|
br i1 %0, label %if.then, label %if.else
|
|
|
|
if.then: ; preds = %entry
|
|
%1 = bitcast i32* %temp to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %1) #2
|
|
call void @_Z11capture_argPi(i32* nonnull %temp)
|
|
%add = add nuw nsw i32 %param, 1
|
|
call void @_Z19test_multiple_exitsi(i32 %add)
|
|
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1) #2
|
|
br label %if.end14
|
|
|
|
if.else: ; preds = %entry
|
|
%param.off = add i32 %param, -10
|
|
%2 = icmp ult i32 %param.off, 10
|
|
br i1 %2, label %if.then5, label %if.else7
|
|
|
|
if.then5: ; preds = %if.else
|
|
%add6 = add nuw nsw i32 %param, 1
|
|
call void @_Z19test_multiple_exitsi(i32 %add6)
|
|
br label %if.end14
|
|
|
|
if.else7: ; preds = %if.else
|
|
%3 = and i32 %param, -2
|
|
%4 = icmp eq i32 %3, 20
|
|
br i1 %4, label %if.then11, label %if.end14
|
|
|
|
if.then11: ; preds = %if.else7
|
|
%add12 = add nsw i32 %param, 1
|
|
call void @_Z19test_multiple_exitsi(i32 %add12)
|
|
call void @_Z4funcv()
|
|
br label %if.end14
|
|
|
|
if.end14: ; preds = %if.then5, %if.then11, %if.else7, %if.then
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs: argmemonly nounwind willreturn
|
|
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2
|
|
|
|
; Function Attrs: argmemonly nounwind willreturn
|
|
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2
|
|
|
|
attributes #0 = { nofree noinline norecurse nounwind uwtable }
|
|
attributes #1 = { nounwind uwtable }
|
|
attributes #2 = { argmemonly nounwind willreturn }
|